iOS面试题梳理(二)

继续.....

循环引用的产生原因,以及解决方法

1.产生原因:如下图所示,对象A和对象B相互引用了对方作为自己的成员变量,只有自己销毁的时候才能将成员变量的引用计数减1。对象A的销毁依赖于对象B的销毁,同时对象B销毁也依赖与对象A的销毁,从而形成循环引用,此时,即使外界没有任何指针访问它,它也无法释放。

2.多个对象间依然会存在循环引用问题,形成一个环,在编程中,形成的环越大越不容易察觉,如下图所示:

解决方法:

1,事先知道存在循环引用的地方,在合理的位置主动断开一个引用,是对象回收;

2.使用弱引用的方法。

KeyPath、KVC、KVO

键路径(KeyPath):

1.在一个给定的实体中,同一个属性的所有值具有相同的数据类型。

2.键-值编码技术用于进行这样的查找,它是一种间接访问对象属性的机制。 键路径是一个由用点作分隔符的键组成的字符串,用于指定一个连接在一起的对象性质序列。第一个键的性质是由先前的性质决定的,接下来每个键的值也是相对于其前面的性质。

3.键路径使您可以以独立于模型实现的方式指定相关对象的性质。通过键路径,您可以指定对象图中的一个任意深度的路径,使其指向相关对象的特定属性

键值编码(KVC):

1.键值编码是一种间接访问对象的属性使用字符串来标识属性,而不是通过调用存取方法,直接或通过实例变量访问的机制,非对象类型的变量将被自动封装或者解封成对象,很多情况下会简化程序代码;

2.KVC的缺点:一旦使用 KVC 你的编译器无法检查出错误,即不会对设置的键、键路径进行错误检查,且执行效率要低于合成存取器方法和自定的 setter 和 getter 方法。因为使用 KVC 键值编码,它必须先解析字符串,然后在设置或者访问对象的实例变量。

键值观察(KVO):

1.键值观察机制是一种能使得对象获取到其他对象属性变化的通知 ,极大的简化了代码。

2.实现 KVO 键值观察模式,被观察的对象必须使用 KVC 键值编码来修改它的实例变量,这样才能被观察者观察到。

Demo

比如我自定义的一个button

[self addObserver:self forKeyPath:@"highlighted" options:0 context:nil]; #pragma mark KVO 
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { 
     if ([keyPath isEqualToString:@"highlighted"] ) { 
      [self setNeedsDisplay]; } 
  }

对于系统是根据keypath去取的到相应的值发生改变,理论上来说是和kvc机制的道理是一样的。

KVC机制通过key找到value的原理

1.当通过KVC调用对象时,比如:[self valueForKey:@”someKey”]时,程序会自动试图通过下面几种不同的方式解析这个调用;

2.首先查找对象是否带有 someKey 这个方法,如果没找到,会继续查找对象是否带有someKey这个实例变量(iVar),如果还没有找到,程序会继续试图调用 -(id) valueForUndefinedKey:这个方法。如果这个方法还是没有被实现的话,程序会抛出一个NSUndefinedKeyException异常错误。

3.补充:KVC查找方法的时候,不仅仅会查找someKey这个方法,还会查找getsomeKey这个方法,前面加一个get,或者_someKey以_getsomeKey这几种形式。同时,查找实例变量的时候也会不仅仅查找someKey这个变量,也会查找_someKey这个变量是否存在。

4.设计valueForUndefinedKey:方法的主要目的是当你使用-(id)valueForKey方法从对象中请求值时,对象能够在错误发生前,有最后的机会响应这个请求。

Objective-C 中如何实现 KVO

1.注册观察者(注意:观察者和被观察者不会被保留也不会被释放)

- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath 
options:(NSKeyValueObservingOptions)options 
context:(void *)context;

2.接收变更通知

- (void)observeValueForKeyPath:(NSString *)keyPath 
ofObject:(id)object change:(NSDictionary *)change   context:(void *)context;

