iOS 日常小知识点总结

defineconst常量有什么区别

define在预处理阶段进行替换, const常量在编译阶段使用;
宏不做类型检测,仅仅进行替换, const常量有数据类型,会执行类型检测;
define不能调试,const常量可以调试;
define定义的常量在替换后运行过程中会不断的占用内存, 而const定义的常量存储在数据段只有一分copy,效率更高
define可以进行定义一些简单的函数, const不可以;


atomic一定是线程安全吗? nonatomic一定线程不安全吗?

这个问题, 看怎么理解, atomic修饰的属性, 保证它的settergetter方法一定是线程安全, 但是这个属性的相关操作不是线程安全的;其本质是在gettersetter中添加@synchronized()保证安全;
nonatomic则一定是不安全的;
例子:一个atomic修饰的NSMutableArray *muArr; 则muArrgettersetter一定是线程安全的, 但是对这个数组的相关操作例如[muArr addObject]之类的都不是线程安全的;atomic能保证getter时取到一个完整点值;


结构体和类的区别:

结构体
只能封装属性 能封装属性和方法
分配在栈区,空间小,但是效率高;如果在结构体中赋值很多属性,会降低程序运行的效率 分配在堆区,空间较大但是读取效率低
结构体直接赋值 赋值的是对象的指针

@dynamic@synthesize比较

@dynamic关键字: 表示必须要自己实现gettersetter方法;
@synthesize关键字: 表示系统会自动生成gettersetter方法, 如果自己实现了就会替换掉系统的;


NSCacheNSDictionary的优点:

  1. NSCache采用LRU规则, 会对超出限制的数据进行清除;
  2. NSCache会在系统内存很低时自动释放一些对象;
  3. NSCache是线程安全的;不需要对cache加锁;
  4. NSCachekey只是做强引用, 不需要实现NSCoping协议;

编译和链接的过程:

C++, OC都是编译类型语言,在执行时需要先通过编译器生成机器码,机器码可以直接在CPU上执行,所以效率比较高;
Python, JS都是直译式语言, 不需要经过编译的过程, 而是在执行的时候通过一个中间的解释器将代码解释为CPU可以执行的代码;所以直译型语言的效率低一些, 但是编写效率高;
以下以OC为例:
1.编译器前端的任务:语法分析, 语义分析, 生成中间代码, 在这个过程中会进行类型检查, 如果发现错误和警告会标注出哪行;
2.编译器后端的任务:进行机器无关的代码优化, 生成机器语言, 并进行机器相关的代码优化;
以打印一行”hello world”为例需要四个步骤:预处理, 编译, 汇编, 链接;


去掉导航条下方的线

[self.navigationController.navigationBar setBackgroundImage:[[UIImage alloc] init] forBarMetrics:UIBarMetricsDefault]; self.navigationController.navigationBar.shadowImage = [[UIImage alloc] init];


@property的本质:

在编译阶段由编译器自动帮我们生成ivar成员变量,getter方法, setter方法

@property = ivar + getter + setter; “属性” (property)有两大概念:ivar(实例变量)、getter+setter(存取方法)
“属性” (property)作为 Objective-C 的一项特性,主要的作用就在于封装对象中的数据。
Objective-C 对象通常会把其所需要的数据保存为各种实例变量。
实例变量一般通过“存取方法”(access method)来访问。
其中,“获取方法” (getter)用于读取变量值,而“设置方法” (setter)用于写入变量值。


NSDictionary的实现原理?

通过方法- (void)setObject:(id)anObject forKey:(id)aKey;进行存储, 底层是基于哈希表(又称为散列表)的key-value映射存储; 本质上是一个数组在存储, 每一个元素存储着键值对的信息;

hash的存储过程

  1. 通过key进行hash运算出哈希值h;
  2. 假设散列表长度为n, 则这个键值对应该存储的位置是h%n
  3. 如果这个位置已经被存储了, 则用开放寻址法或者拉链法进行解决冲突;

如果对散列表的原理完全不懂的, 建议看下入门课程陆军工程大学的公开课第四周

哈希表的负载因子

它被用来衡量哈希表的满/空程度;
负载因子=键值对总数/散列表长度; 当值大于某个值后哈希表再次扩展空间, 一般是双倍空间, 因此即使原先的键值对的hash不会变由于散列表的长度变化, 也会导致其所在链表存储位置发生变化, 这个过程成为重哈希;

如果用拉链法(上文中所说存储时所用的数组, 数组元素中存储链表, 将取模冲突的键值对依次排列在链表中)解决冲突时; 哈希表扩容后,其实并不能有效提高查找效率;因为每个键值对仍然存储在链表中, 链表的长度也没变化, 只是位置改变了;


各个APP之间有什么通信的方式?

  1. URLScheme
  2. KeyChain
  3. UIPasteboard
  4. 隔空投送
  5. UIActivityViewController分享

你可能感兴趣的:(iOS 日常小知识点总结)