有关面试第一弹

来源:互联网 发布:执行云计算的服务器 编辑:程序博客网 时间:2024/04/30 11:21

1:概述

面试软通动力第一面是电话面试

面试过程中主要为了几个问题,由于对概念型的概况掌握不是很好,重在的是动手能力,所以估计没有下文了吧!

下面列出面试问到的问题已经在google得到的解释

2:解释下原子性和非原子性

             nonatomic 非原子性 线程不安全 效率高

            atomic 原子性 线程安全 效率不高

            原子属性是一种单(线程)写多(线程)读的多线程技术,不过可能会出现脏数据

            atomic属性内部的锁称为 自旋锁

           凡是线程安全的对象,内部肯定会加锁

           atomic和nonatomic区别用来决定编译器生成的getter和setter是否为原子操作。atomic提供多线程安全,是描述该变量是否支持多线程的同步访问,如果选择了atomic 那么就是说,系统会自动的创建lock锁,锁定变量。nonatomic禁止多线程,变量保护,提高性能。

  • atomic:默认是有该属性的,这个属性是为了保证程序在多线程情况下,编译器会自动生成一些互斥加锁代码,避免该变量的读写不同步问题。
    nonatomic:如果该对象无需考虑多线程的情况,请加入这个属性,这样会让编译器少生成一些互斥加锁代码,可以提高效率。

  • atomic的意思就是setter/getter这个函数,是一个原语操作。如果有多个线程同时调用setter的话,不会出现某一个线程执行完setter全部语句之前,另一个线程开始执行setter情况,相当于函数头尾加了锁一样,可以保证数据的完整性。nonatomic不保证setter/getter的原语行,所以你可能会取到不完整的东西。因此,在多线程的环境下原子操作是非常必要的,否则有可能会引起错误的结果。

  • 比如setter函数里面改变两个成员变量,如果你用nonatomic的话,getter可能会取到只更改了其中一个变量时候的状态,这样取到的东西会有问题,就是不完整的。当然如果不需要多线程支持的话,用nonatomic就够了,因为不涉及到线程锁的操作,所以它执行率相对快些。

  • 下面是载录的网上一段加了atomic的例子:

  •   {lock}
                                    if (property != newValue) { 
                                            [property release]; 
                                            property = [newValue retain]; 
                                    }
                            {unlock}

  • 可以看出来,用atomic会在多线程的设值取值时加锁,中间的执行层是处于被保护的一种状态,atomic是oc使用的一种线程保护技术,基本上来讲,就是防止在写入未完成的时候被另外一个线程读取,造成数据错误。而这种机制是耗费系统资源的,所以在iPhone这种小型设备上,如果没有使用多线程间的通讯编程,那么nonatomic是一个非常好的选择。

     3:Runloop和线程之间的区别

           总的说来,Run loop,正如其名,loop表示某种循环,和run放在一起就表示一直在运行着的循环。实际上,run loop和线程是紧密相连的,可以这样说run loop是为了线程而生,没有线程,它就没有存在的必要。Run loops是线程的基础架构部分,Cocoa和CoreFundation都提供了run loop对象方便配置和管理线程的run loop(以下都以Cocoa为例)。每个线程,包括程序的主线程(main thread)都有与之相应的run loop对象

           runloop和线程的关系:主线程的run loop默认是启动的。iOS的应用程序里面,程序启动后会有一个如下的main()函数

         int main(int argc, char * argv[]) {

                   @autoreleasepool {

                         return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));

                 }

            }


        重点是UIApplicationMain()函数,这个方法会为main thread设置一个NSRunLoop对象,这就解释了:为什么我们的应用可以在无人操作的时候休息,需要让它干活的时候又能立马响应。

        对其它线程来说,run loop默认是没有启动的,如果你需要更多的线程交互则可以手动配置和启动,如果线程只是去执行一个长时间的已确定的任务则不需要。

在任何一个Cocoa程序的线程中,都可以通过以下代码来获取到当前线程的run loop。

         NSRunLoop *runloop = [NSRunLoop currentRunLoop];

  获得RunLoop对象后要调用run方法来启动一个运行循环 

   //启动RunLoop

   [[NSRunLoop currentRunLoop] run];


        RunLoop的其他启动方法 

   //第一个参数:指定运行模式
   //第二个参数:指定RunLoop的过期时间,即:到了这个时间后RunLoop就失效了

   [[NSRunLoop currentRunLoop] runMode:kCFRunLoopDefaultModebeforeDate:[NSDatedistantFuture]];

    4:冒泡算法实现

    NSMutableArray *arr_M = [NSMutableArray arrayWithObjects:@1,@4,@2,@3,@5,nil];    //遍历`数组的个数`次    /*     i = 0 的时候,j的相邻两个位置都要比较排一下位置:         j = 0 的时候:arr_M = 41235         j = 1 的时候:arr_M = 42135         j = 2 的时候:arr_M = 42315         j = 3 的时候:arr_M = 42351     i = 1;      ……  ……     */    for (int i = 0; i < arr_M.count; ++i) {        //遍历数组的每一个`索引`(不包括最后一个,因为比较的是j+1)        for (int j = 0; j < arr_M.count-1; ++j) {            //根据索引的`相邻两位`进行`比较`            if (arr_M[j] < arr_M[j+1]) {                [arr_M exchangeObjectAtIndex:j withObjectAtIndex:j+1];            }        }    }    NSLog(@"最终结果:%@",arr_M);

         5:block定义

         Block是一种比较特殊的数据类型。它可以保存一段代码,在合适的时候取出来调用。

         block的修饰

