美文网首页我爱编程
自己整理面试(1)

自己整理面试(1)

作者: 奔跑的蜗牛最开心 | 来源:发表于2018-04-10 16:39 被阅读23次

    《IOS高级软件开发工程师80题》

    *设计模式 一个功能 怎么设计

    *响应链

    *冒泡排序 二叉树

    *内存池

    基础 (1-40)  

    (1)assign,copy,retain;

    assign:

                简单赋值,不改变引用计数,一般用于非oc对象,如int等普通类型;

    copy:

              a:先release旧值,再copy新值,应用计数+1,内容拷贝,一般用于NSString等不可变的对象;

              b:本质为复制该内存所存储的内容,重新创建一个对象赋给其相同的内容,即创建一个新对象,内容不变;

              c:指针指向不同的内存区域;

    retain:

               a:先relase旧值,再retain新值,引用计数+1,指针拷贝, 一般用于OC中的对象;

               b:最终指向同一块内存区域;

    (2)strong与weak,unsafe_unretained:指针指向内存地址,内存地址存储内容

     strong:强引用 ,引用计数+1;

     weak:  弱引用,当指针指向的地址一旦被释放,这些指针将被赋值为nil ,防止引起野指针;

     说明:a:strong与weak是arc引入的,类似于非arc下的retain与assign

                b:放风筝:strong相当于风筝线,weak相当于风筝的影子

     unsafe _unretained: 声明一个弱应用,但是不会自动nil化,也就是说,如果所指向的内存区域被释放了,这个指针就是一个野   指针了。

    (3)类变量@private,@protected,@public,@package,声明各有什么含义?

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

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

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

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

    (4).虚位以待? 

    (5)IOS本地数据存储有哪几种方式?

    NSKeyedArchiver:归档形式保存数据,遵守NSCoding协议

    NSUserDefaults:应用程序设置和属性,用户保存的数据

    Write写入:永久保存到磁盘中

    Sqlite (FMDB):FMDB中小型数据库

    coredata

    (6)深拷贝与浅拷贝的理解

    浅拷贝:复制出来一个跟原对象相同地址的对象/只复制指向对象的指针,而不复制引用对象本身

    深拷贝:复制一个跟源对象不同地址的对象,改变源对象对新对象没有影响/复制引用对象本身

    总结:

    浅复制好比你和你的影子,你完蛋,你的影子也完蛋

    深复制好比你和你的克隆人,你完蛋,你的克隆人还活着

    (13)举出5个你所熟悉的ios sdk库有哪些和第三方库有哪些?

    AFWorking/WebKit/SQLite/Core Data/Address Book

    (8)#import、#include和@class有什么区

        #import 系统文件,自定义文件引用  自动只导入一次 不会重复导入

         #include 和 #import 几乎一样 但是他需要注意不能重复引用

         @class  只是告诉系统有这个类,但是如果在实现类中用到这个类需要重新用  #import导入该类头文件

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

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

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

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

      (10)简述应用程序按Home键进入后台时的生命周期,以及从后台回到前台时的生命周期?

      将进入后台时

    -(void)applicationWillResignActive:(UIApplication *)application;

    -(void)applicationDidEnterBackground:(UIApplication *)application;

    进入前台时

    -(void)applicationDidEnterForeground:(UIApplication *)application;

    -(void)applicationWillResignActive:(UIApplication *)application;

     (11)viewcontroller的alloc loadView,viewDidLoad,viewWillAppear,viewWillDisAppear,viewDidAppear,viewDidDisAppear,viewDidUnload,dealloc,init分别是在什么时候调用的?

    alloc申请内存时调用

    loadView加载试图时调用

    viewDidLoad视图已经加载后调用

    ViewWillAppear视图将要渲染时调用

    ViewWillDisAppear视图渲染结束时调用

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

    dealloc销毁该视图时调用

    init视图初始化时调用

    (12) UIImage初始化一张图片有几种方法?简述各自的优缺点。

    imgeNamed:系统会先检查系统缓存中是否有改名字的imge,如果有的话,则直接返回,如果没有,则先加载图片到缓存,然后再返回;

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

    (13)怎么样实现一个单利类:避免重复创建,节省内存空间

    答:在objective-c中要实现一个单例类,至少需要做以下四个步骤:

    1).为单例对象实现一个静态实例,并初始化,然后设置成nil,

    2).实现一个实例构造方法检查上面声明的静态实例是否为nil,如果是则新建并返回一个本类的实例,

    3).重写allocWithZone方法,用来保证其他人直接使用alloc和init试图获得一个新实力的时候不产生一个新实例,

    4).适当实现allocWitheZone,copyWithZone,release和autorelease。

    //代码实现

    static Model * model;

    +(id)singleton{

    if(!model){

     @synchronized(self){

    model = [[Model alloc]init];

    }}

    return model;

    }

    (14)分别描述类别(categories)和延展(extensions)是什么?以及两者的区别?继承和类别在实现中有何区别?为什么Category只能为对象添加方法,却不能添加成员变量?

    类别:不改变原来代码的情况下往里面添加新的方法,只能添加,不能删除修改。

               1.将类的实现分散到多个不同文件或多个不同框架中

               2.创建私有方法的前向引用

               3.向对象添加非证实协议

    延展:是给类添加私有方法 只为自己类所见 所使用 

               1.extensions可以认为是一个私有的category

               2.后者可以添加属性,且添加的方法是必须要实现的 

    继承:可以扩展实例变量 而类别不能/继承可以增加,修改或者删除方法,并且可以增加属性。

    备注:在上线的项目更新中 用类别比继承更能维护项目的稳定性

    (15)什么事懒汉模式(lazy loading)?

    备懒汉模式,只在用到的时候才去初始化。也可以理解成延迟加载。

    一个延时加载,避免内存过高

    一个异步加载,避免线程堵塞

    (16)简述KVC、KVO、NotificationCenter、Delegate?并说明它们之间的区别?

    KVC(键值编码):通过字符串的名字(key)来间接访问对象属性的机制,而不是通过setter和getter。

    KVO(键值观察):提供了观察某一属性变化的方法(这是一个对象与另外一个对象保持同步的一种方法),即一个对象发生变化时,观察者立马做出反应,极大的简化了代码。

    NotificationCenter(消息中心):

    消息的发送者告知接收者事件已经发生或者将要发生,接收者并不能反过来影响发送者的行为。

    通常发送者和接收者的关系间接的多对多关系,类似于广播的形式。

    任何对象可以发送通知到中心,同时任何对象可以监听中心的通知。

    Delegate(代理):代理的目的是改变或者传递控制链。让别人帮助自己做某事。

    说明:类A调用类B,当类B想回调类A的方法的时候,要用到delegate.多用于发送者希望接收到接受者的某个功能反馈值.

    (17).简述你对UIView、UIWindow和CALayer的理解

    UIView:属于UIkit.framework框架,负责渲染矩形区域的内容,为矩形区域添加动画,响应区域的触摸事

    件,布局和管理一个或多个子视图 

    UIWindow:属于UIKit.framework框架,是一种特殊的UIView,通常在一个程序中只会有一个UIWindow,但可以手动创建多个UIWindow,同时加到程序里面。UIWindow在程序中主要起到三个作用:

    1、作为容器,包含app所要显示的所有视图

    2、传递触摸消息到程序中view和其他对象

    3、与UIViewController协同工作,方便完成设备方向旋转的支持

    CAlayer:属于QuartzCore.framework,是用来绘制内容的,对内容进行动画处理依赖与UIView来进行显示,不能处 理用户事件。UIView和CALayer是相互依赖的,UIView依赖CALayer提供内容,CALayer依赖UIView一共容器显示 绘制内容。

    UIViewController:管理视图的基础,每个视图控制器都有一个自带的视图,并且负责这个视图相关的一切事务。方便管理视图中的子视图,负责model与view的通信;检测设备旋转以及内存警告

    (18)ViewController 的 didReceiveMemoryWarning 是在什么时候被调用的?

     当应用程序的内存使用接近系统的最大内存使用时,应用会向系统发送内存警告,程序收到内存警告时候ViewController会调用  didReceiveMemoryWarning这个方法

    (18)看下面的程序,第一个nslog会输出什么?找时str的retain count 是多少?第二个和第三个呢?为什么

    (19)block的使用?

    (1) Block的声明

    Block(闭包)是可以获取其他函数内部变量的匿名函数,其不但方便开发,并且可以大幅提高应用的执行效率。

    Blo以上声明了一个名字叫做WXYTestBlock的block, 参数为一个字符串类型的name和一个int类型的age,返回值为NSString.当然你也可以声明成这样

    无参数,无返回值。

    (2) Block的使用

    a:独立block

    b:内联block

    (3) Block使用外部变量

    一个有趣的现象:

    现在你定义了一个独立的block,并且这个block使用了外部的变量

    然后这个变量又被改变了,然后你调用了这个block

    注意书序:定义独立block并且使用外部变量---》外部变量改变---》调用block

    这是为什么呢?

    block中如果使用了外部变量,他会拷贝一份这个变量,并且这个变量是只读的。

    所以外部变量改变并不影响block内部拷贝的那一份变量。

    代码中的内联block是在变量改变后才使用这个变量的,所以并不影响。

    如果不想让block拷贝变量,想让内部使用的变量和外部使用的变量指向同一地址的话

    需要在变量前面加上__block关键字

    需要说明的是,加上__block关键字之后,外部变量不再是只读的,在block内部也可以改变它的值。

    (4)block循环引用的问题

     首先在self类中声明一个NSString的属性

    现在:你想要在block中使用self,或者使用self.myStr

    如果,self的类中包含block,block中又引用了self,这样就会造成循环引用

    解决方法如下

    将self转化成为一个用__weak修饰的weakSelf, 就可以避免循环引用

    (20).谈谈你对多线程开发的理解?ios中有几种实现多线程的方法?

    好处:

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

    2.程序的运行速度可能加快

    3.体验更加友好

    缺点:

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

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

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

    实现多线程的方法:

    NSOperation

    NSOperation是一个抽象类,它封装了线程的细节实现,我们可以通过子类化该对象,加上NSQueue来同面向对象的思维,管理多线程程序。具体可参看这里:一个基于NSOperation的多线程网络访问的项目。

    NSThread

    NSThread是一个控制线程执行的对象,它不如NSOperation抽象,通过它我们可以方便的得到一个线程,并控制它。但NSThread的线程之间的并发控制,是需要我们自己来控制的,可以通过NSCondition实现。

    NSThread: 主线程中执行:performSelector:OnMainThread

                        延时执行:performSelector:onThread:withObject:waitUntilDone:

    GCD :

     GCD(Grand Central Dispatch) ,对多线程,多核开发较完整的封装,在使用GCD的时候,系统会自动根据CPU使用情况进行调度线程。

     自己只是创建队列queue  所有的执行都放到队列中,队列的特点是FIFO(先提交的先执行)

     *队列: 串行  并行

     *线程: 同步  异步

     综合:

     GCD: 线程管理总结

     *同步执行

      (1) 并发队列:不会开线程

      (2)串行队列:不会开线程

     *异步执行

      (1)并发队列: 能开启n条线程

      (2)串行队列: 开启1条线程

    (19)响应链

    事件响应链:UIButton - UIView - UIViewController - UIWindow - UIApplication - AppDelegate

    响应者:iOS中,能够响应事件的对象都是UIResponder的子类对象。UIResponder提供了四个用户点击的回调方法,分别对应用户点击开始,移动,点击结束以及取消点击,其中只有在程序强制退出或者来电时,取消点击事件才会调用。

    (20) 代理为什么使用weak?

    如果使用strong,则会执行UIScrollView*scrollView=[[UIScrollview alloc] init]; scrollview.delegate=self;

    (self代表控制器)

    当控制器想要销毁时,控制器被强指针指着; (self被scrollview.delegate指着)

    scrolview添加到视图控制器view也被强指针指着,无法销毁,那么他的delegate不会销毁;

    delegate指向控制器,造成了循环引用。

    把delegate变成weak; 当控制器生命周期结束时,view随之销毁,delegate也就销毁了;

    (20):框架Foundation概述

    1.Cocoa是创建Mac OS X 和 IOS程序的原生面相对象API,为两者应用提供了编程环境。

    2.Cocoa是一个框架的集合,包含中国子框架,最重要的有Foundation和UIKit.前者是基础框架,和界面无关,包含大量常用的API;

       后者是基础的UI类库。

    3.所有的Mac OS X 和 IOS程序都是由大量对象构成,而这些对象的根对象都是NSObject,NSObject都在Foundation框架之中。

    (21)

    (40)小知识点

    1.id声明的对象有什么特性?

    答:id声明的对象具有运行时的特性,即可以指向任意类型的obj对象 

    2.如何对ios设备进行性能测试?

    答: Profile-> Instruments ->Time Profiler

    3.多态

    答:不同对象以自己的方式响应相同的消息的能力叫做多态

    4.方法和选择器有什么不同?

    答:selector是一个方法的名字,method是一个组合体,包含了名字和实现。

    5.在应用中可以创建多少autorelease对象,是否有限制?

    答:无

    6.什么时候需要程序中创建内存池?

    答:界面线程维护着自己的内存池,用户自己创建的数据线程,则需要创建该线程的内存池。

    7.什么是简便构造方法?

    答:简便构造方法一般由CocoaTouch框架提供 如:NSNumber的+numberWithBool:

    8.什么是coredata?

    答:coredata是苹果提供一套数据保存框架,其基于SQlite

    7.什么是谓词?

    答:谓词是通过NSPredicate给定逻辑条件作为约束条件,完成对数据的筛选。

    8.什么

    答:简

    9.什么

    答:简

    10.什么

    //=========================//==========高级问题设置===========//===========================

    冒泡算法  二叉树  数据库设计   生命周期  runtime

    (41)大量数据处理

    大量数据意味着需要我们关注内存占用和性能,写代码时需要记得一下规划:

    1.尽可能缓存需要的数据,不相关的数据保持faults状态

    2.fetch时尽可能精准,少引入不相关的数据

    3.构建多context时尽量将同类managed object集中,最大限度减少合并需求

    4.提升操作效率,对asynchronous fetch, batch update,batch delete等新特性尽可能利用

    (42)RunLoop

    一般来讲,一个线程一次只能执行一个任务,执行完成后线程就会退出。如果我们需要一个机制,让线程能随时处理事件但并不退出,通常的代码逻辑是这样的:

    1

    2

    3

    4

    5

    6

    7

    function loop() {

        initialize();

        do {

            var message = get_next_message();

            process_message(message);

        } while (message != quit);

    }

    这种模型通常被称作Event Loop。 Event Loop 在很多系统和框架里都有实现,比如 Node.js 的事件处理,比如 Windows 程序的消息循环,再比如 OSX/iOS 里的 RunLoop。实现这种模型的关键点在于:如何管理事件/消息,如何让线程在没有处理消息时休眠以避免资源占用、在有消息到来时立刻被唤醒。

    所以,RunLoop 实际上就是一个对象,这个对象管理了其需要处理的事件和消息,并提供了一个入口函数来执行上面 Event Loop 的逻辑。线程执行了这个函数后,就会一直处于这个函数内部 "接受消息->等待->处理" 的循环中,直到这个循环结束(比如传入 quit 的消息),函数返回。

    OSX/iOS 系统中,提供了两个这样的对象:NSRunLoop 和 CFRunLoopRef。

    CFRunLoopRef 是在 CoreFoundation 框架内的,它提供了纯 C 函数的 API,所有这些 API 都是线程安全的。

    NSRunLoop 是基于 CFRunLoopRef 的封装,提供了面向对象的 API,但是这些 API 不是线程安全的。

    CFRunLoopRef 的代码是开源的,你可以在这里http://opensource.apple.com/tarballs/CF/CF-855.17.tar.gz下载到整个 CoreFoundation 的源码。为了方便跟踪和查看,你可以新建一个 Xcode 工程,把这堆源码拖进去看。

    (43)RunTime

     1.runtime实现的机制是什么,怎么用,一般用来干嘛?

     答:runtime是一套比较底层的纯c语言API,属于1个C语言库,包含了很多底层的C语言API.

     2.runtime用来干什么呢?用在哪些地方呢?怎么用呢?

    答: 1.在程序运行过程中,动态创建一个类(比如kvo的底层实现)

            2. 在程序运行过程中,动态地为某个类添加属性/方法,修改属性/方法

            3. 遍历一个类的所有成员变量(属性)/所有方法

     (44) Socket: 熟悉TCP/IP协议族,定义了主机如何连入因特网及数据束河在他们之间传输

            应用层: HTTP  SNMP  FTP  NDS

            传输层: TCP UDP

            网络层: IP

         1.Socket描述了一个IP, 端口对。它简化了程序的操作,知道对方的IP以及PORT就可以给对方发送消息,再由服务器来处理发送的这些消息。所以,socket一定包含了通信的双发,即客户端(Client)与服务器(server).

          a: 服务端利用socket监听端口

          b: 客户端发起连接

          c: 服务端返回信息,建立连接,开始通信

          d: 客户端,服务端断开连接

         2.套接字(socket)是通信的基石,是支持TCP/IP协议的网络通信的基本单元;

            应用层通过传输层进行数据通信时,TCP会遇到同时为多个应用程序进程提供并发服务的进程。

            多个TCP连接或者多个应用程序进程可能需要通过同一个TCP协议端口传输数据,为了区分不同的应用程序进程或连接

            许多计算机系统为应用程序与TCP/IP协议交互提供了套接字(socket)接口,应用层和传输层通过socket接口,区分来自不同应用程序或者网络连接的通信,实现数据传输的并发服务;

        3. 建立socket连接至少需要一对套接字,其中一个运行于客户端(Clientsocket),另一个运行于服务器端(Serversocket);

            套接字之间的连接分为三个步骤:服务器监听  客户端请求  连接确认。

        4.创建Socket连接时,可以指定使用的传输层协议,Socket可以支持不同的传输层协议(TCP或UDP),当使用TCP协议进行连接时,该Socket连接就是一个TCP连接。

      (45) :写一个标准宏MIN,这个宏输入两个参数并返回较小的一个?

       #define MIN(X,Y)  ((X)>(Y)?(Y):(X))

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

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

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

    NSMutableString * str = [[NSMutableString alloc]initWithFormat;@“aabcad”];

    for (int i = 0 ,i < str.length - 1 ;i++){

        unsigned char a = [str characterAtIndex:i];

        for (int j = i + 1 ,j < str.length ,j++){

            unsigned char b = [str characterAtIndex:j];

            if (a == b ){

                if (j == i + 1){

                    }else{

                    [str deleteCharactersInRange:NSMakeRange(j, 1)];

                    }

                }

            }

        }

    NSLog(@“%@”,str);

    (47)谓词

    (48)自动化测试

    相关文章

      网友评论

        本文标题:自己整理面试(1)

        本文链接:https://www.haomeiwen.com/subject/ztenhftx.html