objective-c 语法快速过(4)

oc 里的字符串

字符串的快速创建(最简单的方法)

NSStirng *str = @“Hello”;//oc的字符串都是@“”形式的

oc的字符串也是类的对象,是NSString类的对象,创建没有那么麻烦不用[ ],使用面向对象的思想来操纵字符串。

 char *name = "xxxxx";//c风格字符串

oc使用 %@ 输出字符串,不是%s

NSString *name = @”dashuai”;

NSLog(@“我的名字是%@”,  name);

c 风格字符串输出解析的用法是%s

NSLog(@"%s", name);//%s是c风格的格式化解析

OC字符串的另一方式,Foundation 框架里的 NSString 类

NSString *newStr = [NSString stringWithFormat:@"My age is %d and no is %d and name is %@", age, no, name];

NSLog(@"---- %ld", [newStr length]); 
length方法,返回unsigned long类型
 NSString *name = @"哈哈达到";
// length方法算的是字数总数,包含的文字的数目!不是求字符个数!!
int size = [name length];

不懂就去查询文档!百度!

//  main.m
#import <Foundation/Foundation.h>
/*
 NSString : 不可变字符串
 NSMutableString : 可变字符串
 */
int main()
{
    NSMutableString *s1 = [NSMutableString stringWithFormat:@"my age is 10"];
    // 拼接内容到s1的后面
    [s1 appendString:@" 11 12"];

    // 获取is的范围
    NSRange range = [s1 rangeOfString:@"is"];
    [s1 deleteCharactersInRange:range];

    NSString *s2 = [NSString stringWithFormat:@"age is 10"];

   //新建字符串,拼接好的字符串到新建的字符串里,但是原来的字符串没有变!两个方法不一样。
    NSString *s3 = [s2 stringByAppendingString:@" 11 12"];
    NSLog(@"s1=%@, s2=%@", s1, s2);

    return 0;
}

void stringExport()
{
    // 字符串的导出
    [@"Jack\nJack" writeToFile:@"/Users/apple/Desktop/my.txt" atomically:YES encoding:NSUTF8StringEncoding error:nil];

    NSString *str = @"4234234";

    NSURL *url = [NSURL fileURLWithPath:@"/Users/apple/Desktop/my2.txt"];

    [str writeToURL:url atomically:YES encoding:NSUTF8StringEncoding error:nil];
}

void stringCreate()
{
    /*
     1.字符串的创建
     */
    NSString *s1 = @"jack";

    //NSString *s2 = [[NSString alloc] initWithString:@"jack"];这种方法不推荐!

    NSString *s3 = [[NSString alloc] initWithFormat:@"age is %d", 10];

    // C字符串 --> OC字符串
    NSString *s4 = [[NSString alloc] initWithUTF8String:"jack"];
    // OC字符串 --> C字符串
    const char *cs = [s4 UTF8String];

    // NSUTF8StringEncoding 用到中文就可以用这种编码
    NSString *s5 = [[NSString alloc] initWithContentsOfFile:@"/Users/apple/Desktop/1.txt" encoding:NSUTF8StringEncoding error:nil];

    // URL : 资源路径
    // 协议头://路径
    // 本地文件   file://
    // ftp://
    // 网页资源 http://weibo.com/a.png
    // http://www.baidu.com

    // NSURL *url = [[NSURL alloc] initWithString:@"file:///Users/apple/Desktop/1.txt"];
    NSURL *url = [NSURL fileURLWithPath:@"/Users/apple/Desktop/1.txt"];

    NSString *s6 = [[NSString alloc] initWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];
    NSLog(@"s6=\n%@", s6);

    /*
     一般都会有一个类方法跟对象方法配对
     [NSURL URLWithString:<#(NSString *)#>];
     [NSString stringWithFormat:@""];
     [NSString stringWithContentsOfFile:<#(NSString *)#> encoding:<#(NSStringEncoding)#> error:<#(NSError *__autoreleasing *)#>];
     */
}