ARC情况下
1.如果用copy修饰Block,该Block就会存储在堆空间。则会对Block的内部对象进行强引用,导致循环引用。内存无法释放。
解决方法:
新建一个指针(__weak typeof(Target) weakTarget = Target )指向Block代码块里的对象,然后用weakTarget进行操作。就可以解决循环引用问题。

2.如果用weak修饰Block,该Block就会存放在栈空间。不会出现循环引用问题。

MRC情况下
用copy修饰后,如果要在Block内部使用对象,则需要进行(__block typeof(Target) blockTarget = Target )处理。在Block里面用blockTarget进行操作

Block的定义格式

返回值类型(^block变量名)(形参列表) = ^(形参列表) {
};
调用Block保存的代码
block变量名(实参);

6:delegate定义

在IOS中委托通过一种@protocol的方式实现,所以又称为协议.协议是多个类共享的一个方法列表

由于松耦合的原因,一个对象能成为多个对象的委托。某些情况下,相较于通过继承让子类实现相关的处理方法,可以有效减少代码复杂度。所以iOS中也大量的使用了委托。
委托对象的实现有两种方式:正式协议和非正式协议,对象主体在协议中定义委托方法,委托对象可以选择实现其中某些委托方法,因此如果通过正式协议定义委托方法需要使用@option。

7:动态库和静态库的定义 区别

库的分类

  • 开源库:源代码是公开的,可以看到每个实现文件(.m文件)的实现,例如GitHub上的常用的开源库:AFNetworking、SDWebImage等;
  • 闭源库:不公开源代码,是经过编译后的二进制文件,看不到具体的实现。闭源库又分为:静态库 和 动态库

静态库存在的形式

  • .a
  • .framework

动态库的存在形式

  • .dylib
  • .framework

静态库和动态库的区别

  • .a文件肯定是静态库,.dylib肯定是动态库,.framework可能是静态库也可能是动态库;
  • 静态库在链接时,会被完整的复制到可执行文件中,如果多个App都使用了同一个静态库,那么每个App都会拷贝一份,缺点是浪费内存。类似于定义一个基本变量,使用该基本变量是是新复制了一份数据,而不是原来定义的;
  • 动态库不会复制,只有一份,程序运行时动态加载到内存中,系统只会加载一次,多个程序共用一份,节约了内存。类似于使用变量的内存地址一样,使用的是同一个变量;
  • 但是项目中如果使用了自己定义的动态库,苹果是不允许上架的,在iOS8.0以后苹果开放了动态加载.dylib的接口,用于挂载.dylib动态库

静态库的运用场景

  • 保护自己的核心代码,如讯飞语言摸索了好多年探索出的结果当然要保护起来了,都公开了公司还怎么生存。
  • 将MRC的项目打包成静态库,可以在ARC下直接使用,不用转换。如别人使用MRC写的开源库,放到自己ARC项目中,需要对每个文件加一个编译参数 -fno-objc-arc,这样相对来说麻烦,将整个工程打包成静态库直接放到项目中即可,也不用对每个文件添加编译选项。

静态库的特点

.a + .h

.a : 可以看做所有.m文件加密后的一个二进制文件
.h : 头文件用户暴漏可用的接口(方法)


静态库的版本

静态库有4种版本:

  • 调试版本:不会对代码进行优化
    • 模拟器版本
    • 真机版本
  • 发布版本 :会对代码进行优化,执行效率相对调试版本快,但不会有明显的差别
    • 模拟器版本
    • 真机版本

.bundle

在使用第三方库时有可能会有一个.bundle文件,.bundle其实是一个物理文件夹,里面可以放图片等资源。因为.bundle是一个物理文件夹,所以当被拖入到项目中就不会和自己项目中的图片重名。

.a 和 .framework

使用.a时需要同时将.a 和 .h 文件拖入到工程中,使用.framework时直接将这个文件夹拖入进去即可,因为.framework文件夹中已经包含了.h文件。

.a + .h + .bundle = .framework, 使用.framework更加方便


Swift不支持静态库只支持动态库

Swift is not supported for static libraries.
Swift暴漏方法的方式:Swift不像OC那样有头文件,将Swift中的类和方法用public修饰就可以将类和方法暴漏出来



8:xamp

对即时通讯的了解
由于用的是第三方的环信和融云,所以对底层的代码无法获知,智能修改相应的UI模块,或自定义拓展UI


9:ios cpu指令集

ARMv8-A = iPhone 6s,iPhone 6s Plus,iPad Air 2,Apple TV 4,iPad Air,iPhone 6ARMv8/ARM64 = iPhone 5s, iPad Air, Retina iPad MiniARMv7s = iPhone 5, iPhone 5c, iPad 4ARMv7  = iPhone 3GS, iPhone 4, iPhone 4S, iPod 3G/4G/5G, iPad, iPad 2, iPad 3, iPad Mini  ARMv6  = iPhone, iPhone 3G, iPod 1G/2G

10:对runtime的理解和项目中的运用

       Runtime基本是用C和汇编写的,Objective-C 是一门动态语言,所以它需要一个运行时系统……这就是 Runtime 系统,RunTime简称运行时,就是系统在运行的时候的一些机制,其中最主要的是消息机制。

       http://yulingtianxia.com/blog/2014/11/05/objective-c-runtime/ 这编文章对Runtime描述得很好,建议查看。



    

1 0
原创粉丝点击