OC学习笔记总结(Block语法开始)

1, Block语法

定义:Block就是把一个匿名函数定义成一个变量,

语法格式: int (^)(int, int) Block类型

等号右边给变量赋值,赋值是一个匿名函数

int (^myBlock)(int , int ) = ^int (int a, int b)

{

return a > b ? a : b;

};

int result = myBlock(10, 15);

NSLog(@”%d”, result);

//赋值的匿名函数返回值类型可以去掉 ^/*int*/(int a, int b)

//无参无返回值赋值匿名函数的时候,参数,返回值可以省略

void (^helloBlock)() = ^

{

NSLog(@”hello world”);

};

helloBlock();

 

API知识

//将字符串按某节点分割,取第一块

NSString * (^splitString)(NSString *, NSString *) = ^(NSString * targetString, NSString * sepatorString)

{

return [[targetString  componentsSeparatedByString: sepatorString] firstObject];

};

NSString * string = splitString(@www.baidu.com, @”.”);

NSLog(@”%@”, string);

//逆序输出数组

API: exchangeObjectAtIndex: (nsinteger)withObjectAtIndex: (nsinteger)

//将字符串数组拼接成字符串输出

API: (NSString * targetstring) stringByAppendingString: (NSString * appendingstring);

//Block回调,

//Block用于排序

案例:在定义多个person对象后,对person对象进行年龄排序,定义一个不可变数组存放每个person对象,

Block语法: NSArray * newArray = [Array  SortedArrayUsingComparator: ^ NSComparisionResult(id obj1, id obj2)]

{

//强转类型,在输出的时候能快速定位到年龄

Person * person1 = (Person *)obj1;

Person * person2 = (Person *)obj2;

If ([person1 age] < [person2 age])

{

Return NSOrderedAscending;

}else if ([person1 age] > [person2 age])

{

return NSOrderedDescending;

}

return NSOrderedSame;

} ];

//默认情况下,Block中使用Block之外的变量,默认是只读的,不可修改

//使用__block告诉编译器,此变量在block中可以使用

//block类型的参数是用于回调时从里向外传值(传递信息出去)

//block类型种的类型返回值用于从外向里传值,(就是block回调完得到的结果)

 

多态:

//允许父类指针指向子类型对象

//屏蔽子类之间的差异,写出更通用的代码

//常见形式:

//参数多态和返回值多态

 

属性

属性的声明: 属性的类型  属性名

@property  NSString  *  name;

//等价于声明了一对方法,一个setter, 一个getter

//属性的类型决定生成的setter方法的参数类型,getter方法的返回值类型

//属性名决定生成的方法名是什么

属性的特性:

第一大特性:

//readwrite 既生成setter, 也生成getter

//readonly 只生成 getter

//setter = , getter = , 用于控制生成setter方法和方法名

原子性特性:

//nonatomic 非原子性特性,不保证在多线程环境下访问实例变量的安全性

//atomic 原子性特性(默认), 保证在多线程环境下访问实例变量是安全的, 因为会加一把线程锁

setter语义特性,控制生成的setter方法的内部实现细节

//assign (默认), 通常适用基本类型,setter方法中就是直接赋值

//retain, 适用于所有的对象类型,setter方法中会自动生成内存优化的代码

//copy, 仅适用于接受过NSCoping协议的类的对象才适用

如果属性的setter方法和getter方法同时重写

//那么默认就不会帮你生成实例变量

//解决方案1:自己定义实例变量

//解决方案2:使用@synthesize

//@synthesize array = _array;

 

属性的实现

//name = _name的含义,属性name生成的setter和getter的实现中操作_name这个实例变量

//会先检查有没有该实例变量,如果没有,会自动生成

//从iOS6.0之后@synthesize也可以不用写了,编译器自动生成

//但默认生成的属性实现中是操作与属性名同名加下划线的实例变量

//实例变量也可以不写,不写会自动生成,但生成的是私有的,子类不可以直接访问

//父类里私有的实例变量,仅仅是不可以在子类中直接访问

//子类创建对象的时候,这些父类私有实例变量也会被分配内存存储,可以通过同父类继承的setter或getter访问

 

点语法

//点出现在等号左边,等价于调用了setter方法

//点出现在等号右边,等价于调用了getter方法

//没有等号出现点,等价于getter

KVC(键值编码)

时间类API使用

NSDate (date) 获取当前时间

NSDateFormatter 把日期和字符串之间互转

NSDateFormatter * formatter = [[NSDateFormatter alloc] init];

//设置转换格式

formatter.dateFormat = @”yyyy-MM-dd EEEE hh:mm:ss a”;

//把日期对象转成一个字符串

NSString * dateString = [formatter stringFromDate:date];

NSLog(@”%@”, dateString);

//假设这个是服务器端给我们返回的一个时间戳

//是一个表示时间的字符串

NSString * dateString = @”20150814061022”;

NSDateFormatter * formatter = [[NSDateFormatter alloc] init];

//字符串格式要跟返回的字符串格式一样才能正确输出

formatter.dateFormat = @”yyyyMMddhhmmss”;

//把日期字符串转换成日期对象

NSDate * messageDate = [formatter dateFormString: dateString];

//获取当前时间

NSDate * currentDate = [NSDate date];

