您的位置:首页 > 其它

OC知识点大全(笔记)

2017-03-06 11:47 127 查看
·成员变量与属性的区别:声明了@property并@synthesize后编译器会为实例变量生成getter和setter方法,成员变量用来存储属性的值

//NSObject 属性Foundation框架下的一个类

//iOS 中的四个基本框架:Foundation、SystemConfiguration、UIKit、CFNetWork

//对象的生命周期:对象的生命周期从 alloc 开始,到delloc结束

//通过属性调用setter方法给_name赋值

修饰属性关键字:atomic/nonatomic/readwrite/readonly/ assign/retain/strong/weak/copy/

@property(nonatomic,copy,readwrite,setter=setName:,getter=name)NSString

atomic/nonatomic 原子操作和非原子操作 (原子操作能保证多线程安全)

readwrite/readonly 读写权限

setter 属性的写方法名

getter 属性的读取方法

assign:修饰基本数据类型 直接赋值 NSInteger CGFloat int float double char

weak:修饰对象类型和id类型 弱引用 引用计数不会加一,防止循环引用 只能在ARC环境中使用

strong:修饰对象类型 强引用 引用计数会加一 在ARC里代替retain的作用 只能在ARC环境中使用

retain:修饰对象类型 强引用 旧对象引用计数减一,新对象引用计数加一,如下set方法

-(void)setName:(NSString *)name {

if(_name){

[_name release];

}

_name = [name retain];

}

用strong或者weak修饰的对象的retainCount为0时,属性会被置为nil,不会造成野指针,不会引起崩溃,而用retain/assign 修饰的对象retainCount为0时,是不会进行任何操作的,如果再用属性去调用该对象时,可能会有崩溃现象,野指针操作

·使用copy 或 MutableCopy的对象 必须遵循NSCopy、NSCoding协议或者MutableCopy协议

copy:对不可变对象copy是浅拷贝,对可变对象copy是深拷贝

mutableCopy:一定是深拷贝

析构方法中:要将强引用的对象类型的属性和成员变量释放掉,置为nil;使用assgin 和weak修饰的属性,不用管,释放对象时,先释放本类中的属性和成员变量,在释放父类中的属性和成员变量

·内存管理:基本数据类型的数据 内存在栈上,栈内存由系统去开辟和回收,对象类型的数据 内存在堆上,内存管理就是对对象的内存管理、对堆内存的管理(系统中有一个管理系统空闲空间的链表存放着空闲状态的内存,申请内存时 系统会遍历链表找到大于等于申请的内存的结点将该结点分配给发起申请的对象,并将该结点从存储空闲内存空间的链表中移除;释放一个对象时,对象占的内存回到空闲状态系统又会将对象的堆结点存入链表中,等待下一次分配)OC中的内存管理原则:谁引用,谁管理

·引用计数:继承NSObject的类都有一个引用计数器retainCount,用于记录当前被几个指针引用

·内存管理原则:对象通过引用计数来进行内存管理,引用计数记录对象被几个指针引用。引用计数为零时对象就会被销毁。

采用 alloc、new、copy/MutableCopy(深拷贝)创建对象时,对象的retainCount会增加 1

对一个对象发送 retain、copy 消息,进行强引用时(浅拷贝),对象的retainCount会加 1

**iOS 中的内存管理方式:**ARC、MRC、自动释放池

ARC 和 MRC中内存管理的机制,从本质上讲是一样的,只是不需要我们自己手动编写 retain/copy/mutableCopy/strong/, 也不用去写release/autorelease

autorelease:延迟释放,调用autorelease对象的retainCount 不会立刻减1,而是被添加到自动释放池管理延迟释放对象的数组,等待自动释放池执行结束时才会真正的释放 retainCount - 1

·类方法创建的对象不需要手动release,原因是在类方法中添加了autorelease。缺点:不知道对象什么时候被释放,可能造成提前释放

+ (instancetype)personWithName:(NSString *)name {

Person *p = [[self alloc] init];

p.name = name;

return [p autorelease];

}

·向数组中添加对象时 对象的retainCount会加一,从数组中移出对象,对象
4000
的retainCount会减一

·向字典中添加键值对时 对象的retainCount会加一,从字典中移出对象,对象的retainCount会减一

//Block的用法,是OC中的一种语法

/**

1.block的声明

2.block的实现和赋值

3.block的调用

4.block作为函数的参数

5.block作为函数的返回值

*/

// 如果回调只有一种或两种情况的时候,使用block进行回调比较方法,如果有多种回调情况的,采用协议代理
//1.声明block的变量 : 返回值(^block变量名)(参数类型1 参数名,参数类型2 参数名); 声明时,参数名可以省略,但是不推荐省略
//Swift中声明闭包: var closure:((参数名:参数类型,参数名2:参数类型,...)->(返回值类型1,返回值类型2,...))  ={(参数名1,参数名2,...) in 闭包体 }

//使用block需要注意的问题:
//1.声明block类型的属性时,修饰的关键词 copy
//2.block要避免闭环强引用
void(^blockName)(NSString * str,BOOL success);


// 省略参数的写法:void(^blockName1)(NSString *,BOOL);