OC的 set 和 get 方法

类的成员变量尽量不要@public,保持数据的隐蔽性和封装性,使用对象直接访问类的成员变量也不推荐,因为这样类的成员变量可以被随意的修改,不安全,而是应该间接的调用。并且直接调用会让别人一下子就看到了类的内部结构和信息,失去了封装的意义。

set方法

1)   作用:用来设置成员变量,可以在方法里面过滤掉一些不合理的值

2)   命名规范:

  • 方法名都是以set开头,而且后面跟上成员变量名,成员变量名的首字母必须大写
  • 一定接受参数,且形参名称不要跟成员变量同名
  • 返回值void

get方法

1)   作用:返回对象内部的成员变量

2)   命名规范:get方法的名称一般就跟成员变量同名

/*成员变量的命名规范:一定要以下划线 _ 开头
@interface Student : NSObject
{
  1.让成员变量和get方法的名称区分开
  2.可以跟局部变量区分开,一看到下划线开头的变量,一般都是成员变量
  */
    int _no;
    Sex _sex;
}
// sex的set和get方法
- (void)setSex:(Sex)sex;
- (Sex)sex;
// no的set和get方法
- (void)setNo:(int)no;
- (int)no;
@end

oc特有的语法—兼容c系列的点语法

可以使用点语法来代替oc古怪的对象调用的形式。这是oc特有的让其他(主要是习惯了 c 系列编程语言的程序员,比如 c,c++,java等)程序员快速看懂的一个做法。

 // 点语法的本质还是方法调用
    p.age = 10; // [p setAge:10];

这里还是古怪,到底是get还是set方法,要看是给它赋值了(set),还是被赋值了(get)。还是和java或c++的点语法区分。

oc 中类的成员变量的作用于

@public : 在任何地方都能直接访问对象的成员变量

@private : 只能在当前类的对象方法中直接访问。私有成员只能在本类被直接访问,子类不可见,只能是set和get方法访问(@implementation中默认是@private,因为一般不会包含实现文件,都是包含头文件,故实现文件默认是私有的)

@protected : 可以在当前类及其子类的对象方法中直接访问  (@interface中默认就是@protected)

@package : 只要处在同一个框架中,就能直接访问对象的成员变量,不常用

@interface和@implementation中不能声明同名的成员变量,同名冲突,很好理解

Xcode的一个特性@property和@synthesize

s?nθ??sa?z v综合合成;(通过化学或生物)合成;(音响)合成

@property

自动生成set和get方法,类似java的eclipse的 setter 和 getter选项

#import <Foundation/Foundation.h>
@interface Person : NSObject
{
    int _age;
    int _height;
    double _weight;
    NSString *_name;
}
// @property:只能用在声明里,可以自动生成某个成员变量的setter和getter声明,并且和java还不一样,xcode把自动的声明隐藏,不可见。这是编译器的特性!
下面这一句,代表注释的那两句。
@property int age;
//- (void)setAge:(int)age;
//- (int)age;
@property int height;//先生成set再get
//- (void)setHeight:(int)height;
//- (int)height;
- (void)test;
@property double weight;
//如果成员变量类型一样,可以合并在一起写,但是实际开发不这样,分开比较好
@property NSString *name;
@end

注意:@property里的变量age如果没有被提前声明,那么也是可以运行的,编译器会自动生成_age成员变量,xcode4.4版本之后有的。这样生成的成员变量,在类声明里是@private。若类声明里存此成员变量,如果@property还是那么写,就不会再自动生成。

@synthesize

只写在实现里。可以自动去类声明里找@property,然后根据它去生成类的成员变量的setter和getter方法的实现,并且会访问这个成员变量

@synthesize age = _age;

如果这样写,默认会访问age这个成员变量,如果没有age,就会自动生成@private类型的age变量,都是自动存在类声明里。