3.移除对象的观察者身份

- (void)removeObserver:(NSObject *)observer 
forKeyPath:(NSString *)keyPath;

3.KVO中谁要监听谁注册,然后对响应进行处理,使得观察者与被观察者完全解耦。KVO只检测类中的属性,并且属性名都是通过NSString来查找,编译器不会检错和补全,全部取决于自己。

代理的作用(Delegate)

1.代理又叫委托,是一种设计模式,代理是对象与对象之间的通信交互,代理解除了对象之间的耦合性。

2.改变或传递控制链。允许一个类在某些特定时刻通知到其他类,而不需要获取到那些类的指针。可以减少框架复杂度。

3.另外一点,代理可以理解为java中的回调监听机制的一种类似。

4.代理的属性常是assign的原因:防止循环引用,以至对象无法得到正确的释放。

NSNotification、Block、Delegate和KVO的区别

1.代理是一种回调机制,且是一对一的关系,通知是一对多的关系,一个对向所有的观察者提供变更通知;

2.效率:Delegate比NSNOtification高;

3.Delegate和Block一般是一对一的通信;

4.Delegate需要定义协议方法,代理对象实现协议方法,并且需要建立代理关系才可以实现通信;

5.Block:更加简洁,不需要定义繁琐的协议方法,但通信事件比较多的话,建议使用Delegate;

Objective-C中可修改和不可以修改类型

1.可修改不可修改的集合类,就是可动态添加修改和不可动态添加修改。

2.比如NSArrayNSMutableArray,前者在初始化后的内存控件就是固定不可变的,后者可以添加等,可以动态申请新的内存空间.

当我们调用一个静态方法时,需要对对象进行 release 吗?

不需要,静态方法(类方法)创建一个对象时,对象已被放入自动释放池。在自动释放池被释放时,很有可能被销毁。

当我们释放我们的对象时,为什么需要调用[super dealloc]方法,它的位置又是如何的呢?

因为子类的某些实例是继承自父类的,因此需要调用[super dealloc]方法, 来释放父类拥有的实例,其实也就是子类本身的。一般来说我们优先释放子类拥 有的实例,最后释放父类所拥有的实例。

谓词的认识

Cocoa 中提供了一个NSPredicate的类,该类主要用于指定过滤器的条件, 每一个对象通过谓词进行筛选,判断条件是否匹配。如果需要了解使用方法,请看谓词的具体使用.

static、self、super关键字的作用

1.函数体内static变量的作用范围为该函数体,不同于auto变量,该变量的内存只被分配一次,因此其值在下次调用时仍维持上次的值.

2.在模块内的 static 全局变量可以被模块内所用函数访问,但不能被模块外其它函数访问.

3.在模块内的static函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明.

4.在类中的static成员变量属于整个类所拥有,对类的所有对象只有一份拷贝.

5.self:当前消息的接收者。

6.super:向父类发送消息。

#include与#import的区别、#import 与@class 的区别

  1. #include#import其效果相同,都是查询类中定义的行为(方法);
  2. #import不会引起交叉编译,确保头文件只会被导入一次;
  3. @class 的表明,只定 义了类的名称,而具体类的行为是未知的,一般用于.h 文件;
  4. @class#import 编译效率更高。
  5. 此外@class#import 的主要区别在于解决引用死锁的问题。

@public、@protected、@private 它们的含义与作用

  1. @public:对象的实例变量的作用域在任意地方都可以被访问 ;
  2. @protected:对象的实例变量作用域在本类和子类都可以被访问 ;
  3. @private:实例变量的作用域只能在本类(自身)中访问 .

解释 id 类型

任意类型对象,程序运行时才决定对象的类型。

switch 语句 if 语句区别与联系

均表示条件的判断,switch语句表达式只能处理的是整型、字符型和枚举类型,而选择流程语句则没有这样的限制。但switch语句比选择流程控制语句效率更高。

isMemberOfClass 和 isKindOfClass 联系与区别

