2021 iOS初级面试题及答案

1.为什么说Objective-C是一门动态的语言?

1.object-c类的类型和数据变量的类型都是在运行是确定的,而不是在编译时确定。例如:多态特性,我们可以使用父类对象来指向子类对象,并且可以用来调用子类的方法。运行时(runtime)特性,我们可以动态的添加方法,或者替换方法。

2.讲一下MVC和MVVM,MVP?

MVC:简单来说就是,逻辑、视图、数据进行分层,实现解耦。
MVVM:是Model-View-ViewMode模式的简称。由视图(View)、视图模型(ViewModel)、模型(Model)三部分组成.比MVC更加释放控制器臃肿,将一部分逻辑(耗时,公共方法,网络请求等)和数据的处理等操作从控制器里面搬运到ViewModel
MVVM的特点:

  1. 低耦合。View可以独立于Model变化和修改,一个ViewModel可以绑定到不同的View上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。
  1. 可重用性。可以把一些视图的逻辑放在ViewModel里面,让很多View重用这段视图逻辑。
  1. 独立开发。开发人员可以专注与业务逻辑和数据的开发(ViewModel)。设计人员可以专注于界面(View)的设计。
  1. 可测试性。可以针对ViewModel来对界面(View)进行测试

MVP:本小编没有接触,希望可以得到大家的帮助。可以在下面留言。

3.为什么代理要用weak?代理的delegate和dataSource有什么区别?block和代理的区别?

代理是使用weak来修饰的。1.使用weak是为了避免循环引用。2.当使用weak修饰的属性,当对象释放的时候,系统会对属性赋值nil,object-c有个特性就是对nil对象发送消息也就是调用方法,不会cash。
delegate:表示代理,代理可以让A对象通知B对象,我(A)发生的变化,前提B遵循了A的代理,并且实现了A的代理方法。
dataSource:表示数据源,如果A对象声明了数据源,当我们创建A对象的时候,我们就该实现数据源,来告诉A,他所需要的一些数据。例如:tableView数据源方法,需要告诉它,我要实现几组cell,每组cell多少行cell,实现的cell什么样式,什么内容
同样delegatedataSource,都是可以使用requireoptional来修饰的。

代理和Block的区别

相同点:代理和Block大多是我们都可以用来做倒序传值的。我们都得注意避免循环引用。
不同点:代理使用weak修饰,代理必须先声明方法。当我们调用代理的时候要判断是否已经实现。
block:使用的是copy来修饰,block保存的是一段代码,其实也就是一个函数。当我们调用block的时候要判断是否已经实现。

4.属性的实质是什么?包括哪几个部分?属性默认的关键字都有哪些?@dynamic关键字和@synthesize关键字是用来做什么的?

属性是描述类的特征,也就是具备什么特性。三个部分,带下划线的成员变量,get、setter方法。
默认关键字:readwrite,assign, atomic;
@dynamic :修饰的属性,其getter和setter方法编译器是不会自动帮你生成。必须自己是实现的。
@synthesize:修饰的属性,其getter和setter方法编译器是会自动帮你生成。不必自己实现,可以指定与属性相对应的成员变量。

5.属性的默认关键字是什么?

默认关键字:readwrite,assign, atomic;

