iOS面试题整理

作者: 浅陌 | 来源:发表于2016-03-19 10:57 被阅读201次

    最近在找工作,整理了几个比较基础的面试题,回答仅供回顾,不是太深入,也不一定正确,平时还是应该有目的性的深入理解。

    1.深拷贝与浅拷贝
    回答:
    深拷贝是新拷贝一块内存交给对象使用,copy声明的就是深拷贝。
    浅拷贝是创建一个新对象,两个对象指向同一个内存地址,ratain声明的就是浅拷贝。
    在oc中只有一种情况下是浅拷贝,就是不可变对象的copy,其它的都是深拷贝(包括不可变对象的mutableCopy、可变对象的copy和mutableCopy)。

    2.retain、strong、assign、weak、copy、nonatomic和atomic分别是做什么的
    回答:
    atomic是声明属性为原子属性,线程安全的,为防止属性在写的过程中被另一个线程读取,造成数据错误,一般用于读取文件,在手机端很少使用(桌面端会使用),应避免使用,因为它底层的实现是自旋锁(对应的为同步锁,也叫互斥锁,这是线程同步的知识)性能比较低,最好找其他的方式代替,比如通过改变代码逻辑的方式,属性默认是atomic。
    nonatomic是声明属性为非原子属性,是线程不安全的。
    assign是默认的值,用以声明基础数据类型(NSInteger、CGFloat)和C数据类型(int、float)。
    retain用于声明对象。
    copy只对实行了NSCopying协议的对象类型有效,也是用于声明对象。
    strong用来声明一个强引用的属性,对应retain和copy。
    weak声明一个弱引用的属性,可以自动nil化。
    unsafe_unretained也是声明一个弱引用属性,但不会自动nil化,也就是说,如果内存被释放掉,这个指针就是一个野指针。

    3.objective-c的内存管理原理
    oc为每块内存设定一个引用计数,当内存被赋值给a对象时,引用计数加1,当内存又被赋值给b对象时,引用计数再加1,这时候引用计数是2,当a不再使用这块内存时,引用计数减1,当b不再使用这块内存时,本来引用计数应该再减1,变成0,但是这时候系统为了减少系统开支,不会进行减1操作,而会直接将内存释放掉。

    4.UIView、UIWindow和CALayer的联系和区别
    回答:
    UIView负责渲染矩形区域的内容,为矩形区域增加动画和相应的触摸事件,布局和管理多个子视图。
    UIWindow是一个特殊的UIView,而一个程序中通常只有一个UIWindow,但可以手动创建多个。
    UIWindow主要起到三个作用:
    1.作为容器,包含程序所有要显示的视图;
    2.传递触摸消息到其它的UIView或者其它对象;
    3.与UIViewController协同工作,完成设备方向旋转的支持。
    CALayer是绘制内容的,不处理事件响应,与UIView是相互依赖的,依赖于UIView来显示绘制内容,UIView依赖于CALayer来提供内容。

    1. @implementation Son : Father
      • (id)init {
        if (self = [super init]) {
        NSLog(@"%@“, NSStringFromClass([self class]));
        NSLog(@"%@“, NSStringFromClass([super class]));
        NSLog(@"%@“, NSStringFromClass(self.superclass));
        }
        return self;
        }
        @end
        //打印结果就是
        Son
        Son
        Father
        为什么呢?
        回答:
        因为self和super的消息主体依然是self,也就是说self和super指向的是同一个对象,只是查找方法的位置有区别,一个从本类,一个从本类的超类。
        一般情况下class方法只在根类NSObject中定义,极少情况有子类重写class方法,所以[self calss]和[super class]都是在根类中找方法实现,如果重写可能会不太一样。

    6.#import、#include和@class的联系和区别
    回答:
    通常引用一个类有两种方法,一种是#import,另一种是@class,两者的区别在于#import会包含引用类的所有信息,包括被引用类的属性和方法,而@class只会告诉编译器声明了一个类,而类中有什么信息不需要知道。

    import被确定每个文件只会被引用一次,而#include会被多次引用,容易引起交叉编译。

    7.手写block与反写block
    回答:

    typedef void(^selectRowAtIndex)(NSInteger index);
    @property (nonatomic, copy) selectRowAtIndex handle;
    
    [UIView transitionWithView:self.view
                                 duration:0.2
                                  options:UIViewAnimationOptionTransitionFlipFromLeft
                             animations:^{ 
                                           [[blueViewController view] removeFromSuperview];
                                           [[self view] insertSubview:yellowViewController.view atIndex:0];
                                          }
                             completion:nil];
    typedef void(^animations)(void);
    typedef void(^completion)(BOOL finished);
    

    8.类别(category)和继承的区别
    回答:
    类别是对一个功能完备类的补充,比如一个Animal类,具有run和eat方法,想给类增加一个bark方法,可以使用类别。
    而多个类具有相同的实例变量和方法时,考虑用继承,即子类可以继承父类相同的特性,比如Animal类具有年龄和体重两个属性,Dog也具有年龄和体重两个属性,Dog就可以继承Animal的两个属性,即为继承。
    共同点是都给类进行了扩展。
    区别是:
    1.类别是对方法的扩展,不能添加成员变量,继承可以在父类的成员变量基础上添加新的成员变量。
    2.类别只能添加新方法,而不能修改和删除原来的方法,继承可以增加、修改和删除方法。
    3.类别不提倡对原有方法进行重载,继承可以使用super对原来的方法进行重载。
    4.类别可以被继承,如果一个父类中定义了一个类别,那么子类中也会继承此类别。

    9.__block与__weak的区别
    回答:
    __block对象在block中是可以被修改和重新赋值的。
    __block可以修饰对象和基本数据类型,而__weak只能修饰对象。
    __weak对象不可以在block中被重新赋值。

    10.多线程
    回答:
    多线程的实现方式包括:
    Pthreads 跨平台,使用难度大,很少使用。
    NSThread 更加面向对象,可直接操作线程对象。生命周期需要自己手动管理,最常用的可能是暂停功能- (void)sleepForTimeInterval:(NSTimeInterval)time;
    GCD 基于C语言,取代NSThread,充分利用设备多核,常用,会自动管理线程的生命周期。
    GCD是基于任务和队列来进行的,队列遵循FIFO(先进先出)原则,队列氛围并行队列和串行队列。
    NSOperation & NSOperationQueue 对GCD的封装,比GCD更加面向对象,比GCD性能稍微差一点,常用。
    NSOperation与NSOperationQueue分别对应GCD中的任务和队列的概念。

    11.isKindOfClass和isMemberOfClass的区别
    回答:
    isKindOfClass可以确定一个对象是否是一个类的实例,或者该类祖先类的实例,而isMemberOfClass只能用来判断前者,不能用来判断后者。

    12.UCP和TCP的区别
    回答:
    TCP(传输控制协议),提供的是面向连接、可靠的字节流服务。当客户和服务器彼此交换数据前,必须先在双方之间建立一个TCP连接,之后才能传输数据。TCP提供超时重发,丢弃重复数据,流量控制等功能,保证能从一端传到另一端。
    UDP(用户数据协议),是一个简单的面向数据的运输层协议。UDP不提供可靠性,它只是把应用程序传给IP层的数据报发送出去,但是并不能保证它们能到达目的地。因为UDP在传输数据使不用在客户和服务器之间建立一个连接,且没有超时重发机制,所以传输速度很快。

    13.delegate、block和NSNotification的区别
    回答:
    NSNotification发出消息后,可以有多个消息接受者,delegate效率比较高,delegate发出消息后只能由某个特定的对象获得消息。
    block可以代替delegate的功能,而且实现起来比较简洁,delegate需要对每个事件进行判断识别来源,而block可以在创建事件时区分开来。

    14.KVO和KVC的区别
    回答:
    KVC即是指 NSKeyValueCoding,一个非正式的Protocol,提供一种机制来间接访问对象的属性。而不是通过调用Setter、Getter方法访问。KVO 就是基于 KVC 实现的关键技术之一。
    - (id)valueForKey:(NSString *)key;
    - (void)setValue:(id)value forKey:(NSString *)key;
    KVO的是KeyValue Observe的缩写,中文是键值观察。这是一个典型的观察者模式,观察者在键值改变时会得到通知。

    addObserver:forKeyPath:options:context:;
    observeValueForKeyPath:ofObject:change:context:
    

    KVO需要注意在对象销毁时,要移除观察者,不然会崩溃。

    removeObserver:forKeyPath:context:
    

    KVO是同步执行,不能执行耗时方法,KVO可能发生资源抢夺

    15.GCD
    回答:

    dispatch_get_global_queue 后台执行
    dispatch_get_main_queue 主线程执行
    dispatch_once_t 一次性执行
    dispatch_time_t 延迟执行
    dispatch_group_async 并行执行
    dispatch_group_notify 并行执行后汇总
    

    还有自定义队列

    相关文章

      网友评论

        本文标题:iOS面试题整理

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