注意:xcode4.4之后,为了让程序员把精力放在业务逻辑上,而不是无谓的垃圾代码的书写上,xcode变得越来越方便,做的东西也越多,现在可以省略类的成员变量的声明,直接@property就可以自动生成变量和配套的set与get方法的声明。同样,4.4之后,类的实现里,@synthesize也不用写了。也就是说,set和get的实现不用写。

意味着,现在的@property 声明,类声明里的@property默认做两个事情,即生成set和get的声明,也生成set和get的实现。当然,如果类声明里没有变量声明,那么还要做第三个事情,自动生成私有的成员变量。

Xcode原则就是:没有,我替你生成,有我就直接用。

这里就可以解释为什么苹果建议类的成员变量前面加下划线?

因为@property 的新特性:自从 xcode4.4之后,@property 就独揽了@synthesize 的功能,也就说,@proeprty 可以同时生成成员变量的 set,get 方法的声明和实现,两个都能。默认的情况下,set 和 get 方法的实现,会去访问下划线的成员变量,故要求类的声明里使用下划线的变量命名方式命名成员变量。说到底:就是因为新特性的@property自动生成set,get方法的声明和实现,默认访问的都是前面带下划线的成员变量。

oc 里的 id 类型(万能指针)

id 是一种类型

类型不能做变量名,好比 int  int;是错误的,一个道理。

Id 是万能指针

能指向(操纵)任何的 oc 对象,而且不能加*,只写id就代表指针(因为 id内部已经包含*,见官方文档)。

 Person *p = [Person new];//传统的操作人的对象,人类型指针p 指向人的对象

万能指针,id能指向 or 操作任何OC对象,只适合用在 oc 对象上

id d = [Person new];//id 指向人的对象      

id 的缺点:

如果同样是指向(调用)类不存在的对象方法,那么编译器直接报错!不会弱语法了

千万别加*

oc 的构造方法和重写

构造方法:用来初始化对象的方法,oc里是个对象方法,-开头  -init

面向对象的语言,都包含的东西---构造方法,用和 c++类似的new 这个类方法创建对象,其实不好。

// Person *p = [Person new];不推荐这样创建对象

new 其实是类方法,是 NSObject 类的方法,可以创建对象,分配内存,但是事实上,我们不常用,因为太死板,做的事情很单调,就是完整的创建一可用对象。

完整地创建一个可用的对象其实分两步:

1.分配存储空间  +alloc

2.初始化 -init

new 方法做这两个事情,new 方法内部,调用两个方法(一个类方法,一个对象方法)完成这个步骤,细节为:

1.调用+alloc分配存储空间

Person *p1 = [Person alloc];//此时对象不可用,没有初始化,返回 id(oc 对象)

2.调用-init进行初始化

Person *p2 = [p1 init];反回 oc 对象(已经初始化之后)本身

说明 new 是两个方法的联合,开发不常用,比较死板,一般分两步做,这样后果是方便选择。因为初始化不一定必须是 init对象方法初始化。。

两步合并的简单写法:掌握,开发常用这个写法,从此不用 new 了。

Person *p4 = [[Person alloc] init];

Oc的构造方法就是-init 方法,用来初始化对象的方法。对象方法,每个对象内部的成员变量默认都初始化为0,

创建 person 对象,保证她的_age 默认都是10,不是0,怎么做?

需要重写 –init方法,覆盖父类 –init方法

重写构造方法的目的:

为了让对象创建出来,成员变量就会有一些固定的值

重写构造方法的注意点

1.先调用父类的构造方法([super init])

2.再进行子类内部成员变量的初始化,和 c++类似。

Person.h
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property int age;
@end

Person.m
#import "Person.h"
@implementation Person
// 重写-init方法,其实 id 有些类似 c++的模板的应用。
//- (id)init
//{
//    1、一定要先调用super的init方法:先初始化父类中声明的一些成员变量和其他属性
     self = [super init]; // 返回的是当前oc对象,一定用 self接受,这里需要好好研究,先知道。