1.联系:两者都能检测一个对象是否是某个类的成员

2.区别:isKindOfClass 不仅用来确定一个对象是否是一个类的成员,也可以用来确定一个对象是否派生自该类的类的成员 ,而isMemberOfClass 只能做到第一点。

3.举例:如 ClassA派 生 自NSObject 类 , ClassA *a = [ClassA alloc] init];,[a isKindOfClass:[NSObject class]] 可以检查出 a 是否是 NSObject派生类 的成员,但 isMemberOfClass 做不到。

iOS 开发中数据持久性有哪几种?

数据存储的核心都是写文件。

1.属性列表:只有NSString、NSArray、NSDictionary、NSData可writeToFile;存储依旧是plist文件。plist文件可以存储的7中数据类型:array、dictionary、string、bool、data、date、number。

2.对象序列化(对象归档):对象序列化通过序列化的形式,键值关系存储到本地,转化成二进制流。通过runtime实现自动化归档/解档,请参考这个文章。实现NSCoding协议必须实现的两个方法:

3.编码(对象序列化):把不能直接存储到plist文件中得到数据,转化为二进制数据,NSData,可以存储到本地;

4.解码(对象反序列化):把二进制数据转化为本来的类型。

5.SQLite 数据库:大量有规律的数据使用数据库。

6.CoreData :通过管理对象进行增、删、查、改操作的。它不是一个数据库,不仅可以使用SQLite数据库来保持数据,也可以使用其他的方式来存储数据。如:XML。

7.CoreData的介绍:

  • CoreData是面向对象的API,CoreData是iOS中非常重要的一项技术,几乎在所有编写的程序中,CoreData都作为数据存储的基础。
  • CoreData是苹果官方提供的一套框架,用来解决与对象声明周期管理、对象关系管理和持久化等方面相关的问题。
  • 大多数情况下,我们引用CoreData作为持久化数据的解决方案,并利用它作为持久化数据映射为内存对象。提供的是对象-关系映射功能,也就是说,CoreData可以将Objective-C对象转换成数据,保存到SQL中,然后将保存后的数据还原成OC对象。

8.CoreData的特征:

1.通过CoreData管理应用程序的数据模型,可以极大程度减少需要编写的代码数量。

2.将对象数据存储在SQLite数据库已获得性能优化。

3.提供NSFetchResultsController类用于管理表视图的数据,即将Core Data的持久化存储在表视图中,并对这些数据进行管理:增删查改。

4.管理undo/redo操纵;

5.检查托管对象的属性值是否正确。

Core Data的6成员对象

1.NSManageObject:被管理的数据记录Managed Object Model是描述应用程序的数据模型,这个模型包含实体(Entity)、特性(Property)、读取请求(Fetch Request)等。

2.NSManageObjectContext:管理对象上下文,持久性存储模型对象,参与数据对象进行各种操作的全过程,并监测数据对象的变化,以提供对undo/redo的支持及更新绑定到数据的UI。

3.NSPersistentStoreCoordinator:连接数据库的Persistent Store Coordinator相当于数据文件管理器,处理底层的对数据文件的读取和写入,一般我们与这个没有交集。

4.NSManagedObjectModel:被管理的数据模型、数据结构。

5.NSFetchRequest:数据请求;

6.NSEntityDescription:表格实体结构,还需知道.xcdatamodel文件编译后为.momd或者.mom文件。

Core Data的功能

1.对于KVC和KVO完整且自动化的支持,除了为属性整合KVO和KVC访问方法外,还整合了适当的集合访问方法来处理多值关系;

2.自动验证属性(property)值;

3.支持跟踪修改和撤销操作;

4.关系维护,Core Data管理数据的关系传播,包括维护对象间的一致性;

5.在内存上和界面上分组、过滤、组织数据;

6.自动支持对象存储在外部数据仓库的功能;

7.创建复杂请求:无需动手写SQL语句,在获取请求(fetch request)中关联NSPredicate。NSPreadicate支持基本功能、相关子查询和其他高级的SQL特性。它支持正确的Unicode编码、区域感知查询、排序和正则表达式;

