iOS-常见问题

1、 kvo & kvc

  • KVC是Key Value Coding的简称。它是一种可以通过字符串的名字(key)来访问类属性的机制。而不是通过调用Setter、Getter方法访问。关键方法定义在 NSKeyValueCodingProtocol
    KVC支持类对象和内建基本数据类型。
  • KVO:Key-Value Observing, 基于 KVC 实现。它能够观察一个对象的 KVC key path 值的变化。
    [objc addObserver:self forKeyPath:@“name” options: NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:NULL];
    当变化时会通知

2、NSNotification 和 KVO
NSNotification是通知模式,KVO的全称是键值观察(Key-value observing),其是基于KVC(key-value coding)的,KVC是一个通过属性名访问属性变量的机制。
例如将Module层的变化,通知到多个Controller对象时,可以使用NSNotification;如果是只需要观察某个对象的某个属性,可以使用KVO。

3、class方法load和initialize区别:

  • load函数调用特点如下:
    当类被引用进项目的时候就会执行load函数(在main函数开始执行之前),与这个类是否被用到无关,每个类的load函数只会自动调用一次.由于load函数是系统自动加载的,因此不需要调用父类的load函数,否则父类的load函数会多次执行。

    • 1.当父类和子类都实现load函数时,父类的load方法执行顺序要优先于子类
    • 2.当子类未实现load方法时,不会调用父类load方法
    • 3.类中的load方法执行顺序要优先于类别(Category)
    • 4.当有多个类别(Category)都实现了load方法,这几个load方法都会执行,但执行顺序不确定(其执行顺序与类别在Compile Sources中出现的顺序一致)
    • 5.当然当有多个不同的类的时候,每个类load 执行顺序与其在Compile Sources出现的顺序一致
  • initialize函数调用特点如下:
    initialize在类或者其子类的第一个方法被调用前调用。即使类文件被引用进项目,但是没有使用,initialize不会被调用。由于是系统自动调用,也不需要再调用 [super initialize] ,否则父类的initialize会被多次执行。假如这个类放到代码中,而这段代码并没有被执行,这个函数是不会被执行的。
    -1.父类的initialize方法会比子类先执行
    -2.当子类未实现initialize方法时,会调用父类initialize方法,子类实现initialize方法时,会覆盖父类initialize方法.
    -3.当有多个Category都实现了initialize方法,会覆盖类中的方法,只执行一个(会执行Compile Sources 列表中最后一个Category 的initialize方法)

3、extension和category区别

  • 形式上看:extension 是匿名的category
  • extension中声明的方法需要在implementation中实现,而category 不做强制要求
  • extension 可以添加属性、成员变量,而category 一般不可以。

详解:

  • category
    • 1.是运行期决议的
    • 2.类扩展可以添加实例变量,分类不能添加实例变量
      原因:因为在运行期,对象的内存布局已经确定,如果添加实例变量会破坏类的内部布局,这对编译性语言是灾难性的。
    • 3.category的其他几个使用场景:
      • 1、模拟多继承
      • 2、framework的私有方法公开
  • extension
    • 1.在编译器决议,是类的一部分,在编译器和头文件的@interface和实现文件里的@implement一起形成了一个完整的类。
    • 2.伴随着类的产生而产生,也随着类的消失而消失。
    • 3.extension一般用来隐藏类的私有消息,你必须有一个类的源码才能添加一个类的extension,所以对于系统一些类,如nsstring,就无法添加类扩展

4、property 默认关键字

  • readwrite 此标记说明属性会被当成读写的,这也是默认属性。
  • readonly 此标记说明属性只可以读,也就是不能设置,可以获取。
  • assign 不会使引用计数加1,也就是直接赋值。
  • retain 会使引用计数加1。
  • copy 建立一个索引计数为1的对象,在赋值时使用传入值的一份拷贝。
  • nonatomic 非原子性访问,多线程并发访问会提高性能。
  • atomic 原子性访问。,atomic 的本意是指属性的存取方法是线程安全的,并不保证整个对象是线程安全的。
  • strong 打开ARC时才会使用,相当于retain。
  • weak 打开ARC时才会使用,相当于assign,可以把对应的指针变量置为nil。

5、ios9以后的新增关键字:

  • 1、__nonnull
    书写格式:
	@property (nonatomic, strong, nonnull) NSString *icon;
	@prepertu (nonatomic, strong)NSString *_Nonnull icon;
	@prepertu (nonatomic, strong)NSString *__nonnull icon;
  • 2、nullable 可以为空
	@property (nonatomic, strong, nonable) NSString *icon;
	@prepertu (nonatomic, strong)NSString *_Nonable icon;
	@prepertu (nonatomic, strong)NSString *__nonable icon;
  • 3、null_resettable get方法不能为空,set方法可以为空
  • 4、
    • id: 任意类型,编译时不会检查变量类型,泛指所有class
    • instancetype具有对象类型检测功能,只能作为函数返回值,不能用来定义定义变量。