//    2.如果父类对象初始化成功,才有必要进行接下来的初始化
//    if (self != nil)
//    {
//        _age = 10;
//    }
//
//    3.返回一个已经初始化完毕的oc对象
//    return self;
//}
//综合的写法,熟练之后如下这样写:
- (id)init
{
    if ( self = [super init] )
    {
        _age = 10;
    }
    return self;
}
@end

要求:

学生类的学生对象,初始化完毕之后,年龄都是10,学号都是1.还是重写构造方法-init

Student.h继承 person 类
#import "Person.h"
@interface Student : Person
@property int no;
@end

Student.m
#import "Student.h"
@implementation Student
// 学生对象初始化完毕后,年龄就是10,学号就是1
- (id)init
{
    if ( self = [super init] )
    {
        _no = 1;
    }
    return self;
}
@end

main.h
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Student.h"
int main()
{  // 每个stu对象创建出来,他的_age都是10,学生学号都是1,isa 指向本身
每个 p4对象创建出来,她的 _age 都是10,isa 指向本身类
    Person *p4 = [[Person alloc] init];
    Student *stu = [[Student alloc] init];
    return 0;
}

student 继承了 person ,而 person继承了 NSObject,比如 student 对象内部有三个成员变量,分别为: student 自己的_no,和继承自父类 person 类的_age,还有 person 最开始就继承的父类NSObject 的 isa指针,这个三个成员变量,都是 student 对象 stu 包含的!

因为student 类 创建 student 对象的时候,先进入 student 类查找-init,(因为 oc 里规定,如果父类和子类有同名方法,子类对象优先调用子类同名方法),然后 在 student 类里发现- (id)init方法,之后又发现:

{

    if ( self = [super init] )这句话,那么编译器会率先进入到父类 person,因为 super 的作用

    {

        _no = 1;

    }

    return self;

}

然后先调用直接父类 person 的 –init,而 person 的-init为:

- (id)init

{

    if ( self = [super init] )还是执行到此,我们发现调试就进不去了,因为 super 调用的是 NSObject,苹果是不开源的,但是事实还是进去偷着执行 NSobject 的-init 方法,初始化isa 指针, 把 isa 初始化为指向student 类本身,记住是当前的类,初始化完毕,程序执行回到 person 类,继续向下执行_age=10。(同时student 的成员变量 age 变为10)

    {

        _age = 10;

    }

    return self;最后返回的 self 指向的是 当前student 的对象

}

当person的-init 调用完毕,最后才回到 子类student 类,继续执行 student 的-init, 执行_no=1,继承来的 isa 初始化为指向本身 student 类,这才初始化完毕。

person 对象初始化的时候,同理,先在本类查找初始化方法,发现 super 语句,然后再去父类 NSObject 类 里查找-init方法,(这里先记住 self=[super init]的写法,下来再深入),NSObject 做一件事,那就是初始化 isa,把 isa 指向 person 类本身,(指向当前类,这个类是毕源的,看不到内部代码)然后回到 person类,_age=10。执行完毕。

再看一看 student 对象,创建的时候,先初始化,同理在本类,然后 发现 super,那么去父类 person 执行-init,还是发现 super,还是去 NSObject执行-init,把 isa 指向 student 类本身,(当前类不是 person,是 student 了)然后回到 person,_age=10.回到student,_no=1,执行完毕,再回main 函数,初始化,完毕。

oc构造方法的自定义

oc自定义构造方法的规范

1.一定是对象方法, 故一定以 - 开头

2.返回值一般是id类型

3.方法名一般以initWith开头

这让我想起了,c++构造函数的含参构造和默认构造,和不带参数的构造,意义是类似的。其实就是带参构造。和 c++大同小异。

Person.h
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property NSString *name;
@property int age;
- (id)initWithName:(NSString *)name;
- (id)initWithAge:(int)age;
- (id)initWithName:(NSString *)name andAge:(int)age;
@end