8.延迟操作:Core Data使用懒加载(lazy loading)方式减少内存负载,还支持部分实体化延迟加载和复制对象的数据共享机制;

9.合并策略:Core Data内置版本跟踪和乐观锁(optimistic locking)来支持多用户写入冲突的解决,其中,乐观锁就是对数据冲突进行检测,若冲突就返回冲突的信息;

10.数据迁移:Core Data的Schema Migration工具可以简化应对数据库结构变化的任务,在某些情况允许你执行高效率的数据库原地迁移工作;

11.可选择针对程序Controller层的集成,来支持UI的显示同步Core Data在IPhone OS之上,提供NSFetchedResultsController对象来做相关工作,在Mac OS X上我们用Cocoa提供的绑定(Binding)机制来完成的。

对象可以被copy的条件

12.只有实现了NSCopyingNSMutableCopying协议的类的对象才能被拷贝,分为不可变拷贝和可变拷贝,具体区别戳这;

NSCopying协议方法

- (id)copyWithZone:(NSZone *)zone {
 MyObject *copy = [[[self class] allocWithZone: zone] init]; copy.username = [self.username copyWithZone:zone]; return copy;
}

自动释放池工作原理

1.自动释放池是NSAutorelease类的一个实例,当向一个对象发送autorelease消息时,该对象会自动入池,待池销毁时,将会向池中所有对象发送一条release消息,释放对象。

2.[pool release]、 [pool drain]表示的是池本身不会销毁,而是池子中的临时对象都被发送release,从而将对象销毁。

原文发布于微信公众号 - 攻城狮的动态(iOSDevSkills)

原文发表时间:2016-06-13

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏韩伟的专栏

框架设计原则和规范(完)

祝大家圣诞节快乐!有事没事别出门,外面太!挤!了! 此文是《.NET:框架设计原则、规范》的读书笔记,本文内容较多,共分九章,今天推送最后一章。 1. 什么是好...

29640
来自专栏大闲人柴毛毛

提高Java代码质量的Eclipse插件之Checkstyle的使用详解

CheckStyle是SourceForge下的一个项目,提供了一个帮助JAVA开发人员遵守某些编码规范的工具。它能够自动化代码规范检查过程,从而使得开发人员...

44490
来自专栏哈雷彗星撞地球

Runtime系列(一)-- 基础知识

众所周知,Objective-C 是一种运行时语言。运行时怎么来体现的呢?比如一个对象的类型确定,或者对象的方法实现的绑定都是推迟到软件的运行时才能确定的。而运...

8920
来自专栏owent

我们的Lua类绑定机制

最近一个人搞后台,框架底层+逻辑功能茫茫多,扛得比较辛苦,一直没抽出空来写点东西。

34510
来自专栏Scott_Mr 个人专栏

如何正确使用const(常量),define(宏)

29170
来自专栏SDNLAB

《P4语言规范》parser详解

前言 为深入研究P4语言相关规范及运行操作使用,本系列文章根据P4.org网站给出的《The P4 Language Specification v1.0.2》...

40990
来自专栏MelonTeam专栏

KVO实现原理

概览 本文分为两个大的方面。一、kvo的简单使用场景。二、kvo的来龙去脉,讲讲苹果的实现。 KVO 使用方法,和常用场景。 Key-value obser...

313100
来自专栏進无尽的文章

实践-小细节Ⅷ

const 这个单词翻译成中文是“常量”的意思。在程序中我们知道“常量”的值是不能变的,固定的。所以const关键字的作用就是:

12640
来自专栏Scott_Mr 个人专栏

如何正确使用const(常量),define(宏)

12020
来自专栏Android先生

Java多线程-带你认识Java内存模型,内存分区,从原理剖析Volatile关键字

地址:https://juejin.im/post/59f8231a5188252946503294

11230

扫码关注云+社区

领取腾讯云代金券