- 设计模式相关:
设计模式是一种编码经验, 就是以比较成熟的逻辑去处理某一类型的事情. 架构模式: (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)- viewWillAppearview即将显示; (6)- updateViewConstrains:更新view的约束; (7)- viewWillLayoutSubviews; (8)- viewDidLayoutSubviews:; (9)- viewDidAppear:视图已经完全展示; (10)- viewWillDisappear:视图即将消失; (11)- viewDidDisappear:视图已经完全消失; (12)dealloc.











网友评论