Person.m
#import "Person.h"
@implementation Person
- (id)initWithName:(NSString *)name
{
    if ( self = [super init] )固定写法,记住
    {
        _name = name;
    }
    return self;
}
- (id)initWithAge:(int)age
{
    if ( self = [super init] )
    {
        _age = age;
    }
    return self;
}
- (id)initWithName:(NSString *)name andAge:(int)age
{
    if ( self = [super init] )
    {
        _name = name;
        _age = age;
    }
    return self;
}
@end

Student.h继承 person 类
#import "Person.h"
@interface Student : Person
@property int no;//_no 是子类 student 自己的属性
- (id)initWithNo:(int)no;
- (id)initWithName:(NSString *)name andAge:(int)age andNo:(int)no;
@end

student.m
#import "Student.h"
@implementation Student
- (id)initWithNo:(int)no
{
    if ( self = [super init] )
    {
        _no = no;
    }
    return self;
}
// 要理解和接受这个做法和思想:
// 父类的属性交给父类方法去处理,子类方法处理子类自己的属性
- (id)initWithName:(NSString *)name andAge:(int)age andNo:(int)no
{
// 将name、age传递到父类方法中进行初始化,no 在本类初始化
使用了自定义的构造方法
    if ( self = [super initWithName:name andAge:age])
    {
        _no = no;
    }
    return self;
}
@end

main.m
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Student.h"
int main(int argc, const char * argv[])
{
    @autoreleasepool {
        Student *p = [[Student alloc] initWithName:@"Jim" andAge:29 andNo:10];
    }
    return 0;
}

每个对象创建之后,都有一个默认名,年龄,和学号,但是每个人的结果不一样。此时,需要使用自定义构造方法初始化。否则重写构造方法初始化的话(不带参数)导致名称都是一样的。不符合程序要求。

首先,创建 student 对象,初始化对象指针 p(指向对象),先在本类找 initWithName 方法,确实有,然后进入执行,将name和age(都是继承来的属性)传到父类方法中进行初始化:这样分工明确(其实和 c++一样的思路),自己做自己的事情,体现了良好的架构思想,还有这样做的好处是,如果我们都统一在子类初始化,那么一旦父类的成员变量名称改变了,会导致子类的代码出错,需要修改,一旦工程较大,后果不堪设想,而分工明确,自己做自己的事情,把父类的成员让父类去初始化,子类只管自己的,就能做到不变应万变。

时间: 2024-10-08 02:06:23

objective-c 语法快速过(4)的相关文章

Swift语法快速索引

在WWDC的演示中就可以看出来Swift这个更接近于脚本的语言可以用更少的代码量完成和OC同样的功能.但是对于像我一样在战争中学习战争的同学们来说,天天抱着笨Swift Programming Language Reference之类的大部头看不实际.毕竟还是要养家糊口的.而且,那么1000+页内容讲的东西不是什么都要全部在平时工作中用到的.咱们就把平时用到的全部都放在一起,忘记了立马翻开看看,不知不觉的就学会了之后变成习惯.这样多省事. 变量 1 // Variable 2 var int_v

markdown语法快速入门

# markdown语法快速入门 > 只记住下面的语法就可以满足日常使用了 **强调***斜体*~~划掉~~++下划线++==字体颜色==# 标题一## 标题二### 标题三#### 标题四##### 标题五###### 标题六---分割线> 引用的文字 - 无序列表 - 无序列表- 无序列表 1. 有序列表2. 有序列表3. 有序列表 - [ ] 未完成任务列表- [ ] 未完成任务列表- [x] 已完成任务列表 [链接](http://www.xxxx.com/) ![image](htt

Objective-C基础语法快速入门