6.NSString为什么要用copy关键字,如果用strong会有什么问题?(注意:这里没有说用strong就一定不行。使用copy和strong是看情况而定的

众所周知,我们知道,可变类型(NSMutableArray,NSMutableString等)是不可边类型(NSString,NSArray等)的子类,因为多态的原因,我们可以使用赋值指向子类对象,也就是我们可以使用不可边类型去接受可变类型。
1.当我们使用strong修饰A不可边类型的时候,并且使用B可变类型给A赋值,再去修改可变类型B值的时候,A所指向的值也会发生改变。引文strong只是让创建的对象引用计数器+1,并返回当前对象的内容地址,当我们修改B指向的内容的时候,A指向的内容也同样发生了改变,因为他们指向的内存地址是相同的,是一份内容。
2.当我们使用copy修饰A不可边类型的时候,并且使用B可变类型给A赋值,再去修改可变类型B值的时候,A所指向的值不会发生改变。因为当时用copy的修饰的时候,会拷贝一份内容出来,并且返回指针给A,当我们修改B指向的内容的时候,A指向的内容是没有发生改变的。因为A指向的内存地址和B指向的内存地址是不相同的,是两份内容
3.copy修饰不可边类型(NSString,NSArray等)的时候,且使用不可边类型进行赋值,表示浅拷贝,只拷贝一份指针,和strong修饰一样,当修饰的是可变类型(NSMutableArray,NSMutableString等)的时候,表示深拷贝,直接拷贝新一份内容,到内存中。表示两份内容。

7.如何令自己所写的对象具有拷贝功能?

必须遵循nscopying协议,如果想实现可变和不可边拷贝时,必须同时遵循nscopingnsmutablecoping协议。并且实现

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

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

可变使用copy表示深拷贝,不可变集合类使用copy的时候是浅拷贝。
可变集合类使用mutablecopy表示深拷贝,不可变集合类使用copy的时候是浅拷贝。
关于容器实现copy 或 metableCopy ,容器内元素默认都是 指针拷贝,不是内容复制。

9.为什么IBOutlet修饰的UIView也适用weak关键字?

在xib或者Sb拖控件时,其实控件就加载到了父控件的subviews数组里面,进行了强引用,即使使用了weak,也不造成对象的释放。

10.nonatomic和atomic的区别?atomic是绝对的线程安全么?为什么?如果不是,那应该如何实现?

nonatomic:表示非原子,不安全,但是效率高。
atomic:表示原子行,安全,但是效率定。
atomic:不能绝对保证线程的安全,当多线程同时访问的时候,会造成线程不安全。可以使用线程锁来保证线程的安全。

11.UICollectionView自定义layout如何实现?

实现一个自定义layout的常规做法是继承UICollectionViewLayout类,然后重载下列方法:

-(CGSize)collectionViewContentSize
返回collectionView的内容的尺寸
-(NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
返回rect中的所有的元素的布局属性
返回的是包含UICollectionViewLayoutAttributes的NSArray
UICollectionViewLayoutAttributes可以是cell,追加视图或装饰视    图的信息,通过不同的UICollectionViewLayoutAttributes初始化方法可以得到不同类型的UICollectionViewLayoutAttributes:
   layoutAttributesForCellWithIndexPath:
   layoutAttributesForSupplementaryViewOfKind:withIndexPath:
layoutAttributesForDecorationViewOfKind:withIndexPath:
  -(UICollectionViewLayoutAttributes )layoutAttributesForItemAtIndexPath:(NSIndexPath )indexPath
返回对应于indexPath的位置的cell的布局属性
-(UICollectionViewLayoutAttributes )layoutAttributesForSupplementaryViewOfKind:(NSString )kind atIndexPath:(NSIndexPath *)indexPath
返回对应于indexPath的位置的追加视图的布局属性,如果没有追加视图可不重载
-(UICollectionViewLayoutAttributes * )layoutAttributesForDecorationViewOfKind:(NSString)decorationViewKind atIndexPath:(NSIndexPath )indexPath
返回对应于indexPath的位置的装饰视图的布局属性,如果没有装饰视图可不重载
-(BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
当边界发生改变时,是否应该刷新布局。如果YES则在边界变化(一般是scroll到其他地方)时,将重新计算需要的布局信息。

12.用StoryBoard开发界面有什么弊端?如何避免?

使用简单逻辑页面的跳转是可以使用sb的,开发比较块。
但是SB对于逻辑项目比较复杂的时候,开发起来比较慢。不适合多人合作开发;也不利于版本的梗系和后期的维护。使用sb在项目变异编译的时候,也都会直接加载到内存中,造成内存的浪费。
可以使用xib来代替,编辑复杂逻辑界面时候可以使用纯码编写。

13.进程和线程的区别?同步异步的区别?并行和并发的区别?

进程:是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.
线程:是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.
同步:阻塞当前线程操作,不能开辟线程。
异步:不阻碍线程继续操作,可以开辟线程来执行任务。
并发:当有多个线程在操作时,如果系统只有一个CPU,则它根本不可能真正同时进行一个以上的线程,它只能把CPU运行时间划分成若干个时间段,再将时间 段分配给各个线程执行,在一个时间段的线程代码运行时,其它线程处于挂起状。.这种方式我们称之为并发(Concurrent)。
并行:当系统有一个以上CPU时,则线程的操作有可能非并发。当一个CPU执行一个线程时,另一个CPU可以执行另一个线程,两个线程互不抢占CPU资源,可以同时进行,这种方式我们称之为并行(Parallel)。
区别:并发和并行是即相似又有区别的两个概念,并行是指两个或者多个事件在同一时刻发生;而并发是指两个或多个事件在同一时间间隔内发生。在多道程序环境下,并发性是指在一段时间内宏观上有多个程序在同时运行,但在单处理机系统中,每一时刻却仅能有一道程序执行,故微观上这些程序只能是分时地交替执行。倘若在计算机系统中有多个处理机,则这些可以并发执行的程序便可被分配到多个处理机上,实现并行执行,即利用每个处理机来处理一个可并发执行的程序,这样,多个程序便可以同时执行。

14.线程间通信?

当使用dispath-async函数开辟线程执行任务的完成时,我们需要使用dispatch_async(dispatch_get_main_queue(), ^{ });函数会到主线程内刷新UI。并完成通信

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

我们使用队列组来开辟线程时,队列组中的队列任务是并发,当所有的队列组中的所有任务完成时候,才可以调用队列组完成任务。

/**创建自己的队列*/
dispatch_queue_t dispatchQueue = dispatch_queue_create("ted.queue.next", DISPATCH_QUEUE_CONCURRENT);
/**创建一个队列组*/
dispatch_group_t dispatchGroup = dispatch_group_create();
/**将队列任务添加到队列组中*/
dispatch_group_async(dispatchGroup, dispatchQueue, ^(){
    NSLog(@"dispatch-1");
});
   /**将队列任务添加到队列组中*/
dispatch_group_async(dispatchGroup, dispatchQueue, ^(){
    NSLog(@"dspatch-2");
});
  /**队列组完成调用函数*/
dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), ^(){
    NSLog(@"end");
})

barrier:表示栅栏,当在并发队列里面使用栅栏时候,栅栏之前的并发任务开始并发执行,执行完毕后,执行栅栏内的任务,等栅栏任务执行完毕后,再并发执行栅栏后的任务。

dispatch_queue_t concurrentQueue = dispatch_queue_create("my.concurrent.queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(concurrentQueue, ^(){
    NSLog(@"dispatch-1");
});
dispatch_async(concurrentQueue, ^(){
    NSLog(@"dispatch-2");
});
dispatch_barrier_async(concurrentQueue, ^(){
    NSLog(@"dispatch-barrier"); 
});
dispatch_async(concurrentQueue, ^(){
    NSLog(@"dispatch-3");
});
dispatch_async(concurrentQueue, ^(){
    NSLog(@"dispatch-4");
});