//得到两个时间之间相差的描述

NSTimeInterval = seconds = [currentDate timeIntervalSinceDate:messageDate];

NSLog(@”%.1f”, seconds);

后边可以接跟时间长短的判断,分成刚刚,几分钟前,几小时前,几天前,几月几号几时几分几秒

得到一个从现在开始多少秒后的一个时间

NSDate * date = [NSDate dateWithTimeIntervalSinceNow:120];

NSLog(@”%@”, date);

得到从1970年到当前时间流逝的秒数

[date timeIntervalSince1970];

根据一个从1970年流逝的秒数得到一个时间对象

[NSDate dateWithTimeIntervalSince1970:seconds];

 

类目

//类目(分类, Categary): 给一个没有原码的类扩展方法

//类目只能扩展方法,不能扩展实例变量

//扩展的方法会成为原始类的一部分,和原始类中的方法一样,级别相同,会被子类继承

//                目标类    类目名

@interface NSString (SayHIMethod)

延展

//延展Extension, 帮一个类管理私有方法和私有变量

//OC中没有绝对的”私有”方法,所谓私有方法就是在.m里有实现, .h里面没有声明

//延展就是一种特殊形式的类目,就是把类目的声明写到.m中,并且()里不加类目名

协议

//在 .h文件里创建

//协议中方法的参数的作用:用于让代理调用时给它信息,供代理使用

//协议中方法返回值的作用:用于得到代理调用完方法的结果,让委托方作出处理

//协议中定义的是一堆方法声明,只有声明,没有实现

//一个类可以接受一到多个协议,接受了协议就必须实现协议里面的@required方法

//@required修饰的方法代表必须实现,@optional代表的方法是可选实现

//在父类后面加<协议名>表示遵守协议

内存管理

内存管理原则一:

//凡是出现alloc , retain, copy的地方,都要有对应的release或者autorelease与之对应,保证对象用完的时候可以被及时的销毁

内存管理原则二:

//建类必备dealloc, 凡是有属性被修饰成retain或copy的,都要dealloc里release, 防止外界使用属性赋值之后最后一份释放不掉

内存管理原则三:

//便利构造器内自带autorelease

//问题1: 一个对象通过属性赋完值之后,对象提前销毁了,导致赋值完的属性也用不了

//解决方案:赋值时加一个retain,那么会带来问题2;

//问题2:每一次赋新值得时候,上次旧值留到内存里

//解决方案,每次赋新值前,先release一次旧值

//但是会产生问题3

//问题3: 多次给一个属性赋同一个值,第二次赋值时对对象提前释放

//解决方案:setter中加一个判断,如果是同一个值,不做任何处理

//问题4: 最后一份创建的对象无法释放

//解决方案:当班级对象被销毁的时候,释放学生的所有权,即重写dealloc, release对象之后加[super dealloc]

自动释放池

//工作原理:当对一个对象发送autorelease消息,就会把这个对象扔到离它最近的释放池中,当这个池销毁的时候会把池中所有管理的对象逐一发送一次release,进池出池的过程和栈一样,遵循先进后出的原则,先进池的对象,池销毁后release

copy

//当对一个对象发送copy消息,会自动调用copyWithZone:方法

//在copyWithZone:方法中,NSZone类型的参数记录的原对象的内存结构信息,根据原对象内存结构信息,复制出一个副本

//再把原对象实例变量里面的内容赋值给拷贝出新对象的实例变量

//会让拷贝出得新对象引用计数从0到1,原对象引用计数不变

字符串对象的内存管理

//常量区的字符串引用计数是一个无符号整形数的最大值,正常应使用%lu输出,使用%d输出会溢出,显示-1

//无论对它release,还是retain,都无任何影响

dealloc

//对象引用计数变为0时,对象要被销毁(内存回收), 这时会自动调用对象的dealloc方法

//dealloc方法永远不要手动调用

数组字典的内存管理

//数组,字典,集合会对管理的对象引用计数加1

内存管理原则四:

//谁污染谁处理,凡是你自己alloc, retain, copy的,你就得有对应的,release或者autorelease, 不是干的,不要你管

//每次创建一个新字符串,产生的旧字符串会被存放在释放池中,过多累积

//解决方案:添加自动释放池

//防止对象被提前释放,可以采用建空指针的方法避免

对象类型属性两个作用:

//1,方便在类的外部访问类的实例变量

//2,帮你优化一份内存,在对象的整个生命周期中一直可以使用该实例变量

//在方法里创建对象,如果对象的地址保存在一个栈区指针里边,那么出方法前,一定要release或者autorelease掉

//一旦有被retain, copy修饰的对象,就要重写dealloc

//为了保证数组在一个方法中创建完,到另外一个方法中也能用

//通常把数组,定义为属性,使用self.创建对象,因为此时相当于调用了setter方法, setter方法内部会retain一次,保证数组对象在所属类的整个生命周期中都可以使用,这次retain, 在所属类的dealloc中release一次

//使用数组是可以使用_array, 和使用self.array没有区别, 因为是getter

//getter方法更安全的 写法

return [[_array retain] autorelease];

//作用:延长对象的声明周期

posted @ 2015-08-22 20:00  奎了个善  阅读(2354)  评论(0编辑  收藏  举报