Objective-C基础语法快速入门 2010-11-04 16:32 折酷吧 zheku8 字号:T | T 假如我们对面向对象的思维已经C语言都很熟悉的话,对于我们学习Objective-C将会非常有用.假如我们对C语言还不熟悉的话,那我们需要学习一下C语言. AD: 2010年11月编程语言排行榜和2月编程语言排行榜讲的都是Objective-C.Objective-C是Mac软件开发领域最主要的开发语言,假如我们对面向对象的思维已经C语言都很熟悉的话,对于我们学习Objective-C

《Swift语法快速入门》已可购买,《Swift殿堂之路》接受预定

<Swift语法快速入门>已由电子工业出版社出版,京东当当有售.需要签名版本的朋友,请与我联系.另外,IOS开发常用类库实例演练<Swift殿堂之路>已接受预订,预订链接:http://www.swiftbang.com/read-5-1 在学习Swift的过程中,如有任何疑问,请加入Swift书友会QQ群:259152129,与作者一起讨论.研究Swift开发技术! 欢迎你!

objective-c 语法快速过(6)

内存管理基本原理(最重要) 移动设备的内存极其有限(iphone 4内存512M),每个app所能占用的内存是有限制的(几十兆而已). 当app所占用的内存较多时,系统会发出内存警告,这时得回收一些不需要再使用的内存空间.比如回收一些不需要使用的对象.变量等 管理范围:任何继承了NSObject的对象,对其他基本数据类型(int.char.float.double.struct.enum等)无效,和 java 不一样,oc 开始的时候没有垃圾自动回收机制. OC对象的基本结构 每个OC对象都有自

互联网世界中的C语言——我的golang学习笔记:1(基础语法快速过)

前言 学习任何知识都会有一个学习背景 最近,我们团队乃至我司整个云服务,上go的呼声越来越高!新服务已经开始用go开发,部分现有Java版的服务重构为go也只是时间问题而已,故相关技术积累势在必行!在云网络的分布式服务乃至在一切高并发,分布式后台服务中,golang都有着很大的优势. 据我对国内互联网行业的实际考察,了解,目前国内主流互联网公司都在积极投入go的怀抱…… 青云更是全栈使用了go…… 还有火的一塌糊涂的docker. 它为云而生. 它为并发而生. 还有go的安全.简洁.高效 有良好

objective-c 语法快速过(1)

有一定 c++或者 java 基础,过一遍 oc 语法即可,都是相通的,个人认为难点是 oc 的内存管理,虽然有了 ARC,但是也需要学习下,因为有旧软件的维护. 建立在C语言的基础上,增加了一层小范围的面向对象的语法(保留了面向对象最精华的部分,oc的内容没有java多,而java的内容没有c++多,c++的内容最为繁杂),OC完全兼容C语言,c和oc可以混编.可以在OC代码中混入C语言代码(前提是oc源文件扩展名是.m),甚至是C++代码(不是所有的源文件都能包含c++代码,只有源文件扩展名

objective-c 语法快速过(8)

Block(oc 的数据类型,很常用,本质是c结构体) 类似内联函数,从源代码层看,有函数的结构,而在编译后,却不具备函数的性质.编译时,类似宏替换,使用函数体替换调用处的函数名 Block封装了一段代码,可以在任何时候执行 Block可以作为函数参数或者函数的返回值,而其本身又可以带输入参数或返回值. 苹果官方建议尽量多用block.在多线程.异步任务.集合遍历.集合排序.动画转场用的很多 Blocks的定义: int (^MySum)(int, int) = ^(int a, int b)

objective-c 语法快速过(7)

ARC(是编译器特性) ARC是自iOS 5之后增加的新特性,完全消除了手动管理内存的烦琐,编译器会自动在适当的地方插入适当的retain.release.autorelease语句.你不再需要担心内存管理,因为编译器为你处理了一切 ARC 是编译器特性,而不是 iOS 运行时特性,它也不是类似于其它语言中的垃圾收集器.因此 ARC 和手动内存管理性能是一样的,有时还能更加快速,因为编译器还可以执行某些优化 ARC基本原理(不是类似 java 的垃圾回收机制) ARC 的规则非常简单:只要还有一