一、语法基础
1.OC的语法
关键字基本上都是以@开头,特例:self super id 等等;
字符串以@开始;
BOOL: YES、NO;空:nil;
NSLog(@"Hello");
2.包含框架的主头文件就可以包含所有的.H,及.*的作用。
3.方法与对象:
对象的方法都是以减号-开始;
对象方法的声明必须在@interface和@end之间;
对象方法的实现必须在@implementation和@end之间;
函数可以写在任意位置;
4.方法的参数
OC方法中,一个参数对应一个冒号;
冒号前需要加个说明;
冒号也是方法名的一部分;
- (int)pingFang:(int)num;
-(int)sumWithNum1:(int)num1 andNum2:(int)num2;
int n =[object pingFang:10];
int m = [object sumWithNum1:10 andNum2:5];
5.self
self 代表当前调用的对象或者类;this只能用在对象方法中;
6.多态
父类指针指向子类对象;
父类类型的变量,不能用来调用子类的方法;
7.字符串NSString
NSString *str = @"itcast"; NSLog(@"我在%@上课",str); int age =15; int no= 5; NSString *name = @"Andy"; NSString *newStr = [NSString stringWithFormat:@"My age is %d and no is %d",age,no]; int size = [name length];
8.注释:
#pragma mark 注释标签
9.点语法
点语法的本质是方法调用;
stu.age=10;
编译器:[stu setAge:10];
int nAge=stu.age;
编译器:int nAge = [stu age];
10.set get的编译化
XCode 4.4以后 @property 独揽了@synthesize的功能
#import<Foundation/Foundtation.h> @interface Person:NSObject { int _age; NSString *_name; } @property int age; @property NSString* name; @end; @implementation Person @synthesize age=_age; @synthesize name = _name; @end
11. id类型
id 相当于 NSObject*
id 是万能指针;能指向和操作任何OC对象;
id d = [Person new];
12.构造方法
完成的创建一个可用的对象需要两部:
1.分配存储空间 +alloc;
2.初始化 -init
Person *p=[Person new]; //1.分配存储空间 Person *p1 = [Person alloc]; //2.使用-init进行初始化 Person *p2 = [p1 init]; Person *p3 =[[Person alloc] init]; //重写Person的init方法 -(id) init { //一定要调用super的init方法:初始化父类的其他的成员变量和属性 //self = [super init]; if(self = [super init]) { //初始化成功 _age = 10; } return self; }
3.自定义构造方法规范
a.一定是对象方法;
b.返回类型一般是id类型;
c.方法名一般以init开头
13.Category 分类
不改变原来类的基础上,添加类的方法;
//声明
@interface 类名(分类名称)
@end
//实现
@implementation 类名(分类名称)
分类只能增加方法,不能增加成员变量;
分类方法实现中可以访问原来类的中成员变量;
分类方法的实现优先级最高,然后是原来类,然后是父类,这样会导致原来的方法失效;
14.类的加载和初始化
a.当程序启动时,就会加载项目中所有的类和分类,而且加载后会调用每个类和分类的+load
方法;
b.当第一次使用某个类时,就会调用当前类的+initialize方法;
c.先加载父类,再加载子类;
d.先初始化子类,再初始化子类;
15.description方法
默认情况下,NSLog和%@输出对象时,结果是:<类名:内存地址>
1.会调用对象的p的-description方法;
2.拿到-description方法的返回值(NSString *)显示到屏幕上
16. SEL
-(void) test;
-(void) test2:(NSString *)str;
[p test];
1.把方法包装成SEL类型的数据;
2.根据SEL数据找到test方法;
3.根据方法地址调用对应的方法;
[p performSelector:@selector(test)];
[p performSelector:@selector(test2:) withObject:@"123"];
二、内存管理
1.引用计数器
给对象发送retain消息,可以使引用计数器+1;
给对象发送release消息,可以使引用计数器-1;
可以给对象发送retainCount消息获得当前的引用计数器值;
2.对象的销毁
一个对象的引用计数器为0时;那么它将被销毁;
当一个对象被销毁时,系统会自动向对象发送一条dealloc方法;
Person类的实现 -(void) dealloc { NSLog("对象被销毁"); [super dealloc]; } //alloc 和release要成对出现; //retain和release需成对出现;
3.OC不存在空指针错误,给空指针发送消息不报错;
4.retain方法会返回对象本身;
5.set方法的内存管理
基本数据类型,直接复制;
- (void) setCar:(Car*) car { if(car != _car) { [_car release]; _car = [car retain]; } } - (void)dealloc { [_car release]; }
6.@property参数
1.set方法内存管理相关参数
a.@property (retain) Book *book; retain:release旧值,retain新值;
b.assign:直接赋值,适用于非OC对象类型;
c.copy:release旧值,copy新值;
2.是否生成set方法
readwrite:同时生成setter,getter的声明、实现;(默认)
readonly:只会生成getter的声明、实现;
3.多线程管理
nonatomic:不加锁;性能高,一定要加。
atomic:加锁,默认
4.setter和getter方法的名称
@property (getter=methodName,setter=setName:)int height;
setter方法一定要有冒号:,不常用;
一般常用于BOOL 类型的getter方法名的修改
@property (getter=isRich) BOOL rich;
7.循环retain和@class
循环retain的解决方案:
一端用retain,一端用assign;
@property(nonatomic,retain) Card *card;
@property(nonatomic,assign) Person* person;
8.autorelease
//autorelease方法会返回对象本身 //autorelease会将对象放到一个自动释放池; //当自动释放池被销毁时,会对池子的所有对象做一次release操作; //创建对象时,不要直接用类名;一般用self代替。 int main() { @autoreleasepool {//开始代表创建了释放池 Person *p = [[[Person alloc] init] autorelease]; return 0; }//结束代表销毁释放池 } + (id)person { //使用Person会出现子类调用时,返回的指针类型还是父类的问题 //return [[[Person alloc] init] autorelease] ; return [[[self alloc] init] autorelease] ; } +(id)personWithAge:(int) age { //Person*p = [[[Person alloc] init] autorelease] ; Person*p =[self person]; p.age =age; return p; }
9.ARC机制
//ARC ARC的判断准则: 只要没有强指针指向对象,就会释放对象; 指针分2种: 1.强指针:默认情况下,所有指针都是强指针 __strong 2.弱指针:__weak //strong 等价于之前的 retain // @property (nonatomic,strong) Dog *dog; @property (nonatomic,weak) Dog *dog; ARC的特点: 1.不允许调用release、retain、retainCount; 2.允许重写dealloc,但是不允许调用[super dealloc] 3.@property的参数 *strong:成员变量是强指针(适用于OC对象类型); *weak:成员变量是弱指针; * assign:适用于非OC对象类型; 4.以前的retain,修改为strong,其他一切不变。 5.如果两端互相引用,一端用strong,一端用weak;
三、其他数据类型
1.Block
Block的作用是来封装代码,可以在任何时候执行;
#import <Foundation/Foundation.h> typedef int(*Sump) (int,int); typedef int(^MyBlock)(int,int); int main() { int(^sumBlock)(int,int); sumBlock = ^(int a,int b){ return a+b; }; MyBlock sum2Block = ^(int a,int b){ return a+b; }; return 0; } void test2() { int (^sumBlock)(int,int)= ^(int a,int b) { return a+b; }; int c = sumBlock(10,11); NSLog(@"%d",c); //用一个block输入n条横线 void (^lineBlock)(int)= ^(int n) { for (int i=0; i<n; i++) { NSLog(@"------------"); } }; lineBlock(5); } void test() { //block用来保存一段代码 //block的标识:^ /* block跟函数很像: 1.可以保存代码 2.有返回值 3.有形参 block访问外边的变量: 1.默认情况下,block可以访问外面的变量; 2。默认情况下,block不能修改外面的变量 3.给局部变量加上__block关键字,这个局部变量可以在内部修改; 利用typedef定义block类型 typedef int(^MyBlock)(int,int); 以后利用MyBlock来定义block变量 MyBlock sum2Block = ^(int a,int b){ return a+b; }; */ //定义block变量 //如果block没有形参,后面的括号可以省略 void (^myblock)()= ^{ NSLog(@"test-----------"); }; //利用block变量调用block内部的代码 myblock(); }
2.@protocol 协议
#import <Foundation/Foundation.h> //定义了一个名叫MyProtocol的协议 @protocol MyProtocol <NSObject> //@required 要求实现,不实现就会发出警告;默认 //@optional 不要求实现。 //一个协议遵守了某一份协议,就可以拥有另一个协议中的所有声明方法 //NSObject 是所有类的基类,也是基协议 //要求某个对象遵守这个协议 // NSObject<MyProtocol> *obj = 遵守该协议的类的对象; /* 1.协议的定义: @protocol 协议名称 <NSObject> //方法声明列表... @end 2.如何遵守协议: 1>类遵守协议: @interface 类名:父类名 <协议名称1,协议名称2> @end 2>协议遵守协议: @protocol 协议名称 <其他协议名称1,其他协议名称2> @end 3.协议中方法声明的关键字: 1>@required 要求实现,不实现就会发出警告;默认 2>@optional 不要求实现。 4.定义一个变量的时候,限制这个变量的对象遵守某个协议 类名<协议名称> *变量名;或者 id<协议名称> 变量名; 5.@property中声明的属性也可用做一个遵守协议的限制 @property(nonatomic,strong) 类名<协议名称> *属性名; @property(nonatomic,strong) id<协议名称> 属性名; 6.协议可定义在其他单独文件中, 也可以定义在某个类中 1>如果这个协议只用在某个类中,则定义在该类中; 2>如果用在多个多个类中,则定义在单独文件种。 */ @required - (void)test; @optional - (void)test2; @end
四、Foundation框架
1、结构体
int main() { /* NSRange(location,length) NSPointCGPoint NSSizeCGSize NSRectCGRect */ CGPoint point = NSMakePoint(10, 10); CGPoint point2 = CGPointMake(10, 10);//常用 CGSize size = NSMakeSize(10, 10); CGSize size2 = CGSizeMake(10, 10); CGRect rect1 = CGRectMake(10, 10, 50, 50); CGRect rect2 = {{0,0},{50,50}}; CGRect rect3 = {point,size}; CGRect rect4 = {CGPointZero,CGSizeMake(100, 90)}; NSString *str = NSStringFromPoint(point); //比较两个点是否相同 BOOL bIsSame =CGPointEqualToPoint(point, point2); BOOL bIsContain = CGRectContainsPoint(rect1, point); return 0; } void testRange() { //@“i love oc”; // NSRange r1={2,4};//不用 // NSRange r2={.location=2,.length=4};//不常用 // NSRange r3 = NSMakeRange(2, 4);//常用 NSString *str=@"i love oc"; //查找字符串在str中的范围 //如果找不到,length=0;location=NSNotFound==-1 NSRange range=[str rangeOfString:@"love"]; NSLog(@"loc=%ld,length=%ld",range.location,range.length); }
2、字符串
/* 1.字符串创建 */ NSString *str1=@"hello"; NSString *str2=[[NSString alloc] initWithFormat:@"age is %d",10]; NSString *str3 = [[NSString alloc] initWithUTF8String:"abc"]; const char *cs = [str3 UTF8String]; //从文件中读取 NSString *str4 = [[NSString alloc] initWithContentsOfFile:@"/Users/chenwei/Desktop/objective-c-01.m" encoding:NSUTF8StringEncoding error:nil]; // NSLog(@"%@",str4); //URL:资源路径 //协议头://路径 //本地文件,协议头 file:// NSURL *url = [[NSURL alloc] initWithString:@"file:///Users/chenwei/Desktop/objective-c-01.m"]; NSString *str5 = [[NSString alloc] initWithContentsOfURL: url encoding:NSUTF8StringEncoding error:nil]; NSLog(@"%@",str5); //常用方法.一般都用一个类方法与对象方法对应。 NSString *str6 = [NSString stringWithFormat:@"age is %d",10]; NSURL *str7 = [NSURL URLWithString:@""];
3、数组
/* NSArray: 不可变数组 NSMutableArray:可变数组 @[] 只创建不可变数组NSArray */ int main(int argc, const char * argv[]) { NSMutableArray *array=[NSMutableArray array]; [array addObject:@"Jack"]; [array addObject:@"Rose"]; //nil不能添加 //[array addObject:nil]; //删除元素 //[array removeAllObjects]; return 0; } void useArray() { /* 1.NSArray 创建 */ //OC数组只能存放OC对象、不能放非OC对象,比如int、struct等 //NSArray *array = [NSArray array]; NSArray *array2 = [NSArray arrayWithObject:@"jack"]; //nil是数组元素结束的标记 NSArray *array3=[NSArray arrayWithObjects:@"jack", @"Rose",nil]; //快速创建数组的方式 NSArray *array4=@[@"jack",@"rose",@"others"]; /* 2.NSArray 个数 */ int nCount = array2.count; /* 3.NSArray 遍历 */ for (int i=0; i<array4.count; i++) { NSLog(@"%@",array4[i]); } for(id obj in array4) { NSUInteger nIndex = [array4 indexOfObject:obj]; NSLog(@"%ld---%@",nIndex,obj); } //NSLog(@"%ld",array3.count); [array4 enumerateObjectsUsingBlock: //没遍历到一个元素,就会调用一次block //并且当前元素和索引位置当做参数传递给block ^(id obj, NSUInteger idx, BOOL *stop) { NSLog(@"%ld---%@",idx,obj); if (idx == 0) { //停止遍历 *stop = YES; } }]; void (^myBlock)(id,NSUInteger,BOOL *) = ^(id obj, NSUInteger idx, BOOL *stop) { NSLog(@"%ld---%@",idx,obj); if (idx == 0) { //停止遍历 *stop = YES; } }; for (int i=0; i<array4.count; i++) { BOOL bIsStop = NO; id obj = array4[i]; myBlock(obj, i, &bIsStop); if (bIsStop) { break; } } }
4、字典
int main(int argc, const char * argv[]) { /* 字典: key------>value 索引------>文字内容 里面存储的都是键值对 */ NSDictionary *dict4=@{@"name": @"jack",@"address":@"北京"}; NSArray *keys = [dict4 allKeys]; for (int i=0; i<dict4.count; i++) { NSString *key = keys[i]; NSString *object = dict4[key]; NSLog(@"%@------%@",key,object); } [dict4 enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { NSLog(@"%@------%@",key,obj); }]; return 0; } void useMutableDictionary() { NSMutableDictionary *dict = [NSMutableDictionary dictionary]; [dict setObject:@"Jack" forKey:@"name"]; [dict setObject:@"北京" forKey:@"address"]; [dict setObject:@"Rose" forKey:@"name"]; //[dict removeAllObjects]; NSLog(@"%@",dict); } void userDictionary() { NSDictionary *dict = [NSDictionary dictionaryWithObject:@"jack" forKey:@"name"]; id obj = [dict objectForKey:@"name"]; NSArray *keys=@[@"name",@"address"]; NSArray *objects=@[@"jack",@"北京"]; NSDictionary *dict2 = [NSDictionary dictionaryWithObjects:keys forKeys:objects]; NSDictionary *dict3 = [NSDictionary dictionaryWithObjectsAndKeys: @"jack",@"name", @"beijng",@"address", nil]; //常用方式 NSDictionary *dict4=@{@"name": @"jack",@"address":@"北京"}; id obj2 = [dict4 objectForKey:@"name"]; id obj3 = dict4[@"name"]; NSLog(@"%@",obj2); NSLog(@"%@",obj3); //返回键值对的个数 NSLog(@"%ld",dict4.count); }
5、NSNumber和NSValue
int main(int argc, const char * argv[]) { //NSNumber之所以能包装基本数据类型为对象,是因为集成了NSValue NSNumber *num = [NSNumber numberWithInt:10]; NSDictionary *dict= @{ @"name":@"jack", @"age":num, }; NSNumber *num2 = dict[@"age"]; int nNum = [num2 intValue]; NSLog(@"%d",nNum); //@20将20包装成一个NSNumber对象 NSDictionary *dict2= @{ @"name":@"jack", @"age":@20, }; int age = 10; NSNumber *ageNum= @(age); //将结构体包装成OC对象,使用NSValue。 CGPoint p = CGPointMake(10, 10); NSValue *pValue = [NSValue valueWithPoint:p]; NSArray *array =@[pValue]; //将value转换成对应的结构体 NSPoint newPoint = [pValue pointValue]; return 0; }
6、日期
int main(int argc, const char * argv[]) { //创建一个时间对象 NSDate *date = [NSDate date]; NSLog(@"%@",date); //oc的时间都为秒 NSDate *date2 = [NSDate dateWithTimeInterval:5 sinceDate:date]; //从1970年开始走过的秒数 NSTimeInterval secondsFrom1970 = [date2 timeIntervalSince1970]; //日期格式化类 NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; // y 年 M 月 d 日 // m 分 s 秒 H(24小时) h(12小时) formatter.dateFormat = @"yyyy-MM-dd HH:mm:ss"; NSString *str = [formatter stringFromDate:date]; NSLog(@"%@",str); //字符串,转换成NSDate NSString *str2 = @"2011/09/10 18:56"; NSDateFormatter *formatter2 = [[NSDateFormatter alloc] init]; formatter2.dateFormat = @"yyyy/MM/dd HH:mm"; NSDate *date3 = [formatter2 dateFromString:str2]; return 0; }
7、Copy
@interface Person : NSObject <NSCopying> //copy代表set方法会release旧对象、copy新对象 //修改外面的变量,并不会影响到内部的成员变量 //建议:NSString一般用copy策略,其他对象一般用retain @property (nonatomic,copy) NSString *name; + (id) personWithName:(NSString *)name; @end #import "Person.h" @implementation Person + (id) personWithName:(NSString *)name { Person *person = [[[self class] alloc] init]; person.name = name; return person; } - (id)copyWithZone:(NSZone *)zone { //这里创建的copy对象不要求释放 Person *copy = [[[self class] allocWithZone:zone] init]; copy.name = self.name; return copy; } @end
8.反射
NSString *str = @"Person"; Class class = NSClassFromString(str); Person *person = [[Class alloc] init]; NSLog(@"%@",person); NSString *name = NSStringFromClass([Person class]); //方法反射 NSString *method = @"test"; SEL selector = NSSelectorFromString(method); [person performSelector:selector];