信号量:Semaphore是通过‘计数’的方式来标识线程是否是等待或继续执行的。信号量

dispatch_semaphore_create(int) // 创建一个信号,并初始化信号的计数大小
/* 等待信号,并且判断信号量,如果信号量计数大于等于你创建时候的信号量的计数,就可以通过,继续执行,并且将你传入的信号计数减1,
 * 如果传入的信号计数小于你创建的计数,就表示等待,等待信号计数的变化
 *  如果等待的时间超过你传入的时间,也会继续下面操作
 *   第一个参数:semaphore 表示信号量
 *   第二个参数:表示等待的时间
 *    返回int 如果传入的信号计数大于等于你创建信号的计数时候,返回0\.  反之,返回的不等于0
 */
 int result = dispatch_semaphore_wait(dispatch_semaphore_t  semaphore,time outTime);// 表示等待,也是阻碍线程
// 表示将信号技术+1
dispatch_semaphore_signl(dispatch_semaphore_t semaphore);

实现线程的同步的方法:串行队列,分组,信号量。也是可以使用并发队列。

   //加入队列
dispatch_async(concurrentQueue, ^{
    //1.先去网上下载图片
    dispatch_sync(concurrentQueue, ^{

    });
    //2.在主线程展示到界面里
    dispatch_sync(dispatch_get_main_queue(), ^{

    });
});

16.如何使用队列来避免资源抢夺?

当我们使用多线程来访问同一个数据的时候,就有可能造成数据的不准确性。这个时候我么可以使用线程锁的来来绑定。也是可以使用串行队列来完成。如:fmdb就是使用FMDatabaseQueue,来解决多线程抢夺资源。

17.数据持久化的几个方案(fmdb用没用过)

持久化方案:
plist,存储字典,数组比较好用
preference:偏好设置,实质也是plist
NSKeyedArchiver:归档,可以存储对象
sqlite:数据库,经常使用第三方来操作,也就是fmdb
coreData:也是数据库储存,苹果官方的

18.说一下appdelegate的几个方法?从后台到前台调用了哪些方法?第一次启动调用了哪些方法?从前台到后台调用了哪些方法?

1773988-ab883455881116d0.gif

19.NSCache优于NSDictionary的几点?

1.nscache 是可以自动释放内存的。
2.nscache是线程安全的,我们可以在不同的线程中添加,删除和查询缓存中的对象。
3.一个缓存对象不会拷贝key对象。

20.知不知道Designated Initializer?使用它的时候有什么需要注意的问题?

个人理解:初始化函数,如果你想自定义初始化函数时,也是必须要初始化父类,以来保证可以继承父类的一些方法或者属性。
Designated Initializer

21.实现description方法能取到什么效果?

description是nsobject的一个实例的方法,返回的是一个nsstring。当我们使用nslog打印的时候,打印出来的一般都是对象的内存地址,如果我们实现description方法时,我们就可以使用nslog打印对象的时候,我们可以把它里面的属性值和内存地址一起打印出来.打印什么,就是看你写什么了。

-(NSString *)description{  
      NSString * string = [NSString stringWithFormat:@"<Person:内存地址:%p name = %@ age = %ld>",self,self.name,self.age];  
      return string;      
}  

22.objc使用什么机制管理对象内存?

使用内存管理计数器,来管理内存的。当内存管理计数器为0的时候,对象就会被释放。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,569评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,499评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,271评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,087评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,474评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,670评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,911评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,636评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,397评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,607评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,093评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,418评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,074评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,092评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,865评论 0 196
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,726评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,627评论 2 270

推荐阅读更多精彩内容