欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

iOS面试题整理带答案

程序员文章站 2022-05-25 17:17:27
1、简述oc中内存管理机制。与retain配对使用的方法是dealloc还是release,为什么?需要与alloc配对使用的方法是dealloc还是release,为什么?readwrite,re...
1、简述oc中内存管理机制。与retain配对使用的方法是dealloc还是release,为什么?需要与alloc配对使用的方法是dealloc还是release,为什么?readwrite,readonly,assign,retain,copy,nonatomic 、atomic、strong、weak属性的作用?

管理机制:使用了一种叫做引用计数的机制来管理内存中的对象。

oc中每个对象都对应着他们自己的引用计数,引用计数可以理解为一个整数计数器,当使用alloc方法创建对象的时候,持有计数会自动设置为1。当你向一个对象发送retain消息 时,持有计数数值会增加1。相反,当你像一个对象发送release消息时,持有计数数值会减小1。当对象的持有计数变为0的时候,对象会释放自己所占用的内存。

retain(引用计数加1)->release(引用计数减1)

alloc(申请内存空间)->dealloc(释放内存空间)

readwrite: 表示既有getter,也有setter (默认)

readonly: 表示只有getter,没有setter

nonatomic:不考虑线程安全

atomic:线程操作安全(默认)

线程安全情况下的setter和getter:

-(nsstring*)value

{

@synchronized(self){

return[[_valueretain]autorelease];

}

}

-(void)setvalue:(nsstring*)avalue

{

@synchronized(self){

[avalueretain];

[_valuerelease];

_value=avalue;

}

}

retain: release旧的对象,将旧对象的值赋予输入对象,再提高输入对象的索引计数为1

assign: 简单赋值,不更改索引计数(默认)

copy: 其实是建立了一个相同的对象,地址不同(retain:指针拷贝 copy:内容拷贝)

strong:(arc下的)和(mrc)retain一样(默认)

weak:(arc下的)和(mrc)assign一样, weak当指向的内存释放掉后自动nil化,防止野指针

unsafe_unretained 声明一个弱应用,但是不会自动nil化,也就是说,如果所指向的内存区域被释放了,这个指针就是一个野指针了。?autoreleasing 用来修饰一个函数的参数,这个参数会在函数返回的时候被自动释放。

2、类变量的@protected ,@private,@public,@package,声明各有什么含义?

@private:作用范围只能在自身类

@protected:作用范围在自身类和继承自己的子类(默认)

@public:作用范围最大,可以在任何地方被访问。

@package:这个类型最常用于框架类的实例变量,同一包内能用,跨包就不能访问

3、线程是什么?进程是什么?二者有什么区别和联系?

一个程序至少有一个进程,一个进程至少有一个线程:

进程:一个程序的一次运行,在执行过程中拥有独立的内存单元,而多个线程共享一块内存

线程:线程是指进程内的一个执行单元。

联系:线程是进程的基本组成单位

区别:(1)调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位?(2)并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可并发执行?(3)拥有资源:进程是拥有资源的一个独立单位,线程不拥有资源,但可以访问隶属于进程的资源.?(4)系统开销:在创建或撤消进程时,由于系统都要为之分配和回收资源,导致系统的开销明显大于创建或撤消线程时的开销。

举例说明:操作系统有多个软件在运行(qq、office、音乐等),这些都是一个个进程,而每个进程里又有好多线程(比如qq,你可以同时聊天,发送文件等)

4、谈谈你对多线程开发的理解?ios中有几种实现多线程的方法?

好处:

(1)使用线程可以把占据时间长的程序中的任务放到后台去处理

(2)用户界面可以更加吸引人,这样比如用户点击了一个按钮去触发某些事件的处理,可以弹出一个进度条来显示处理的进度

(3)程序的运行速度可能加快

(4)在一些等待的任务实现上如用户输入、文件读写和网络收发数据等,线程就比较有用了。

缺点:

(1)如果有大量的线程,会影响性能,因为操作系统需要在它们之间切换。

(2)更多的线程需要更多的内存空间。

(3)线程的中止需要考虑其对程序运行的影响。

(4)通常块模型数据是在多个线程间共享的,需要防止线程死锁情况的发生。

实现多线程的方法:

nsobject类方法

nsthread

nsoperation

gcd

5、线程同步和异步的区别?ios中如何实现多线程的同步?

异步:举个简单的例子 就是游戏,游戏会有图像和背景音乐

同步:是指一个线程要等待上一个线程执行完之后才开始执行当前的线程,上厕所

nsoperationqueue:maxcurrentcount

nsconditionlock

gcd->https://blog.csdn.net/onlyou930/article/details/8225906

6、假设有一个字符串aabcad,请写一段程序,去掉字符串中不相邻的重复字符串,即上述字符串处理之后的输出结果为:aabcd