6、property作用:
@property的本质就是ivar(实例变量)加存取方法(getter + setter)。如果没有手动实现getter与setter方法,那么编译器就会自动加上。

7、@synthesize和@dynamic分别有什么作用?

  • @synthesize:就是如果你没有手动实现getter与setter方法,那么编译器就会自动为你加上这两个方法。
  • @dynamic的:告诉编译器,getter与setter方法由用户自己实现,不自动生成。当然对于readonly的属性只需要提供getter即可
  • 如果都没有写@synthesize和@dynamic,那么默认的就是@synthesize var = _var;

8、写一个单例模式:

+ (instancetype)sharedDataTool
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instace = [[self alloc] init];
    });
    return _instace;
 }

9:可变集合类 和 不可变集合类的 copy 和 mutablecopy有什么区别?如果是集合是内容复制的话,集合里面的元素也是内容复制么?

  • 浅拷贝就是拷贝指向原来对象的指针,使原对象的引用计数+1,可以理解为创建了一个指向原对象的新指针而已,并没有创建一个全新的对象。

  • 深拷贝就是拷贝出和原来仅仅是值一样,但是内存地址完全不一样的新的对象,创建后和原对象没有任何关系。

  • 非集合类对象

    • 可变对象的copy和mutableCopy方法都是深拷贝(区别完全深拷贝与单层深拷贝) 。
    • 不可变对象的copy方法是浅拷贝,mutableCopy方法是深拷贝。
    • copy方法返回的对象都是不可变对象。
  • 集合类对象

    • 容器类可变对象mutableCopy和copy都返回一个新的容器,但容器内的元素仍然是浅拷贝

10、如何令自己所写的对象具有拷贝功能?
若想令自己所写的对象具有拷贝功能,则需实现 NSCopying 协议。如果自定义的对象分为可变版本与不可变版本,那么就要同时实现 NSCopying与 NSMutableCopying协议。
具体步骤:
需声明该类遵从 NSCopying 协议
实现 NSCopying 协议。该协议只有一个方法:

- (id)copyWithZone:(NSZone *)zone;

注意:一提到让自己的类用 copy 修饰符,我们总是想覆写copy方法,其实真正需要实现的却是 “copyWithZone” 方法。
ex:

@interface Person : NSObject <NSCopying>
@property (nonatomic, strong) NSString *userId;
@end

@interface Student : Person <NSCopying> 
@property (nonatomic, strong) NSString *studentId;
@end

@implementation Person
- (id)copyWithZone:(NSZone *)zone
{
  Person *p = [[[self class] alloc] init]; // <== 注意这里
  p.userId = self.userId;
  return p;
}
@end

@implementation Student
- (id)copyWithZone:(NSZone *)zone
{
  Student *s = [super copyWithZone:zone];
  s.studentId = self.studentId;
  return s;
}
@end

注意:有子类的对象,父类必须用子类对象必须用 [[[self class] alloc] init];否认子类调用 [super copyWithZone:zone]; 返回父类对象,再赋值给子类时报错:

Unrecognized selector setStudentId sent to instance xxx ...

10、为啥IBOutlet修饰的UIView适用weak关键字?
当我们将控件拖到storyboard或者xib上时,就相当于是创建了一个对象,而这个对象是加到了试图控制器的view上,也就是存放到了subviews数组中。也就是说我们的控件对象是属于view 的,view 对其子控件的关系是强引用。
所以当我们使用Outlet属性的时候,这个Outlet属性是有view来进行强引用的。我们是在viewController中仅仅使用了它,没有必要拥有它,所以使用weak进行修饰。
PS:用strong也是可以的。

11、nonatomic和atomic的区别?atomic是绝对的线程安全么?为什么?如果不是,那应该如何实现?
atomic是属相原子性
对于atomic的属性,系统生成的 getter/setter 会保证 get、set 操作的完整性,不受其他线程影响。比如,线程 A 的 getter 方法运行到一半,线程 B 调用了 setter:那么线程 A 的 getter 还是能得到一个完好无损的对象。
而nonatomic就没有这个保证了。所以,nonatomic的速度要比atomic快。
不过atomic可并不能保证线程安全。如果线程 A 调了 getter,与此同时线程 B 、线程 C 都调了 setter——那最后线程 A get 到的值,3种都有可能:可能是 B、C set 之前原始的值,也可能是 B set 的值,也可能是 C set 的值。同时,最终这个属性的值,可能是 B set 的值,也有可能是 C set 的值
12、为什么说Objective-C是一门动态的语言?
静态、动态是相对的,这里动态语言指的是不需要在编译时确定所有的东西,在运行时还可以动态的添加变量、方法和类。
Objective-C 可以通过Runtime 这个运行时机制,在运行时动态的添加变量、方法、类等,所以说Objective-C 是一门动态的语言。

13、进程和线程的区别?同步异步的区别?并行和并发的区别?
1)进程是一个内存中运行的应用程序,比如在Windows系统中,一个运行的exe就是一个进程。线程是指进程中的一个执行流程。
2)同步是顺序执行,执行完一个再执行下一个。需要等待,协调运行。异步就是彼此独立,在等待某事件的过程中继续做自己的事,不需要等待这些事件完成后再工作。
3)并发性(Concurrence):指两个或两个以上的事件或活动在同一时间间隔内发生。并发的实质是一个物理CPU(也可以多个物理CPU) 在若干道程序之间多路复用,并发性是对有限物理资源强制行使多用户共享以提高效率。
并行性(parallelism)指两个或两个以上事件或活动在同一时刻发生。在多道程序环境下,并行性使多个程序同一时刻可在不同CPU上同时执行。通俗一点并行和并发 是前者相当于三个人同时吃一个馒头,后者相当于一个人同时吃三个馒头。
区别:(并发)一个处理器同时处理多个任务和(并行)多个处理器或者是多核的处理器同时处理多个不同的任务。
14、线程间通信?
ios中线程之间通信三种方式:NSThread、GCD、NSOperation

15、GCD的一些常用的函数?(group,barrier,信号量,线程同步)

  • 1).延迟执行任务函数:dispatch_after(…)。
  • 2).一次性执行dispatch_once(…)。
  • 3).栅栏函数dispatch_barrier_async/dispatch_barrier_sync。
  • 4).队列组的使用dispatch_group_t。
  • 5).GCD定时器 dispatch_source_t。

16、说一下AppDelegate的几个方法?从后台到前台调用了哪些方法?第一次启动调用了哪些方法?从前台到后台调用了哪些方法?

  • 1).当程序第一次运行并且将要显示窗口的时候执行,在该方法中我们完成的操作
(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
  • 2).程序进入后台的时候首先执行程序将要取消活跃该方法
(void)applicationWillResignActive:(UIApplication *)application
  • 3).该方法当应用程序进入后台的时候调用
(void)applicationDidEnterBackground:(UIApplication *)application
  • 4).当程序进入将要前台的时候调用
- (void)applicationWillEnterForeground:(UIApplication *)application
  • 5).应用程序已经变得活跃(应用程序的运行状态)
- (void)applicationDidBecomeActive:(UIApplication *)application
  • 6).当程序将要退出的时候调用,如果应用程序支持后台运行,该方法被applicationDidEnterBackground:替换
-(void)applicationWillTerminate:(UIApplication *)application

17、MVC和MVVM,MVP框架

  • 1)MVC:模型-视图-控制器(Model-View-Controller,MVC)简单而言Model持有数据,View显示与用户交互的界面,而View Controller调解Model和View之间的交互。
  • 2)MVVM:模型-视图-视图模型(Model-View-ViewModel)
    -----View:UI界面
    -----ViewModel:它是View的抽象,负责View与Model之间信息转换,将View的Command传送到Model;
    -----Model:数据访问层。
    mvvm中最需要注意的就是通过将View绑定到ViewModel,然后执行一些命令在向它请求个动作。而反过来,ViewModel跟Model通讯,告诉它更新来响应UI。
  • 3)MVP:
    ----Model:数据访问层
    ----View:UI显示界面
    ----Presenter:负责逻辑的处理即Model层与View之间通信。
    MVP 是从经典的模式MVC演变而来但是它们之间有着很重要区别:在MVP中View并不直接使用Model,它们之间的通信是通过Presenter (MVC中的Controller)来进行的,所有的交互都发生在Presenter内部,而在MVC中View会从直接Model中读取数据而不是通过 Controller。

18、NSString为什么要用copy关键字,如果用strong会有什么问题?

  • 1)因为父类指针可以指向子类对象,使用copy的目的是为了让本对象的属性不受外界影响,使用copy无论给我传入是一个可变对象还是不可对象,我本身持有的就是一个不可变的副本。
  • 2)使用是strong,那么这个属性就有可能指向一个可变对象,如果这个可变对象在外部被修改了,那么会影响该属性。
    -----------copy此特质所表达的所属关系与strong类似。然而设置方法并不保留新值,而是将其“拷贝” (copy)。 当属性类型为NSString时,经常用此特质来保护其封装性,因为传递给设置方法的新值有可能指向一个NSMutableString类的实例。这个类是NSString的子类,表示一种可修改其值的字符串,此时若是不拷贝字符串,那么设置完属性之后,字符串的值就可能会在对象不知情的情况下遭人更改。所以,这时就要拷贝一份“不可变” (immutable)的字符串,确保对象中的字符串值不会无意间变动。只要实现属性所用的对象是“可变的” (mutable),就应该在设置新属性值时拷贝一份。

19、NSCache优于NSDictionary的几点?
NSCache 是一个容器类,类似于NSDIctionary,通过key-value 形式存储和查询值,用于临时存储对象。
注意一点它和NSDictionary区别就是,NSCache 中的key不必实现copy,NSDictionary中的key必须实现copy。
NSCache中存储的对象也不必实现NSCoding协议,因为毕竟是临时存储,类似于内存缓存,程序退出后就被释放了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值