//2.block的实现和赋值
blockName = ^(NSString * str,BOOL success){
//block的实现部分,block体
//声明和赋值时,block体中的代码都不会执行
NSLog(@"执行blokc体中的代码");
};
//3.调用block
blockName(@"bwrgrets",YES);
//4.block作为函数的参数
int(^useBlock)(NSString *) = ^(NSString * str){
NSLog(@"调用blokc str = %@",str);
return 0;
};

//调用函数
[self useAblock:useBlock];
[self useAblock:^int(NSString *str) {


// block 体

NSLog(@”哈哈哈”);

return 1;

}];

//5:block作为函数的返回值
void(^getBlock)() = [self returnABlock];
//调用返回的block
getBlock();


//采用self.myBlock 对block属性赋值,myBlock声明时内存相关的关键词是 copy ,所有调用setter方法是,self对block实现部分进行了一次强引用

//解决闭环强引用:让block对当前对象的引用变成弱引用,用一个当前类的弱引用类型指针pName指向self,在block体中使用pName去代替self
__weak NewViewController *pName = self;
__unsafe_unretained NewViewController * p = self;
//__weak 修饰,对象被释放之后,pName会被置为nil,不会造成野指针,比较安全,只能在ARC环境中使用
//__unsafe_unretained修饰,对象被释放之后,p不会置为nil,会造成野指针,可能会造成程序崩溃,ARC/MRC环境中都能使用
self.myBlock = ^(NSString *str){
NSLog(@"什么都不做");
NSLog(@"name = %@",pName.name);
//在blcok体中 使用的对象,都会被block 进行拷贝,一次强应用,我们调用了self.name,这是block对self进行一次强引用
};


————————

代理:

主动类(给别人东西的类):制定协议(协议构成:当前类的名字+delegate),生成id类型的属性,调用协议方法 (注意:delegate的修饰词是assign,目的是防止循环引用)

被动类(接收东西的类):遵守协议,将自己设置成主动类的代理类,实现协议方法

例题:用代理实现从配置界面回到主界面时,改变主界面中一个按钮的大小为40号字体

思路:当两个类之间有需求关系的时候,往往用到代理。先确定好主动类和被动类(主动类:关键是id的属性和协议 被动类:声明协议和实现协议),发出命令的一般是主动类,即主动类有需求;执行命令的一般是被动类

沙盒:应用程序的所在地

里面共有三个文件夹

Documents:放到是用户请求的到的数据和需要长期保存的数据

libaray:存放的程序的系统设置,默认设置等

tmp:存放的是临时文件

·OC 中的拓展方法:类别、协议、延展、继承

//用类别可以添加属性,但是实现的时候要借助runtime 添加键值对和访问权限(在类别中添加属性,只是声明了setter 和 getter ,但是在类别的实现部分,系统并不会真正的去 实现这两个方法)

.h文件

@property (nonatomic, copy) NSString * subject;

.m文件

-(void)setSubject:(NSString *)subject{

objc_setAssociatedObject(self, “subject”, subject, OBJC_ASSOCIATION_COPY_NONATOMIC);

//OBJC_ASSOCIATION_COPY_NONATOMIC 非原子操作,copy修饰属性

}

-(NSString *)subject{

return objc_getAssociatedObject(self, “subject”);

}

//延展:选择性公开在原类实现文件中声明的成员变量、属性、和方法

单例:

指的是某个类的对象,在整个程序运行期间,只被创建一次,并且在整个程序运行期间都不会被销毁

使用单例的优点:不用多次创建对象、整个工程都可以访问这个对象的数据,实现数据共享

缺点:单例对象在程序运行期间都不会被销毁,很多时候都占用内存,内存泄露问题(在工程中谨慎使用单例模式)

static Person * p = nil;

@implementation Person

//OC中最简单的单例实现方式,但是并不推荐这样去写,多线程环境下,这样是不能保证线程安全

+(instancetype)sharePerson{

if(!p){
p = [[self alloc]init];
}
return p;


}

+(instancetype)defaultPerson{

//使用关键字对对象加锁,保证线程安全,这是苹果推荐的单例实现方法之一

@synchronized (p) {

if(p == nil){

p = [[Person alloc]init];

}

}

return p;

}

+(instancetype)sharePerson1{

//采用GCD dispatch_once 保证创建对象的代码在整个程序运行期间只被执行一次

static dispatch_once_t onceToken;

dispatch_once(&onceToken, ^{

if(p == nil){

p = [[Person alloc]init];

}

});

return p;

}

//1.什么是代理设计模式/简述一下你对代理设计模式的认识

//2.使用代理设计模型应该注意什么问题

//代理设计模式的三要素

/**

1.委托方:想要到达某种目的,而自身做不到,想要通过其他的对象帮助自己来完成操作;声明delegate属性

2.代理方:能完成某种特定功能的对象,但是这些方法,通常不由自己触发,而是通过委托方调用触发

3.协议:约定了委托方能够调用的方法,以及代理方要失效的方法

*/

/**实现协议代理的步骤

1.首先明确委托方,有委托方根据自己要实现的功能,拟定协议方法

2.明确代理方:实现协议方法,接受委托方的委托

3.委托方和代理方建立代理关系 :委托方的delegate 属性 指向 代理方来完成

4.委托方调用协议方法

5.代理方法执行协议方法

*/

@required//使用@required修饰的协议方法,要求代理对象必须实现

-(void)teach:(NSString *)subject;

@optional//使用@optional修饰的协议方法,代理方可以选实现
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: