- 设计模式相关:
设计模式是一种编码经验, 就是以比较成熟的逻辑去处理某一类型的事情. 架构模式: (1).MVC (2).MVVM (3)MVP (4)VIPER MV(X)系列详解 英文原文->
iOS中常用设计模式: (1). 单例模式: 通过
static
关键字及dispatch_once
保证单列在程序运行期间只会被初始化一次. (2). KVO: 通过runtime动态生成一个新的类, 并重写被观察对象属性的setter
方法, 来监听对象属性的改变 (3). 委托模式: protrcol + delegate (4).工厂模式: 通过一个类方法, 批量根据已有模板生产对象.
-
#import
和#incloud
的区别,@class
作用?
#import
和#incloud
都是用来导入头文件.#incloud
是C/C++中用来导入头文件的关键字;#import
是Objective-C中用来导入头文件的关键字, 通过预编译指令来防止文件多次导入;@class
用来告诉编译器某个类的声明, 到运行时才去查看类的实现文件(.m
), 可以解决头文件的相互包含.
-
frame
和bounds
的区别?
frame
是 自身在父view
坐标系统中的位置和大小,bounds
是自身在自己的坐标系统中的位置和大小
- Objective-C的类可以多重继承么?Category是什么? Category重写本类方法后,为什么本类方法不再执行, 是被替换了吗?
Objective-C
的类是不可以多继承的.Category
分类, 其中的方法会在运行时动态的添加到本类的method_list
中,Category
不能添加属性, 原因是无法在运行时本列的ivar_list
大小已经确定, 无法动态的去添加_ivar
, 可以通过动态绑定objc_associated
来添加属性. 因为在运行时中, 本类的方法会先放入method_list
中去,Category
中添加的方法, 会进行memory_copy
放入method_list
中, 排在本类方法的前边, 如果和本类方法重名, 那么在调用的时候, 找到Category
中添加的方法后就会返回调用. 所以并不是被替换,而是根本就没有调用到本类的方法去;
-
@property
的本质是什么?
@property
本质就是_ivar
、setter
、getter
. 属性的本质就是一个带_
的实例变量 +setter``getter
存取方法. 一般们调用的时候尽量直接调用_ivar
, 这样的好处是能够直接对实例变量进行赋值和读取,不用再经过存取方法
-
@property
有什么属性关键字?都有什么作用?
(1): 原子性关键字:
atomic
-- 默认. 原子性, 当属性被atomic
修饰时,系统生成的setter
和getter
方法中, 会进行加锁操作, 这样可以保证数据的完整性, 但并不能保证一定是线程安全的. 相较于nonatomic
而言, 内存消耗更大.nonatomic
-- 非默认. 非原子性, 更快, 若多个线程同时访问, 则结果无法预料.
(2)读写权限:readwrite
-- 默认. 可读写, 系统会自动生成setter
和getter
方法readonly
-- 非默认. 只可读, 系统只会生成getter
方法, 不希望属性在类外改变
(3)内存管理语义:assign
:-- 赋值特性, 进行简单的赋值操作retain(MRC)/strong(ARC)
: -- 持有特性,setter
方法会将传入的参数先保留, 再赋值. 传入参数的retainCount
会+1copy
:-- 表示copy特性,setter
方法会将传入参数复制一份, 常用于NSString, NSArray, NSDictionary
等, 不论传入参数是否是可变对象, 自身持有的那一份保证不可变的属性.weak
-- 表示一种非拥有关系
,weak
在属性所指的对象被销毁时, 属性的值会被自动清空 weak底层实现
- 系统对象的
copy
、mutableCopy
和深拷贝、浅拷贝
- 非集合类对象的
copy
、mutableCopy
:
//!< 非集合类不可变对象:
NSString *str = @"hello word";
id copyStr = [str copy];
id mutableCopyStr = [str mutableCopy];
NSLog(@"str:%p class:%@ \n copyStr:%p class:%@ \n mutableCopyStr:%p class:%@", str, [str class], copyStr, [copyStr class], mutableCopyStr, [mutableCopyStr class]);
//!< 非集合类可变对象:
NSMutableString *str1 = [[NSMutableString alloc] initWithFormat:@"hello word"];
id copyStr1 = [str1 copy];
id mutableCopyStr1 = [str1 mutableCopy];
NSLog(@"str1:%p class:%@ \n copyStr1:%p class:%@ \n mutableCopyStr1:%p class:%@", str1, [str1 class], copyStr1, [copyStr1 class], mutableCopyStr1, [mutableCopyStr1 class]);
- 结果:
2019-04-23 16:57:57.185947+0800 JSOCInteraction[17107:6685981] str:0x102ef43b8 class:__NSCFConstantString
copyStr:0x102ef43b8 class:__NSCFConstantString
mutableCopyStr:0x6000001d2ac0 class:__NSCFString
2019-04-23 16:57:57.186221+0800 JSOCInteraction[17107:6685981] str1:0x6000001cbf00 class:__NSCFString
copyStr1:0x600000fc5660 class:__NSCFString
mutableCopyStr1:0x6000001cbdb0 class:__NSCFString
由上述代码可以看出, 对非集合类不可变对象进行copy
是浅拷贝
, 只复制了对象的指针, 而mutableCopy
是深拷贝
, 拷贝出了一份新的可变对象和一份指针; 对非集合类可变对象进行copy
和mutableCopy
都是深拷贝
- 集合类对象的
copy
和mutableCopy
:
NSArray *arr = @[];
id copyArr = [arr copy];
id mutableCArr = [arr mutableCopy];
NSLog(@"arr:%p class:%@ \n \tcopyArr:%p class:%@ \n \tmutableCArr:%p class:%@", arr, [arr class], copyArr, [copyArr class], mutableCArr, [mutableCArr class]);
NSMutableArray *muArr = [NSMutableArray new];
id copyMuArr = [muArr copy];
id mutableCMuArr = [muArr mutableCopy];
NSLog(@"muArr:%p class:%@ \n \tcopyMuArr:%p class:%@ \n \tmutableCMuArr:%p class:%@", muArr, [muArr class], copyMuArr, [copyMuArr class], mutableCMuArr, [mutableCMuArr class]);
- 结果:
2019-04-23 16:57:57.186472+0800 JSOCInteraction[17107:6685981] arr:0x600000d88030 class:__NSArray0
copyArr:0x600000d88030 class:__NSArray0
mutableCArr:0x6000001cbf00 class:__NSArrayM
2019-04-23 16:57:57.187073+0800 JSOCInteraction[17107:6685981] muArr:0x6000001cbdb0 class:__NSArrayM
copyMuArr:0x600000d88030 class:__NSArray0
mutableCMuArr:0x6000001cbc00 class:__NSArrayM
由结果可见: 对不可变的集合类对象(NSArray, NSDictionary等
)进行copy
是浅拷贝
; 进行mutableCopy
是深拷贝
; 不过只是单层深拷贝
, 即只对对象本身进行深拷贝
, 集合中的元素还是指针拷贝
; 对可变集合类对象进行copy
和mutableCopy
都是进行了单层深拷贝
.
- 如何让自己的类用 copy 修饰符?
@interface WKCopyObject ()<NSCopying, NSMutableCopying>
@property (nonatomic, copy) NSString *name;
@end
- (id)copyWithZone:(NSZone *)zone {
WKCopyObject *obj = [[[self class] alloc] init];
obj.name = self.name;
return obj;
}
- (id)mutableCopyWithZone:(NSZone *)zone {
WKCopyObject *obj = [[[self class] alloc] init];
obj.name = self.name.mutableCopy;
return obj;
}
-
autoreleasepool
的实现原理与释放时机?
我们使用clang指令对
main.m
进行rewrite
, 得到main.cpp
文件:clang -rewrite-objc main.m
, 可以看到有关autoreleasepool
的关键代码:
extern "C" __declspec(dllimport) void * objc_autoreleasePoolPush(void);
extern "C" __declspec(dllimport) void objc_autoreleasePoolPop(void *);
struct __AtAutoreleasePool {
__AtAutoreleasePool() {atautoreleasepoolobj = objc_autoreleasePoolPush();}
~__AtAutoreleasePool() {objc_autoreleasePoolPop(atautoreleasepoolobj);}
void * atautoreleasepoolobj;
};
可以看到
autoreleasepool
是一个由objc_autoreleasePoolPush()
、objc_autoreleasePoolPop()
和一个atautoreleasepoolobj
组成的结构体苹果开源代码
- viewController的生命周期?
(
1
)- initWithNibName:bundle:
(通过.nib创建/init创建时调用,init
创建时, 也是调用- initWithNibName:bundle:
, 只不过参数全部传入nil); (1-1
)- initWithCoder:
(storyboard
创建时, 那个storyboard
会在自己内部生成一个nib
, 将nib
放入一个coder
中); (2
)- awakeFromNib:
; (3
)- loadView:
当需要用到view的时候,但是view还没有初始化时会调用; (4
)- viewDidLoad:
view已经加载完毕; (5
)- viewWillAppear
view即将显示; (6
)- updateViewConstrains:
更新view的约束; (7
)- viewWillLayoutSubviews
; (8
)- viewDidLayoutSubviews:
; (9
)- viewDidAppear:
视图已经完全展示; (10
)- viewWillDisappear:
视图即将消失; (11
)- viewDidDisappear:
视图已经完全消失; (12
)dealloc
.
网友评论