招聘靠谱的ios上

非作者原著 来自摘抄

靠谱的ios

什么情况下使用weak 关键字 相比于assign有什么不同

- 什么情况使用weak关键字
  1. 在arc中 在有可能出现循环引用的时候 往往要通过让其中一端使用weak来
解决 比如 delegate代理属性
  2.自身已经对它进行一次强引用 没有必要再强引用一次 此时也会使用weak 自
定义IBOutlet控件属性一般也使用weak 当然 也可以使用strong
- 不同点
  1. weak此特质表明该属性定义了一种"非拥有关系" 为这种属性设置新值时 设
置方法既不保留新值 也不释放旧值 此特质同assign类似 然而在属性所指的对象
遭到摧毁时 属性值也会清空 而assign的"设置方法"只会执行针对"纯量类型"(列
如 CGFloat  NSInteger 等)的简单赋值操作
  2.assign可以用非OC对象 而weak必须用于OC对象

@property 的本质是什么?ivar、getter、setter 是如何生成并添加到这个类中的

实例变量 + 存取方法
完成属性定义后 编译器会自动编写访问这些属性所需的方法 叫做"自动合成" 
这个过程由编译器在编译期间执行 除了生成方法代码getter setter之外 编
译器还要自动向类中添加适当类型的实例变量 并且在属性名前面加下划线 以此
作为实例变量的名字 

@protocol 和 category 中如何使用@property

- 在protocol 中使用property 只会生成setter 和 getter 方法声明 我们
使用属性的目的 是希望遵守我协议的对象能实现该属性
- category 使用property 也是只会生成 setter和 getter方法的声明 如
果要给category添加属性的实现  需要借助objc_setAssociatedObject 和
objc_getAssociatedObject 两个运行时的函数

runtime 如何实现weak属性 不理解

property中有哪些关键字 @property后面可以有哪些修饰符