nsmutablestring*str=[[nsmutablestringalloc]initwithformat;@“aabcad”];

for(inti=0,i {

unsignedchara=[strcharacteratindex:i];

for(intj=i+1,j {

unsignedcharb=[strcharacteratindex:j];

if(a==b)

{

if(j==i+1)

{

}

else

{

[strdeletecharactersinrange:nsmakerange(j,1)];

}

}

}

}

nslog(@“%@”,str);

7、获取一台设备唯一标识的方法有哪些?

(1)udid

udid的全称是unique device identifier,顾名思义,它就是苹果ios设备的唯一识别码,它由40个字符的字母和数字组成。

(2)uuid

uuid是universally unique identifier的缩写,中文意思是通用唯一识别码.

(3)mac address

(4)open udid

(5)广告标识符

(6)vindor标示符

vendor是cfbundleidentifier(反转dns格式)的前两部分。来自同一个运营商的应用运行在同一个设备上,此属性的值是相同的;不同的运营商应用运行在同一个设备上值不同。

经测试,只要设备上有一个tencent的app,重新安装后的identifierforvendor值不变,如果tencent的app全部删除,重新安装后的identifierforvendor值改变。

*ios7以后使用keychain

8、ios类是否可以多继承?如果没有,那可以用其他方法实现吗?简述实现过程。

不可以多继承,用protocol实现

9、堆和栈的区别?

堆需要用户手动释放内存,而栈则是编译器自动释放内存

问题扩展:要知道oc中nsstring的内存存储方式

10、ios本地数据存储都有哪几种方式?

nskeyedarchiver

nsuserdefaults

write写入方式(plist文件、txt文件等)

sqlite3

coredata

(问题扩展:什么情况下使用什么样的数据存储)

(1)nskeyedarchiver:采用归档的形式来保存数据,数据对象需要遵守nscoding协议,对象对应的类必须提供encodewithcoder:和initwithcoder:方法。缺点:只能一次性归档保存以及一次性解压。所以只能针对小量数据,对数据操作比较笨拙,如果想改动数据的某一小部分,需要解压或归档整个数据。

(2)nsuserdefaults:用来保存应用程序设置和属性、用户保存的数据。用户再次打开程序或开机后这些数据仍然存在。nsuserdefaults可以存储的数据类型包括:nsdata、nsstring、nsnumber、nsdate、nsarray、nsdictionary。缺点:如果要存储其他类型,需要转换为前面的类型,才能用nsuserdefaults存储。

(3)write写入方式:永久保存在磁盘中。第一步:获得文件即将保存的路径:第二步:生成在该路径下的文件:第三步:往文件中写入数据:最后:从文件中读出数据:

(4)sqlite:采用sqlite来存储数据。sqlite作为一中小型数据库,应用ios中,跟前三种保存方式相比,相对比较复杂一些。

(5)coredata:系统自带的数据库存储。

11、写出方法获取ios内存使用情况。

(问题扩展:如何利用xcode观察内存使用情况)

//获取当前设备可用内存及所占内存的头文件

#import

#import

//获取当前设备可用内存(单位:mb)

-(double)availablememory

{

vm_statistics_data_tvmstats;

mach_msg_type_number_tinfocount=host_vm_info_count;

kern_return_tkernreturn=host_statistics(mach_host_self(),

host_vm_info,

(host_info_t)&vmstats,

&infocount);

if(kernreturn!=kern_success)

{

returnnsnotfound;

}

return((vm_page_size*vmstats.free_count)/1024.0)/1024.0;

}

//获取当前任务所占用的内存(单位:mb)

-(double)usedmemory

{

task_basic_info_data_ttaskinfo;

mach_msg_type_number_tinfocount=task_basic_info_count;

kern_return_tkernreturn=task_info(mach_task_self(),

task_basic_info,

(task_info_t)&taskinfo,

&infocount);

if(kernreturn!=kern_success)

{

returnnsnotfound;

}

return(taskinfo.resident_size/1024.0/1024.0);

}

12、深拷贝和浅拷贝的理解?

对实例进行深拷贝时当前类需要实现nscopying协议。

浅拷贝是复制出来一个跟原对象相同地址的对象

深拷贝时复制一个跟源对象不同地址的对象 改变源对象对新对象没有影响

13.怎样实现一个singleton的类。

问题扩展:单例的好处是什么?——节省内存

+(accountmanager*)sharedmanager

{

staticaccountmanager*staticinstance=nil;

staticdispatch_once_tpredicate;

dispatch_once(&predicate,^{

staticinstance=[[selfalloc]init];

});

returnstaticinstance;

}

14、什么是安全释放?

置nil 再释放

15、runloop是什么?

run loops 是线程相关的的基础框架的一部分。

一个 run loop 就是一个事件处理 的循环,用来不停的调度工作以及处理输入事件。

使用 run loop的目的是让你的线程在有工作的时候忙于工作,而没工作的时候处于休眠状态。

runloop还可以在loop在循环中的同时响应其他输入源,比如界面控件的按钮,手势等。

16、什么是序列化和反序列化,可以用来做什么?如何在oc中实现复杂对象的存储?

序列化是把对象转化成字节序列的过程 反序列化是把字节序列恢复成对象

将对象写到文件或者数据库里,并且能读取出来

遵循nscoding协议 实现复杂对象的存储 实现该协议后可以对其进行打包或解包,转化成nsdata

17、写一个标准宏min,这个宏输入两个参数并返回较小的一个?

#define min(x,y) ((x)>(y)?(y):(x))

扩展:在定义宏的时候需要注意哪些问题?

宏全部大写 写在#import 下 @interface上 结尾无分号

18、iphone os有没有垃圾回收机制?简单阐述一下oc内存管理。

iphone os没有垃圾回收机制 oc的内存管理是谁创建谁释放 程序中遇到retain 该对象引用计数+1 遇release该对象引用计数-1 retaincount为0时 内存释放

19、简述应用程序按home键进入后台时的生命周期,以及从后台回到前台时的生命周期?

//进入后台时

-(void)applicationwillresignactive:(uiapplication*)application;

-(void)applicationdidenterbackground:(uiapplication*)application;

//进入前台时

-(void)applicationdidenterforeground:(uiapplication*)application;

-(void)applicationwillresignactive:(uiapplication*)application;

//各个程序运行状态时代理的回调:

//当进程启动但还没进入状态保存

-(bool)application:(uiapplication*)applicationwillfinishlaunchingwithoptions:(nsdictionary*)launchoptions

当进程启动基本完成程序准备开始运行

-(bool)application:(uiapplication*)applicationdidfinishlaunchingwithoptions:(nsdictionary*)launchoptions

//当应用程序将要入非活动状态执行,在此期间,应用程序不接收消息或事件,比如来电话了

-(void)applicationwillresignactive:(uiapplication*)application

当应用程序入活动状态执行,这个刚好跟上面那个方法相反

-(void)applicationdidbecomeactive:(uiapplication*)application

//当程序被推送到后台的时候调用。所以要设置后台继续运行,则在这个函数里面设置即可

-(void)applicationdidenterbackground:(uiapplication*)application

//当程序从后台将要重新回到前台时候调用,这个刚好跟上面的那个方法相反

-(void)applicationwillenterforeground:(uiapplication*)application

//当程序将要退出是被调用,通常是用来保存数据和一些退出前的清理工作。这个需要要设置uiapplicationexitsonsuspend的键值。

-(void)applicationwillterminate:(uiapplication*)application

//当程序载入后执行

-(void)applicationdidfinishlaunching:(uiapplication*)application

20、viewcontroller 的 alloc,loadview, viewdidload,viewwillappear,viewdidunload,dealloc、init分别是在什么时候调用的?在自定义viewcontroller的时候这几个函数里面应该做什么工作?

alloc//申请内存时调用

loadview//加载视图时调用

viewdidload//视图已经加载后调用

viewwillappear//视图将要出现时调用

viewdidunload//视图已经加载但没有加载出来调用

dealloc//销毁该视图时调用

init//视图初始化时调用

21、描述应用程序的启动顺序。

(1)程序入口main函数创建uiapplication实例和uiapplication代理实例。

(2)在uiapplication代理实例中重写启动方法,设置第一viewcontroller。

(3)在第一viewcontroller中添加控件,实现应用程序界面。

22、为什么很多内置类如uitableviewcontrol的delegate属性都是assign而不是retain?请举例说明。

防止循环引用

23、使用uitableview时候必须要实现的几种方法?

- (nsinteger)tableview:(uitableview*)tableviewnumberofrowsinsection:(nsinteger)section;?这个方法返回每个分段的行数,不同分段返回不同的行数可以用switch来做,如果是单个列表就直接返回单个你想要的函数即可。?-(uitableviewcell*)tableview:(uitableview*)tableviewcellforrowatindexpath:(nsindexpath)indexpath;?这个方法是返回我们调用的每一个单元格。通过我们索引的路径的section和row来确定

24、写一个便利构造器。

//id代表任意类型指针,这里代表student*,类方法

+(id)studentwithname:(nsstring*)newnameandage:(int)newage?

{?

student*stu=[[studentalloc]initname:newnameandage:newage];?

return[stuautorelease];

//自动释放?

}

25、uiimage初始化一张图片有几种方法?简述各自的优缺点。

3种

imagenamed:系统会先检查系统缓存中是否有该名字的image,如果有的话,则直接返回,如果没有,则先加载图像到缓存,然后再返回。

initwithcontentsoffile:系统不会检查系统缓存,而直接从文件系统中加载并返回。

imagewithcgimage:scale:orientation当scale=1