Objective C 笔记
-
IOS 不同版本特性。
-
IOS开发工具和相关开发测试工具。
-
OC内存管理方式
- ARC 自动引用计数内存管理方式。
- Reference Count(引用计数):类似于C++的共享指计,会C++的都懂,当一段内在被申请后,就会记录这段内存被使用次数.当次数为0时,被申请的内在就会被释放。
- Retain消息:使计数器+1,改方法返回对象本身。
- Release消息:使计数器-1(并不代表释放对象)。
- RetainCount消息:获得对象当前的引用计数器值。
- 内存管理。
- GC(GarbageConnection): 和Java类似,在程序执行过程中,由程序准确的将内在垃圾回收机制(IOS不支持这种方式)。
- 由程序员自行管理,不过要C使用指针去做这些事情,当然,使用的场景是对内存有很高的要求.因为,OC支持与C混编。
-
OC @符号
- 让编译器识别是OC中的类型,类,方法等,起到一个标识的作用.
-
OC id 类型
-
可声明任意类型的对象,类似于C/C++中
void *
id tmp; -(id) fun: (int)param and : (int) param2;
-
类
- 每个类都有一个class类型的指针 isa,继承于NSObject类,方法变量等信息都存储于这个指针变量 isa 中,isa 在类中是一个隐藏属性,在每个类中都会自动创建.
- 类的声明
1 @interface Test : NSObject 2 { 3 int _count;
4 } 5 -(void) setCount : (int) count;
6 -(void) print;
7
8 @endPS: 在C++中,类的声明关键字是class
class Tmp { };
在OC中,使用@interface与@end包裹.用大括号包裹的是类的成员变量,成员方法在括号之外用加号(+)或减号(-)标识.
加号(+)与减号(-),代表两种不同的方法,减号代表实体方法(instance method),而实体方法只能在类实例化后被调用运行.另外一种是加号(+)标识,代表类方法(class method),脱离类实例化调用运行.有点类似C++中的静态成员方法.
- 类定义
1 @implemention Test 2 -(void) setCount : (int) count 3 { 4 _count = count; 5 } 6 7 -(void) print 8 { 9 NSLog(@"count = %d ", _count); 10 } 11 @end
- 类实例化
1 // 实例化类对象 2 Hello hello = [[Hello alloc] init]; 3 // 将alloc 和 init 封装成 new 4 Hello hello = [Hello new];
PS: 在new执行时,分配内存(Allocation)和初始化(Init)两个操作,如:第二行一样.在编译时每个类会在isa中存储类的所有信息(包括方法和变量),在runtime会读取Class信息,知道了类实例的变量类型大小,以及在内存中的位置偏移,根据这些计算出内存大小.实际上isa也被初始化了,同时会将实例的变量及超类的变量都会清零,至此内存分配就完成了.然后,再开始对实例里的变量进行出初始化.
- 类构造方法(默认构造方法:init)
1 @interface Cattle : NSObject 2 { 3 NSString *_name; 4 NSInteger _age; 5 } 6 7 - (id) initCattle: (NSString *) name withAge: (NSInteger) age; 8 - (void) showInfo; 9 10 @end 11 12 @implementation Cattle 13 - (id) initCattle: (NSString *) name withAge: (NSInteger) age 14 { 15 // 初始化超类 16 self = [super init]; 17 // nil 相当于NULL 18 if (self != nil) 19 { 20 self->_name = name; 21 _age = age; 22 } 23 } 24 25 int main(int argc, char *argv[]) 26 { 27 @autoreleasepool 28 { 29 Cattle *cattle = [[Cattle alloc] initCattle: @"hongniu", withAge: 10]; 30 [cattle showInfo]; 31 } 32 }
PS: 自定义初始化方法,在方法名前必须加init,如第七行一样.
1 // 重写初始化方法 2 @interface Cattle : NSObject 3 - (id) init: (int) count; 4 @end 5 6 @implementation Cattle 7 - (id) init: () count 8 { 9 // init code 10 } 11 12 @end
PS:构造方法使用注意
- 派生类拥有基类所有成员变量(排除私有变量),在重写构造方法时,要先初始化从基类继承的变量。初始化原则是先初始化基类,再初始化派生类。
- 重写构造方法的返回值类型必须为id类型
- 重写构造方法的目的,是让在类实例化时,初始化非0的固定值。
- 重写构造方法,方法名称必须是init。既然,重写构造方法,当然要与原生的构造方法重名。
- 自定义的构造方法,即不重写原生的构造方法,构造方法名称必须以init开头,如上面例子第13行。当然,也要延续1,2,3条原则。
- 构造只能是类成员方法,不能是类方法,或者静态方法。
- 析构函数
1 - (void) dealloc 2 { 3 // 调用基类析构函数 4 [super dealloc]; 5 }
- 类的作用域,默认是@protected作用域 (派生类延续基类作用域,详细看多重继承),类成员变量的作用域和C++中类成员变量作用域没什么不同。
- @private:类变量在@private作用域限定,那么,只能在类里面访问这个变量。
- @protected:类变量在@protected作用域限定,那么,在类里面和类的派生类里面才能访问这个变量,不推荐在类外部访问。
- @public:类变量在@public作用域限定,那么,在类里面和类的派生类里面,以及在外部都可以访问这个变量。
1 // .h 2 #import <Foundation/Foundation.h> 3 4 @interface Cattle : NSObject 5 { 6 @private 7 NSString *_name; 8 NSInteger _age; 9 10 @protected 11 NSString *_cpro; 12 13 @public 14 NSString *_cpub; 15 16 } 17 18 - (id) initCattle: (NSString *) name andAge: (NSInteger) age; 19 20 - (void) showInfo; 21 22 @end 23 24 @interface Bull : Cattle 25 { 26 @private 27 NSString *_bpri; 28 29 @protected 30 NSString *_bpro; 31 32 @public 33 NSString *_bpub; 34 35 } 36 37 - (id) initBull: (NSString *) bpri withBpro: (NSString *) bpri withBpub: (NSString *) bpub; 38 39 - (void) showInfo; 40 41 @end 42 43 @interface Test : Bull 44 { 45 @private 46 NSString *_tpri; 47 @protected 48 NSString *_tpro; 49 @public 50 NSString *_tpub; 51 52 } 53 54 // 重写构造方法 55 - (id) init: (NSString *) tpri withTpro: (NSString *) tpro withTpub: (NSString *) tpub; 56 - (void) showInfo; 57 58 @end 59 60 // .m 61 #import "Cattle.h" 62 63 @implementation Cattle 64 - (id) initCattle: (NSString *) name andAge: (NSInteger) age 65 { 66 // 初始化超类 67 self = [super init]; 68 69 // nil 相当于NULL 70 if (self != nil) 71 { 72 self->_name = name; 73 self->_age = age; 74 _cpro = @"cpro"; 75 _cpub = @"cpub"; 76 } 77 78 return self; 79 } 80 81 - (void) showInfo 82 { 83 NSLog(@"Cattle name is : %@, and age is %ld", _name, _age); 84 } 85 86 @end 87 88 @implementation Bull 89 - (id) initBull: (NSString *) bpri withBpro: (NSString *) bpro withBpub: (NSString *) bpub 90 { 91 self = [super initCattle: bpri andAge: 10]; 92 if (self != nil) 93 { 94 _bpri = bpri; 95 _bpro = bpro; 96 _bpub = bpub; 97 } 98 99 return self; 100 } 101 102 - (void) showInfo 103 { 104 NSLog(@"Cattle name is : %@", _cpro); 105 NSLog(@"Cattle name is : %@", _cpub); 106 NSLog(@"Bull name is : %@", _bpri); 107 NSLog(@"Bull name is : %@", _bpro); 108 NSLog(@"Bull name is : %@", _bpub); 109 } 110 111 @end 112 113 @implementation Test 114 - (id) init: (NSString *) tpri withTpro:(NSString *)tpro withTpub:(NSString *)tpub 115 { 116 self = [super initCattle: tpri andAge: 20]; 117 self = [super initBull: tpri withBpro: tpro withBpub: tpub]; 118 119 if (self != nil) 120 { 121 _tpri = tpri; 122 _tpro = tpro; 123 _tpub = tpub; 124 } 125 126 return self; 127 } 128 129 - (void) showInfo 130 { 131 NSLog(@"Cattle name is : %@", _cpro); 132 NSLog(@"Cattle name is : %@", _cpub); 133 NSLog(@"Bull name is : %@", _bpro); 134 NSLog(@"Bull name is : %@", _bpub); 135 NSLog(@"Test name is : %@", _tpri); 136 NSLog(@"Test name is : %@", _tpro); 137 NSLog(@"Test name is : %@", _tpub); 138 } 139 140 @end 141 142 // main.m 143 #import <Foundation/Foundation.h> 144 #import "Cattle.h" 145 146 int main(int argc, const char * argv[]) 147 { 148 @autoreleasepool 149 { 150 Cattle *cattle = [[Cattle alloc] initCattle: @"hongniu" andAge: 100]; 151 [cattle showInfo]; 152 NSLog(@"Cattle ***********************"); 153 Bull *bull = [[Bull alloc] initBull: @"bullpri" withBpro: @"bullpro" withBpub: @"bullpub"]; 154 [bull showInfo]; 155 156 NSLog(@"Cattle name is : %@", bull->_cpub); 157 NSLog(@"Bull ***********************"); 158 Test *test = [[Test alloc] init: @"test" withTpro: @"testpro" withTpub: @"testpub"]; 159 [test showInfo]; 160 NSLog(@"Test ***********************"); 161 NSLog(@"Test name is : %@", test->_cpub); 162 NSLog(@"Test name is : %@", test->_bpub); 163 } 164 165 return 0; 166 }
- 类方法
- 规则(类方法类似C++中静态方法)
- 类方法可以调用类方法。
- 类方法不能调用类成员方法,但是,类方法可以通过在函数体内部实例化类对象,通过实例化对象访问成员方法。
- 类方法不能使用类成员变量,但是类方法可以使用self对象,因为,self对象不是类成员变量。
- 类方法可以作为消息,类方法可以发送到类或者对象里面去,实际上就是类或者对象可以调用类方法。PS:在C++中对象不能调用静态成员方法。
- 规则(类方法类似C++中静态方法)
- 类成员方法私有化,在OC中,类成员方法是没有@private、@protected这些权限的,类成员方法都是公有方法。但是可以通过一些技巧,将类成员方法私有化,这种方法是不能阻止其他开发都去调用这个被使用技巧私有化的方法。因为,这只是一种潜规则,一种默契。只是告诉开发人员这是一个私有方法,不要去使用它,非要使用也是无可奈何的。因为,这种方法没有任何编译器的支持,同时,Xcode还会给出警告。好了,现在就说说这种技巧吧!其实,很简单,实际上就是类成员方法只定义,不声名。这样,当然会给出警告了,这样做,只是不容易让开发人员看到这个方法,更更要的是,告诉开发人员这是个一私有方法,最好不要用,仅此而已。
-
在OC中使用消息(Message)方式调用类中方法,格式如下:
1 /** 2 * 对象或类名字 称为消息接收器 3 * 方法名称 称为消息选择器 4 * 参数序列 是消息内容 5 */ 6 [对象或者类名字 方法名字 : 参数序列]; 7 [hello setCount: 4]; 8 [hello print];
所谓消息就是对象或者类方法的可以执行动作.当编译器遇到这种格式就会将其当成消息发送,而中括号内容称为消息表达式,"对象或类名字" 称为消息的接收器(Receiver),也就是消息的接收者."方法名称 : 参数序列" 就是一个消息,"方法名称" 被称为消息选择器(Selector)或者关键字(Keyword)."参数序列" 就是消息内容。
- 同步锁,线程同步两种方式:
- NSLock
- @synchronized
-
宏#if , #ifndef, #ifdef (编译器在编译时,选择编译不同版本的代码)
- #if defined(DEBUG) || defined(_DEBUG) #endif
- #ifndef 是 #if not define 缩写,未定义为真
#ifndef __IPHONE_7_0 #endif
- #ifdef 定义为真
#ifdef __IPHone_7_0 #endif
-
Debug 与 Release
- Debug 调试
#if defined(DEBUG) || defined(_DEBUG) #endif
设置Debug调试,project --> Scheme --> Edit Scheme --> Run projectname --> Build Configuration 选择 Debug 或 Release
- 快捷键
- command + \:当前行设置/取消断点;通过鼠标点击蓝色断点来启用/禁用当前行断点.
- command + Y:全局激活或禁用所有的断点,激活进入调试模式(此时断点蓝色可见).
- 编辑断点
- Condition :设置断点触发条件.
- Ignore :设置断点忽略次数,忽略多少才被中断.
- Action :设置断点触发时的动作.
- 调试
- F6 : 逐行执行.
- F7:进入函数体.
- F8:出函数体.
- Control + Command + Y :逐断点(continue)继续执行.
- Debug 调试
-
动态库(lib*.so) 与 静态库(lib*.a)
-
类继承
1 @interface Drivde : Base 2 { 3 // 成员变量 4 } 5 6 // interface method 7 // class method 8 @end
- self : 当前对象或当前类实例的指针,指向内部成员,相当于C++的this指针.
- super : 超类的实例的指针,当想使用基类的可视成员时使用.
1 @interface Drivder : Base 2 { 3 NSString name; 4 } 5 6 -(void) setName : (NSString)name; 7 -(void) Print; 8 9 @end 10 11 @implemention Drivder 12 -(void) setName : (NSString)name 13 { 14 self->name = name; 15 } 16 17 -(void) Pring 18 { 19 NSLog("print : %@str", self-name); 20 } 21 22 @end
PS: 在OC中只有单一继承,没有像C++中的多重继承.
-
@property 与 @synthesize 特性
1 (参数1, 参数2) 类型 变量名;
- @property 与 @synthesize 是成对出现的。
- @property 特性是由xcode自动生成setter和getter方法的声明 。
- @synthesize 特性是由xcode自动生成setter和getter方法的定义。
- @property 是在@interfance与@end之间,并且,不能声明类成员作用域中。
- @synthesize 是在@implemention与@end之间。
- 使用@property定义的变量,可以在其它类中依然有效。
- 在@property定义的变量,使用格式:self.*,而这种格式在@interface块作用域中定义的成员变量,不能如此使用。
1 @interfance Foo : NSObject 2 { 3 NSString *name; 4 NSString *methodvar; 5 } 6 7 @property NSString *name; 8 9 -(void) setMethodVar : (NSString *)methodvar; 10 -(void) print; 11 12 @end 13 14 @implemention Foo 15 16 @synthesize name = _name; 17 18 -(void) setMethodVar : (NSString *) methodvar 19 { 20 self->methodvar = methodvar; 21 } 22 23 -(void) print 24 { 25 NSLog(@"class method var : %@", self->methodvar); 26 } 27 28 @end 29 30 int main(int argc, const char *argv[]) 31 { 32 Foo *foo = [[Foo alloc] init]; 33 [foo setMethodvar : @"mehtod var"]; 34 [foo print]; 35 foo.name = @"property var"; 36 NSLog(@"property var : %@", foo.name); 37 38 return 0; 39 }
-
Class 类型、Selector 选择器、SEL 类型、函数指针
-
Class 类型
-
机制:一个类在正确编译后,在这个被正确编译好的类里面,存在一个isa指针,用于存储类的方法及变量信息,这个isa指针是id类型。可以通过一个普通的字符串可能获取到这个Class类型对象,也可以通过此类的对象获取到此类的Class类型对象,获取到Class类型对象后,可以按类实例化后的对象一样使用它。在程序runtime可以通过类的Class类型对象获取到类实例化后的对象,也可以动态的获取在编译阶段无法确定的对象。
-
因为,在类里面存储了类的所有信息,所以,可以通过类的名称或类的对象获取到Class类型对象。当然,也可以获取到超类的Class类型对象。
1 // 通过类名称或对象,向此类或者对象发送class消息,获取此类的Class类型对象 2 Class class = [类名称或对象 class]; 3 // 通过类名称或对象,向此类或者对象发送superclass消息,获取此类的超的Class类型对象 4 Class superClass = [类名称或对象 superclass]; 5 // 通过类名称字符串,获取此类的Class类型对象 6 Class class = NSClassFromString(类名称字符串); 7 // 通过Class类型对象,获取此类的名称字符串 8 NSString *classname = NSStringFromClass(Class 参数); 9 // 向类对象发送消息,获取类的类名称,classname是一个固定参数,详细参考classname实现源码 10 NSString *classname = [classobject classname];
-
- Selector 选择器
-
机制:选择器Selector是用于表示方法的,会根据方法的名称(参数序列),确定一个唯一的身份证明(其实,就是一个整数),(摸不准/*在不同的类里面相同名称相同声明的方法,其身份证明是相同的)。在runtime就不用对方法的名称进行比较,以确定要执行的是哪一个方法,只要通过一个整数就可以定位到相应的方法,然后就可以找到相应方法的入口地址,就可以执行方法了。在OC中消息的执行(方法的执行)与C语言直接找到函数地址入口方式相比,OC的消息机制从效率上讲是比较低下的。虽然,OC使用了Selector选择等方式进行寻找,总是要花费时间的。OC是兼容C语言的,也就是说可以使用C的函数指针方式,增加效率。当要求效率时,比如,当在一个大循环里,要使用某一功能时,就放弃对某一单一对象发送消息的方式(Selector),从而使用函数指针,这样就有和C一样的效率了。
-
- SEL 类型
- 在Selector选择器已经说了,在编译的时候,会根据方法的名字及参数序列,确定一个唯一的身份证明,这个身份证明就是一个SEL类型,可以通过方法名字取得方法的ID(SEL类型对象),也可以通过方法名称的字符串取得SEL类型对象。反之,也可以通过SEL类型对象(ID)取得方法名字。如下:
1 // 通过方法名称,获取此方法的SEL类型对象 2 SEL 变量名 = @selector(方法名称); 3 // 通过方法名称字符串,获取此方法的SEL类型对象 4 SEL 变量名 = NSSelectorFromString(方法名称字符串); 5 // 通过方法的SEL类型对象及参数,获取方法名称 6 NSString *变量名 = NSStringFromSelector(SEL 参数); 7 // 通过SEL类型对象,获取到此方法的方法名称 8 NSString *变量名 = [SEL methodname];
- 调用方式
1 // 对象 -- 接收器
2 [对象 performSelector: SEL类型变量 withObject: 参数1 withObject: 参数2 ...]; -
好处:增加其方法使用的灵活性,可以通过配置文件(文本文件、XML文件)指定程序要执行的方法,在runtime读取配置文件,将方法名称或方法名称字符串转换成SEL类型对象,通过发送消息执行。由于,OC中寻找方法是通过ID(一个整型值),相比匹配字符串寻找方法要有效率得多。
- 在Selector选择器已经说了,在编译的时候,会根据方法的名字及参数序列,确定一个唯一的身份证明,这个身份证明就是一个SEL类型,可以通过方法名字取得方法的ID(SEL类型对象),也可以通过方法名称的字符串取得SEL类型对象。反之,也可以通过SEL类型对象(ID)取得方法名字。如下:
- 函数指针
- 格式:
1 // C函数指针,id -- 接收者对象,SEL -- 方法的SEL类型对象,NSString * -- 方法参数(自定义) 2 void (*func)(id, SEL, NSString *); 3 // OC 4 IMP funoc;
PS: 用法和C一样。
- 例子 :
1 id cla = [[ClassE alloc] init]; 2 SEL funoc = @Selector(fun); 3 void (*func)(id, SEL, NSString *); 4 func = (id, SEL, NSString *) [cla methodForSelector: funoc]; 5 func(cla, funoc, @"test");
- 参数 (在OC中,函数指针的前两个参数,即:id与SEL是必须的,剩下的参数是由函数指针的参数序列决定)
- id -- 是一个id类型,是指消息的接收者对象。在runtime实际上id就是self对象,因为要从某个对象发送消息。
- SEL -- 是一个SEL类型,是指方法的ID(方法的身份证明,一个整型),在消息发送过程中,通过_cmd方法本身的SEL(方法ID)。也就是说在方法的定义体里面,可以通过_cmd获取方法本身的ID。
- NSString* -- 自定义参数。
- 格式:
-
-
OC 数据类型
- BOOL 类型
- NSString 字符串类型:修改const类型字符串,即,指向一个const类型字符串地址。(字符串不能修改,)
- NSMutableString 字符串类型:修饰非const类型字符串,即,指向一个非const类型字符串地址。可做替换,增加,修改等操作。
1 NSMutableString *str = [NSMutableString stringWithString: @"this a string"];
2 [str insertString: str2 atIndex 3]; - NSNumber 一个类簇
- NSDate 日期类型
- NSArray 数组类型
- 还需要补充与详解。
-
Block
- block 是一个类型,在 runtime 保存代码,有点类似于C++ 宏的功能,但比宏更加强大,在 runtime 时可以再赋值为另一个函数代码 (block 以函数形式表现,类似于函数指针,个人感觉就是宏和函数指针的结合体),格式如下:
1 // 运行时的代码保存 2 int (^add)(int, int) = ^(int a, int b) // ^是block的标识符 3 { 4 return a + b; 5 }; 6 7 // ^ 是一种类型,定义某一种代码格式类型 8 typedef int (^intcat)(int, int); 9 10 intcat cat = ^(int a, int b) 11 { 12 return a > b ? a : b; 13 }; 14 15 int main(int argc, char *argv[]) 16 { 17 int ret = add(1, 3); 18 NSLog(@"add(1, 3) = %d", ret); 19 int catret = cat(1, 3); 20 printf("cat(1, 3) = %d", catret); 21 }
- ^ (block) 是类型标识符。
- 与函数相比:1)返回值 2)有参数或无参数 3)调用方式一样
- block 保存的代码其函数体内部可以使用函数体外部变量。
- block 保存的代码其函数体的外部变量(局部变量)在函数体内部是不能修改的,只能使用。除非,在函数体外的声明的局部变量,在声名时,同时,声明为_block类型。在 block 函数体内部才可以修改值。
- block 是一个类型,在 runtime 保存代码,有点类似于C++ 宏的功能,但比宏更加强大,在 runtime 时可以再赋值为另一个函数代码 (block 以函数形式表现,类似于函数指针,个人感觉就是宏和函数指针的结合体),格式如下:
-
Protocol 协议
- 协议就是委托,是指一个对象提供机会对另一个对象的变化做出反应或者影响另一个对象的行为。
- 协议只能一个用途,就是为继承的类,声明出一堆方法的声明。
- 基类遵守的协议,其派生类也要遵守其基类遵守的协议,也就是说父类的协议可以被子类继承。
- 在OC中类不能多重继承,只能单继承,而协议却可以多继承。
- 协议声明的方法可以由继承的任意类去实现。
- 协议 <NSObject> 是一切协议的基协议。
- 协议可以遵守协议,也就是说一个协议可以去遵守(继承)其它协议,这样就可以拥有其它协议的所有方法的声明。
- 在协议中还有两个关键字@optional and @required,@optional 修改的方法声明告诉开发者可以这个方法可以实现,也可以不实现。@required修饰的方法声明告诉开发都这个方法必须实现,当然,这两个关键字修改的方法,都可以不去理会,但xcode会给出警告。
- 协议定义格式:
1 // 定义的协议名称 遵守协议名称 2 @protocol MyProtocol <NSObject> 3 @required 4 5 @optional 6 7 @end
例子:
1 // 委托者 DemoViewController.h 2 #import <UIKit/UIKit.h> 3 4 @protocol DemoDelegate <NSObject> 5 - (void)setEditWithValue:(NSString *)aValue; 6 @end 7 8 @interface DemoViewController : UIViewController 9 { 10 id<DemoDelegate> iDelegate; 11 } 12 13 // 此delegate就是setDelegate方法 14 @property (nonatomic, assign) id<DemoDelegate> iDelegate; 15 16 @end 17 18 // DemoViewController.m 19 #import "DemoViewController.h" 20 21 @interface DemoViewController () 22 { 23 NSString *iVarString; 24 } 25 26 @property (nonatomic, copy) NSString *iVarString; 27 28 - (void)print; 29 30 @end 31 32 @implementation DemoViewController 33 @synthesize iDelegate; 34 @synthesize iVarString; 35 36 - (void)print 37 { 38 [self.iDelegate setEditWithValue:@"test"]; 39 } 40 41 @end 42 43 44 // 被委托者,要注意,在被委托中要设置代码理对象 45 // DemoController.h 46 #import <Foundation/Foundation.h> 47 48 #import "DemoViewController.h" 49 50 @interface DemoController : NSObject <DemoDelegate> 51 52 @end 53 54 // DemoController.m 55 #import "DemoController.h" 56 57 @interface DemoController () 58 { 59 DemoViewController *iDVController; 60 } 61 62 @property (nonatomic, retain) DemoViewController *iDVController; 63 64 - (instancetype)initWithValue:(NSString *)aValue; 65 66 @end 67 68 @implementation DemoController 69 @synthesize iDVController; 70 71 - (instancetype)initWithValue:(NSString *)aValue 72 { 73 if (self = [super init]) 74 { 75 self.iDVController = [[DemoViewController alloc] init]; 76 [self.iDVController setIDelegate:self]; 77 } 78 79 return self; 80 } 81 82 - (void)setEditWithValue:(NSString *)aValue 83 { 84 // to do 85 NSLog(@"detail page edit value: %@", aValue); 86 } 87 88 @end
PS: 在被委托中设置的代理对象,就是委托都的成员属性,即:@property delegate的getter and setter方法。
1 @interface DemoViewController 2 { 3 id<DemoController> iDelegate; 4 } 5 6 @property (nonatomic, assign) id<DemoController> iDelegate;
-
Category (分类)
1 // Classname.h 2 @interface Classname : NSObject 3 { 4 5 } 6 7 @end 8 9 // Classname.m 10 // 分类,是在原类基础上,增加成员方法。
11 @interface Classname (categoryname) 12 @property (int, int) float value; 13 14 @end 15 16 @implementation Classname 17 18 @end原则:
- 分类依赖于类,它能在不改变原类内容基础上增加一些方法,例如例子中用@property修饰的value。
- 分类只能为原类增加成员方法,不能增加成员变量。
- 使用分类增加的方法,依然能使用原类里面的成员变量。
- 分类也可以实现原类中的原有方法,原类的方法会被覆盖,导致原类中的方法不能使用。
- 类中方法,包括分类增加的方法,方法调用优先级:分类 --> 类原成员方法 --> 父类。在类中有多个分类,最后,定义的分类优先调用。
-
指针
-
智能指针 -- NSAutoreleasePool
-
IOS中传递参数几种方法?
- 采用代理模式
- 采用IOS消息机制
- 通过NSUserDefaults存储(或文件,或数据库存储)
- NSUserDefaults 轻量级本地数据存储数据结构
1 NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
PS: 数据结构以键值对形式存储.
- NSUserDefaults 轻量级本地数据存储数据结构
- 通过AppDelegate定义全局变量(或UIApplication,或定义一个单例类等)
- 通过控制器传递属性 Segue
- 通过单例Class传递