属性可以拥有的特质分为四类
    - 原子性 --- nonatomic 特质
      在默认情况下 由编译器合成的方法会通过锁定机制确保其原子性 如果
      属性具备nonatomic特质 则不使用自旋锁 "请注意"  尽管没有名为
      "atomic"的特质(如果其属性不具备nonatomic 特质 那它就是"原子
      的"(atomic)) 但是 仍然可以在属性特质中写明这一点 编译器不会报
      错 若是自己定义存取方法 那么就应该遵从与属性特质相符的原子性
    - 读/写权限 --- readwrite(读写) readonly(只读)
    - 内存管理语义 --- assign strong weak unsafe_unretained copy
    - 方法名 --- getter =<name> setter = <name>
setter = <name> 用在特殊的环境下 
在数据反序列化 转模型的过程中 服务器返回的字段如果以init开头 需要定义
一个init开头的属性 但默认生成的setter和getter也会以init开头 而编译器
会把所有以init开头的方法当成初始化方法 而初始化方法只能返回self 类型 
因此编译器会报错
@property(nonatomic,strong,getter= p_initBy,setter=setP_initBy:)
NSString *initBy;
还可以使用关键字进行特殊说明 避免编译器报错
@property(nonatomic,readwrite,copy,null_resettable) NSString *
initBy;
- (NSString *)initBy__attribute__((objc_method_family(none)));

weak属性需要在dealloc中置nil么

不需要
在ARC环境无论是强引用还是弱指针都无需在dealloc设置为nil ARC会自动帮
我们处理

在属性所指的对象遭到摧毁时 属性值也会清空

@synthesize 和 @dynamic 分别有什么作用

- @property 有2个对应的词 一个是 @dynamic。如果 @synthesize和 
@dynamic都没写,那么默认的就是@syntheszie var = _var
- @synthesize 的语义是如果你没有手动实现setter和getter方法 那么编译
器会自动为你加上这2个方法
- @dynamic 告诉编译器 属性的setter和getter 方法由用户自己实现 不自
动生成(当然对于readonly的属性只需提供getter即可) 
假如一个属性被声明为 @dynamic var,然后你没有提供 @setter方法和 
@getter 方法,编译的时候没问题,但是当程序运行到 instance.var = 
someVar,由于缺 setter 方法会导致程序崩溃;或者当运行到 someVar = 
var 时,由于缺 getter 方法同样会导致崩溃。编译时没问题,运行时才执行
相应的方法,这就是所谓的动态绑定

@synthesize 合成实例变量的规则是什么? 假如property名为foo 存在一个名为_foo的实例变量 那么还会自动合成新变量么

实例变量 = 成员变量 = ivar
如果使用了属性的话 那么编译器就会自动编写访问属性所需的方法 此过程叫做
"自动合成" 
@synthesize 合成实例变量的规则
1.如果指定了成员变量的名称 会生成一个指定的名称的成员变量
2.如果这个成员已经存在了就不再生成了
3.如果是@synthesize foo; 还会生成一个名称为foo的成员变量
也就是说
> 如果没有指定成员变量的名称会自动生成一个属性同名的成员变量
4.如果是@synthesize foo = _foo; 就不会生成成员变量了
2056006-21e2263cf017f4b3
image

在有了自动合成属性实例变量之后 @synthesize还有那些使用场景

什么情况下不会autosynthesis(自动合成)
1.同时重写了setter 和getter
2.重写了只读属性的getter
3.使用了@dynamic
4.在@protocol中定义了所有属性
5.在category中定义了所有属性
6.重载属性 (在子类中重载了父类中的属性 必须使用@synthesize来手动
合成ivar)

objc中向一个nil对象发送消息将会发生什么

在oc中向nil发送消息时完全有效的 -------只是在运行时不会有任何作用
1.如果一个方法返回值是一个对象 那么发送给nil的消息将返回0(nil)
2.如果方法返回值为指针类型 其指针大小为小于或者等于sizeof(void *), 
float, double, long double或者long long的整型标量 发送给nil的消息
将返回0 
3.如果方法返回值为结构体 发送给nil的消息将返回0 结构体中各个字段的值
将都是0
objc是动态语言 每个方法在运行时会被动态转为消息发送
objc在向一个对象发送消息时 runtime库会根据对象的isa指针找到该对象实
际所属的类 然后在该类中的方法列表以及其父类方法列表中寻找方法运行 然后
在发送消息的时候 objc_msgSend方法不会返回值 所谓的返回内容都是具体
调用时执行的
如果向一个nil对象发送消息 首先在寻找对象的isa指针时就是0地址返回了

objc中向一个对象发送消息[objc foo] 和objc_msgSend()之间有什么关系

方法编译之后就是objc_msgSend()函数调用

什么时候会报unrecognized selector的异常

当调用该对象上某个方法 而该对象上没有实现这个方法的时候 可以通过"消息
转发"进行解决
objc在向一个对象发送消息时,runtime库会根据对象的isa指针找到该对象实
际所属的类,然后在该类中的方法列表以及其父类方法列表中寻找方法运行,如
果,在最顶层的父类中依然找不到相应的方法时,程序在运行时会挂掉并抛出异
常unrecognized selector sent to XXX 。但是在这之前,objc的运行时会
给出三次拯救程序崩溃的机会
1.Method resolution
 objc运行时会调用 +resolveInstanceMethod:或者 +resolveClassMethod
让你有机会提供一个函数实现 如果你添加了函数 那运行时系统就会重新启动
一次消息发送的过程 否则 会进入消息转发
2. Fast forwarding
如果目标对象实现了 -fowardingTargetForSelector:  Runtime这时就会调
用这个方法 给你把这个消息转发给其他对象的机会  只要这个方法返回的不是
nil和self 整个消息发送的过程就会被重启 当然发送的对象就会变成你返回的
对象 否则 则会继续Normal Fowarding 这里叫Fast,只是为了区别下一步的
转发机制。因为这一步不会创建任何新的对象,但下一步转发会创建一个
NSInvocation对象,所以相对更快点
3.Normal fowarding
首先它会发送-methodSignatureForSelector:消息获得函数的参数和返回值
类型。如果-methodSignatureForSelector:返回nil,Runtime则会发出
-doesNotRecognizeSelector:消息,程序这时也就挂掉了。如果返回了一个
函数签名,Runtime就会创建一个NSInvocation对象并发送
-forwardInvocation:消息给目标对象

一个objc对象如何进行内存布局(考虑有父类的情况)

- 所有父类的成员变量和自己的成员变量都会存放在该对象所对应的存储空间中
- 每一个对象内部都有一个isa指针 指向他的类对象 类对象中存放着本对象的
      1.对象方法列表(对象能够接收到的消息列表 保存在它所对应的类对象
        中)
      2.成员变量的列表
      3.属性列表
他内部也有一个isa指针指向元对象(meta class) 元对象内部存放的是类方法
列表 类对象内部还有一个superclass的指针 指向他的父类对象
2056006-0720f90c4c72ba35
image
- 根对象就是NSObject,它的superclass指针指向nil
- 类对象既然称为对象,那它也是一个实例。类对象中也有一个isa指针指向它
的元类(meta class),即类对象是元类的实例。元类内部存放的是类方法列表
根元类的isa指针指向自己,superclass指针指向NSObject类。
2056006-3a84a761c741611a
image

一个objc对象的isa的指针指向什么 有什么作用

指向他的类对象 从而可以找到对象上的方法

runtime如何通过selector找到对应的IMP地址

每一个类对象都有一个方法列表 方法列表中记录着方法的名称 方法实现 以及
参数类型 其实selector本质就是方法名称 通过这个方法名称就可以在方法列
表中找到对应的方法实现

使用runtime Associate方法关联的对象 需要在主对象dealloc的时候释放么

无论在MRC下还是ARC下均不需要
对象的内存销毁时间表
  - 调用 -release  引用计数变为0
    * 对象正在被销毁 生命周期即将结束
    * 不能再有新的 __weak 弱引用 否则将指向nil
    * 调用 [self dealloc]
  - 子类 调用 -dealloc
    * 继承关系中最底层的子类 在调用 -dealloc
    * 如果是MRC代码  则会手动是否实例变量们
    * 继承关系中每一层的父类 都在调用 -dealloc
  - NSObject 调 -dealloc 
    * 只做一件事  调用 objective-C  runtime中的object_dispose()
  - 调用 object_dispose()
    * 为C++的实例变量们 调用 destructors
    * 为ARC状态下的实例变量们调用 -release
    * 解除所有使用 runtime Associate方法关联的对象
    * 解除所有 __weak 引用
    * 调用 free()

objc 中的类方法和实例方法有什么本质区别和联系

类方法:

类方法是属于类对象的
类方法只能通过类对象调用
类方法中的self是类对象
类方法可以调用其他的类方法
类方法中不能访问成员变量
类方法中不能直接调用对象方法
实例方法:

实例方法是属于实例对象的
实例方法只能通过实例对象调用
实例方法中的self是实例对象
实例方法中可以访问成员变量
实例方法中直接调用实例方法
实例方法中也可以调用类方法(通过类名)

猜你喜欢

转载自blog.csdn.net/weixin_33921089/article/details/87165711