美文网首页
iOS 面试题

iOS 面试题

作者: afd0a1817353 | 来源:发表于2016-04-01 04:14 被阅读303次
    1.#import和#include的区别 @class?
    • @class一般用于头文件中需要声明该类的某个实例变量的时候用到,在m文 件中还是需要使用#import
      #import比起#include的好处就是不会引起交叉编译
    2. readwrite,readonly,assign,retain,copy,nonatomic 属性的作用
    • @property是 一个属性访问声明,扩号内支持以下几个属性:
    • 1,getter=getNamesetter=setName,设置setter与 getter的方法名
    • 2,readwrite,readonly,设置可供访问级别
    • 3,assignsetter方法直接赋值,不进行任何retain操作,为了解决原类型与环循引用问题
    • 4,retainsetter方法对参数进行release旧值再retain新值,所有 实现都是这个顺序(CC上有相关资料)
    • 5,copysetter方法进行Copy操作,与retain处理流程一样,先旧值release,再 Copy出新的对象,retainCount为1。这是为了减少对上下文的依赖而引入的机制。
    • 6,nonatomic,非原子性访问,不加同步, 多线程并发访问会提高性能。注意,如果不加此属性,则默认是两个访问方法都为原子型事务访问。锁被加到所属对象实例级(我是这么理解的…)。
    3.在一个对象的方法里面:self.name= “object”;和 name =”object” 有什么不同吗?
    • self.name =”object”:会调用对象的setName()方法;
    • name = “object”:会直接把object赋值给当前对象的name属性。
    4.请简述self.name= nil的机制,以及与[namerelease]的区别?
    • self.name =nil;
      //使用nil参数调用setName:方法

    • [name release] 生成的访问器将自动释放以前的name对象

    5.请简要说明viewDidLoad和viewDidUnload何时调用
    • viewDidLoad在view从nib文件初始化时调用
    • loadView在controller的view为nil时调用。
      此方法在编程实现view时调用,view控制器默认会注册memory warning notification,
    • 当view controller的任何view没有用的时候,
      viewDidUnload会被调用,在这里实现将retain的view release,如果是retain的IBOutlet view 属性则不要在这里release,IBOutlet会负责release 。
    • 控制器View的生命周期:
      • 首先判断控制器是否有视图,如果没有就调用loadView方法创建:通过storyboard或者代码

      • 随后调用viewDidLoad,可以进行下一步的初始化操作;只会被调用一次

    • 在视图显示之前调用viewWillAppear;该函数可以多次调用
    • 视图viewDidAppear
    • 在视图显示之前调用viewWillDisappear;该函数可以多次调用(如需要)
    • 在布局变化前后,调用viewWill/DidLayoutSubviews处理相关信息
    6.实例化一个UITableView对象,要求写出关键语句?
    UITableView *my = [[UITableView alloc]initWithFrame:<(CGRect)frame> style:<(UITableViewStyle)style>];
    my.delegate = self;
    my.dataSource = self;
    
    • 首先需要分配空间设置表格类型
      然后需要设置两个必须的委托对象。
    7.使用sql语句查询出省名以湖开头,邮编为436001所在的市区?(表名及字段名自定义)

    select*fromcitys where postcode=436001 and province=’湖%’;

    8.打印结果
    main()
    {
        int a[5]={1,2,3,4,5};
        int *ptr=(int *)(&a+1);
        printf(“%d,%d”,*(a+1),*(ptr-1));
    }
    
    • 2,5
    • (a+1)就是a[1],(ptr-1)就是a[4],执行结果是2,5
    • &a+1不是首地址+1,系统会认为加一个a数组的偏 移,是偏移了一个数组的大小(本例是5个int)int *ptr=(int *)(&a+1);
    • 则ptr实际 是&(a[5]),也就是a+5
    • 原因如下:
      • &a是数组指针,其类型为 int ( * )[5];
      • 而 指针加1要根据指针类型加上一定的值,不同类型的指针+1之后增加的大小不同。
      • a是长度为5的int数组指针,所以要加 5*sizeof(int)
      • 所以ptr实际是a[5]
      • 但是prt与(&a+1)类型是不一样的(这点很重要)
      • 所以prt-1只会减去sizeof(int*)
        a,&a的地址是一样的
      • 但意思不一样 a是数组首地址
      • 也就是a[0]的地址
      • &a是对象(数组)首地址
      • a+1是数组下一元素的地址
      • 即a[1],&a+1是下一个对象的地址,即a[5].
    void Func ( char str[100] )
    {
        sizeof(str ) = ?
    }
    void *p = malloc( 100 );
    sizeof( p ) = ?
    
    
    • 这题 很常见了,Func ( char str[100] )函数中数组名作为函数形参时,在函数体内,数组名失去了本身的内涵,仅仅只是一个指针;在失去其内涵的同时,它还失去了其常量特性,可以作自增、自减等操作,可以被修改。Windows NT 32位平台下,指针的长度(占用内存的大小)为4字节,故sizeof( str ) 、sizeof( p ) 都为4。
    9.用预处理指令#define声明一个常数,用以表明1年中有多少秒(忽略闰年问题)
    • defineSECONDS_PER_YEAR (60 * 60 * 24 * 365)UL
      我在这想看到几件事情:

    • #define 语法的基本知识(例如:不能以分号结束,括号的使用,等等)

    • 懂得预处理器将为你计算常数表达式的值,因此,直接写出你是如何计算一年中有多少秒而不是计算出实际的值,是更清晰而没有代价的。
      意识到这个表达式将使一个16位机的整型数溢出-因此要用到长整型符号L,告诉编译器这个常数是的长整型数。
      如果你在你的表达式中用到UL(表示无符号长整型),那么你有了一个好的起点。记住,第一印象很重要。

    10.写一” 标准”宏MIN ,这个宏输入两个参数并返回较小的一个
    • #define MIN(A,B)((A) <= (B) ? (A) : (B))
    • 这个测试是为下面的目的而设的:
      标识#define在宏中应用的基本知识。这是很重要的,因为直到嵌入(inline)操作符变为标准C的一部分,宏是方便产生嵌入代码的唯一方
      法,对于嵌入式系统来说,为了能达到要求的性能,嵌入代码经常是必须的方法。
    • 三重条件操作符的知识。这个操作符存在C语言中的原因是它使得编译器能产生比 if-then-else 更优化的代码,了解这个用法是很重要的。 懂得在宏中小心地把参数用括号括起来 我也用这个问题开始讨论宏的副作用
    • 例如:当你写下面的代码时会发生什么事?least = MIN(*p++, b);
    • 结果是:
      ((*p++) <= (b) ? (*p++) :(*p++))
      这个表达式会产生副作用,指针p会作三次++自增操作。
    11.数组和指针的区别
    • 数组可以申请在栈区和数据区;指针可以指向任意类型的内存块
    • sizeof作用于数组时,得到的是数组所占的内存大小;作用于指针时,得到的都是4个字节的大小
    • 数组名表示数组首地址,值不可以改变,如不可以将++作用于数组名上;普通指针的值可以改变,如可将++作用于指针上
    • 用字符串初始化字符数组是将字符串的内容拷贝到字符数组中;用字符串初始化字符指针是将字符串的首地址赋给指针,也就是指针指向了该数组
    12.static的作用
    • 函数体内static 变量的作用范围为该函数体,不同于 auto 变量,该变量的内存只被分配一次,
      因此其值在下次调用时仍维持上次的值;
    • 在模块内的static 全局变量可以被模块内所用函数访问,但不能被模块外其它函数访问;
    • 在模块内的static函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明它的模块内;
    • 在类中的static成员变量属于整个类所拥有,对类的所有对象只有一份拷贝;
    • 在类中的static 成员函数属于整个类所拥有,这个函数不接收 this 指针,因而只能访问类的static 成员变量。
    13.简述内存分区情况
    • 代码区:存放函数二进制代码
    • 数据区:系统运行时申请内存并初始化,系统退出时由系统释放。存放全局变量、静态变量、常量
    • 堆区:通过malloc等函数或new等操作符动态申请得到,需程序员手动申请和释放
    • 栈区:函数模块内申请,函数结束时由系统自动释放。存放局部变量、函数参数
    14.#include<filename>和#include”filename”有什么区别
    • #include<filename>直接在库文件目录中搜索所包含的文件;
    • #include”filename”在当前目录下搜索所包含的文件,如果没有的话再到库文件目录搜索。
    15.const char * p; char const * p; char * const p; const char * const p;
    • 四个修饰指针有什么区别

    • (1)定义了一个指向不可变的字符串的字符指针

    • (2)和(1)一样

    • (3)定义了一个指向字符串的指针,该指针值不可改变,即不可改变指向

    • (4)定义了一个指向不可变的字符串的字符指针,且该指针也不可改变指向

    16.MVC的理解?
    • MVC模式考虑三种对象:
    • 模型对象 Model
    • 视图对象 View
    • 控制器对象。Controller
      • 模型对象负责应用程序的数据和定义操作数据的逻辑;
      • 视图对象知道如何显示应用程序的模型数据;
      • 控制器对象是M与V之间的协调者。
    17.在Obj-c中有没有私有方法?私有变量?一般采用什么方法实现?
    • objective-c – 类里面的方法只有两种, 静态方法和实例方法.
    • 这似乎就不是完整的面向对象了,按照OO的原则就是一个对象只暴露 有用的东西.
    • 如果没有了私有方法的话,对于一些小范围的代码重用就不那么顺手了. 在类里面声名一个私有方法
    @interfaceController : NSObject { NSString *something; }
    +(void)thisIsAStaticMethod;
    -(void)thisIsAnInstanceMethod;
    @end
    @interfaceController (private)
    -(void)thisIsAPrivateMethod;
    @end
    
    • @private可以用来修饰私有变量
      在Objective‐C中,所有实例变量默认都是私有的,所有实例方法默认都是公有的
    18.OC中加号方法与减号的区别?
    • 加号方法是类方法,属于静态方法
    • 减号方法是实例方法必须由类的实例来调用
    19.free与release的区别
    20.在终端环境下,分别说明4,2,1,0对应的权限是什么
    • linux系统下文件的权限由三位二进制数表示,从左到右依次表示读、写、可执行。0表示不行,1表示行。4对应2进制的100,就是可读不可写不可执行。
    21.ARC机制

    ARC就是automatic reference counting ,简单说就是就是代码中自动加入了retain/release,原先需要手动添加的用来处理内存管理的引用计数的代码可以自动地由编译器完成了。

    • 使用ARC的好处
      使用ARC有什么好处呢?
      看到上面的例子,大家就知道了,以后写Objective-C的代码变得简单多了,因为我们不需要担心烦人的内存管理,担心内存泄露了,代码的总量变少了,看上去清爽了不少,也节省了劳动力
      代码高速化,由于使用编译器管理引用计数,减少了低效代码的可能性
    • 不好的地方
      记住一堆新的ARC规则—关键字及特性等需要一定的学习周期
      一些旧的代码,第三方代码使用的时候比较麻烦;修改代码需要工数,要么修改编译开关
    22.自动释放池是什么,如何工作
    • 当向一个对象发送一个autorelease 消息时,Cocoa就会将该对象的一个引用放入到最新的自动释放池。
    • 它仍然是个正当的对象,因此自动释放池定义的作用域内的其它对象可以向它发送消息。当程序执行到作用域结束的位置时,自动释放池就会被释放,池中的所有对象也就被释放。
    • ojc-c 是 通过一种referring counting(引用计数)的方式来管理内存的, 对象在开始分配内存(alloc)的时候引用计数为一,以后每当碰到有copy,retain的时候引用计数都会加一, 每当碰到release和autorelease的时候引用计数就会减一,如果此对象的计数变为了0, 就会被系统销毁.
    • NSAutoreleasePool 就是用来做引用计数的管理工作的,这个东西一般不用你管的.
    • autoreleaserelease没什么区别,只是引用计数减一的时机不同而已,autorelease会在对象的使用真正结束的时候才做引用计数减一.
    23.浅复制和深复制的区别?//浅拷贝和深拷贝
    • 浅层复制(copy):只复制指向对象的指针,而不复制引用对象本身。//通过对象的指针来访问这个对象
    • 深层复制(mutableCopy):复制引用对象本身 意思就是有个A对象,复制一份后得到A_copy对象后,对于浅复制来说,A和A_copy指向的是同一个内存资源,复制的只不过是是一个指针,对象本身资源 还是只有一份,那如果我们对A_copy执行了修改操作,那么发现A引用的对象同样被修改,这其实违背了我们复制拷贝的一个思想。深复制就好理解了,内存中存在了 两份独立对象本身。//当修改A时,A copy不变。
    25.frame和bounds有什么不同?
    • frame指的是:该view在父view坐标系统中的位置和大小。(参照点是父亲的坐标系统)//frame:框架、结构
    • bounds指的是:该view在本身坐标系统中 的位置和大小。(参照点是本身坐标系统)//bounds:界限
    26. obj-c的优缺点
    • 优点:
    • Cateogies
    • Posing
    • 动态识别
    • 指标计算
    • 弹性讯息传递
    • 不是一个过度复杂的 C 衍生语言
    • Objective-C 与 C++ 可混合编程
    • 缺点:
    • 不支援命名空间
    • 不支持运算符重载
    • 不支持多重继承
    • 使用动态运行时类型,所有的方法都是函数调用,所以很多编译时优化方法都用不到。(如内联函数等),性能低劣。
    27.用变量a给出下面的定义
    a)一个整型数(An integer)
    b)一个指向整型数的指针( A pointer to aninteger)
    c)一个指向指针的的指针,它指向的指针是指向一个整型数( Apointer to a pointer to an intege)r
    d)一个有10个整型数的数组( An array of 10 integers)
    e) 一个有10个指针的数组,该指针是指向一个整型数的。(An array of 10 pointers to integers)
    f) 一个指向有10个整型数数组的指针( A pointer to an array of 10 integers)
    g) 一个指向函数的指针,该函数有一个整型参数并返回一个整型数(Apointer to a function that takes an integer as an argument
     andreturns an integer)
    h)一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数( An array of ten pointers to functions t
    hat takean integer argument and return an integer )
    
    a) int a; // Aninteger
    b) int *a; // A pointer to aninteger
    c) int **a; // A pointer to apointer to an integer
    d) int a[10]; // An array of10 integers
    e) int *a[10]; // An array of10 pointers to integers
    f) int (*a)[10]; // A pointerto an array of 10 integers
    g) int (*a)(int); // A pointerto a function a that takes an integer argument and returns aninteger
    h) int (*a[10])(int); // Anarray of 10 pointers to functions that take an integer argument andreturn an integer
    
    28.写出几个死循环?
    29.队列和栈有什么区别:
    • 队列和栈是两种不同的数据容器。从”数据结构”的角度看,它们都是线性结构,即数据元素之间的关系相同。
    • 队列是一种先进先出的数据结构,它在两端进行操作,一端进行入队列操作,一端进行出列队操作。
    • 栈是一种先进后出的数据结构,它只能在栈顶进行操作,入栈和出栈都在栈顶操作。
    30.HTTP协议中,POST和GET的区别是什么?
    • 1.GET方法
    • GET方法提交数据不安全,数据置于请求行,客户端地址栏可见;
    • GET方法提交的数据大小有限
    • GET方法不可以设置书签
    • 2.POST方法
    • POST方法提交数据安全,数据置于消息主体内,客户端不可见
    • POST方法提交的数据大小没有限制
    • POST方法可以设置书签
    31. iOS的系统架构分为
    • (核心操作系统层theCore OS layer)
    • (核心服务层theCore Services layer)
    • (媒体层theMedia layer)
    • (Cocoa界面服务层the Cocoa Touch layer)四个层次
    32. 控件主要响应3种事件:
    • (基于触摸的事件)
    • (基于值的事件)
    • (基于编辑的事件)。
    33.xib文件的构成分为哪3个图标?都具有什么功能。
    • File’s Owner是所有nib文件中的每个图标,它表示从磁盘加载nib文件的对象;
    • First Responder就是用户当前正在与之交互的对象;
    • View显示用户界面;完成用户交互;是UIView类或其子类。
    34. 简述视图控件器的生命周期。
    • loadView尽管不直接调用该方法,如多手动创建自己的视图,那么应该覆盖这个方法并将它们赋值给试图控制器的view属性。

    • viewDidLoad只有在视图控制器将其视图载入到内存之后才调用该方法,这是执行任何其他初始化操作的入口。

    • viewVillAppear当试图将要添加到窗口中并且还不可见的时候或者上层视图移出图层后本视图变成顶级视图时调用该方法,用于执行诸如改变视图方向等的操作。实现该方法时确保调用[super viewWillAppear:].

    • viewDidAppear当视图添加到窗口中以后或者上层视图移出图层后本视图变成顶级视图时调用,用于放置那些需要在视图显示后执行的代码。确保调用[super viewDidAppear:]。

    • viewDidUnload当试图控制器从内存释放自己的方法的时候调用,用于清楚那些可能已经在试图控制器中创建的对象。

    35. 动画有基本类型有哪几种;表视图有哪几种基本样式?
    • 动画有两种基本类型:
    • 隐式动画
    • 显式动画。
    36. 实现简单的表格显示需要设置UITableView的什么属性、实现什么协议?
    • 实现简单的表格显示需要设置UITableViewdataSourcedelegate 属性,实现UITableViewDataSourceUITableViewDelegate 协议。
    37. Cocoa Touch提供了哪几种Core Animation过渡类型(10分)?
    • Cocoa Touch 提供了 4 种 Core Animation 过渡类型,分别为:
    • 交叉淡化
    • 推挤
    • 显示
    • 覆盖
    38. UIView与CLayer有什么区别?
    1. UIView 是 iOS 系统中界面元素的基础,所有的界面元素都是继承自它。它本身完全是由 CoreAnimation 来实现的。它真正的绘图部分,是由一个 CALayer 类来管理。 UIView 本身更像是一个 CALayer 的管理器,访问它的跟绘图和跟坐标有关的属性。
    2. UIView 有个重要属性 layer ,可以返回它的主 CALayer 实例。
    3. UIView 的 CALayer 类似 UIView 的子 View 树形结构,也可以向它的 layer 上添加子layer ,来完成某些特殊的表示。即 CALayer 层是可以嵌套的。
    4. UIView 的 layer 树形在系统内部,被维护着三份 copy 。分别是逻辑树,这里是代码可以操纵的;动画树,是一个中间层,系统就在这一层上更改属性,进行各种渲染操作;显示树,其内容就是当前正被显示在屏幕上得内容。
    5. 动画的运作:对 UIView 的 subLayer (非主 Layer )属性进行更改,系统将自动进行动画生成,动画持续时间的缺省值似乎是 0.5 秒。
    6. 坐标系统: CALayer 的坐标系统比 UIView 多了一个 anchorPoint 属性,使用CGPoint 结构表示,值域是 0~1 ,是个比例值。这个点是各种图形变换的坐标原点,同时会更改 layer 的 position 的位置,它的缺省值是 {0.5,0.5} ,即在 layer 的中央。
    7. 渲染:当更新层,改变不能立即显示在屏幕上。当所有的层都准备好时,可以调用setNeedsDisplay 方法来重绘显示。
    8. 变换:要在一个层中添加一个 3D 或仿射变换,可以分别设置层的 transform 或affineTransform 属性。
    9. 变形: Quartz Core 的渲染能力,使二维图像可以被自由操纵,就好像是三维的。图像可以在一个三维坐标系中以任意角度被旋转,缩放和倾斜。 CATransform3D 的一套方法提供了一些魔术般的变换效果。
    39.链表翻转。
    40. 链表逆序(C语言)。

    链表逆序就是把一个链表按照原来的链接顺序逆序实现(也就是将头变成尾,尾变成头)。
    编程思路:其实最关键的是先通过原来的链接顺序找到下个节点,然后再把前个节点反序。

    41. Quatrz 2D的绘图功能的三个核心概念是什么并简述其作用(10分)。
    • 上下文:主要用于描述图形写入哪里;
    • 路径:是在图层上绘制的内容;
    • 状态:用于保存配置变换的值、填充和轮廓, alpha 值等。
    42. iPhone OS主要提供了几种播放音频的方法(10分)?
    • SystemSound Services
    • AVAudioPlayer 类
    • Audio Queue Services
    • OpenAL
    43. 使用AVAudioPlayer类调用哪个框架、使用步骤(10分)?
    • AVFoundation.framework
    • 步骤:
      • 配置 AVAudioPlayer 对象;
      • 实现 AVAudioPlayer 类的委托方法;
      • 控制 AVAudioPlayer 类的对象;
      • 监控音量水平;
      • 回放进度和拖拽播放。
    44. 有哪几种手势通知方法、写清楚方法名?
    -(void)touchesBegan:(NSSet*)touchedwithEvent:(UIEvent*)event;
    -(void)touchesMoved:(NSSet*)touched withEvent:(UIEvent*)event;
    -(void)touchesEnded:(NSSet*)touchedwithEvent:(UIEvent*)event;
    -(void)touchesCanceled:(NSSet*)touchedwithEvent:(UIEvent*)event;
    
    45. 实例化一个UITableView对象,要求写出关键语句。
    UITableView *my = [[UITableView alloc]initWithFrame:<(CGRect)frame> style:<(UITableViewStyle)style>];
    my.delegate = self;
    my.dataSource = self;
    
      • 首先需要分配空间设置表格类型
      • 然后需要设置两个必须的委托对象。
    46. CFSocket使用有哪几个步骤(10分)。
    • 创建 Socket 的上下文;
    • 创建 Socket ;
    • 配置要访问的服务器信息;
    • 封装服务器信息;连接服务器;
    47. Core Foundation中提供了哪几种操作Socket的方法?
    • CFNetwork
    • CFSocket
    • BSD Socket 。
    48. 解析XML文件有哪几种方式(10分)?
    • 以 DOM 方式解析 XML 文件
    • 以 SAX 方式解析 XML 文件;
    49. 自定义一个委托(15分)。
    @protocol SimpleProtocol
    -(void)doSomething:(NSString*)str;
    @end
    @interfaceSimpleClass:NSObject< SimpleProtocol >{
    }
    @end
    @implementationSimpleClass
    -(void)doSomething:(NSString *)str
    {
    NSLog(str);
    }
    @end
    
    50. 类别的作用?继承和类别在实现中有何区别?
    • category 可以在不获悉,不改变原来代码的情况下往里面添加新的方法,只能添加,不能删除修改。
    • 并且如果类别和原来类中的方法产生名称冲突,则类别将覆盖原来的方法,因为类别具有更高的优先级。
    • 类别主要有 3 个作用:
      • (1) 将类的实现分散到多个不同文件或多个不同框架中。
      • (2) 创建对私有方法的前向引用。
      • (3) 向对象添加非正式协议。 继承可以增加,修改方法,并且可以增加属性。
    51.通知和协议的不同之处?
    • 协议有控制链 (has-a) 的关系,通知没有。 首先我一开始也不太明白,什么叫控制链(专业术语了 ~ )。但是简单分析下通知和代理的行为模式,我们大致可以有自己的理解
    • 简单来说,
    • 通知的话,它可以一对多,一条消息可以发送给多个消息接受者。
    • 代理按我们的理解,到不是直接说不能一对多,比如我们知道的明星经济代理人,很多时候一个经济人负责好几个明星的事务。只是对于不同明星间,代理的事物对象都是不一样的,一一对应,不可能说明天要处理 A明星要一个发布会,代理人发出处理发布会的消息后,别称 B 的发布会了。但是通知就不一样,他只关心发出通知,而不关心多少接收到感兴趣要处理。 因此控制链(has-a) 从英语单词大致可以看出,单一拥有和可控制的对应关系。
    52.关于多态性
    • 多态,子类指针可以赋值给父类。 这个题目其实可以出到一切面向对象语言中, 因此关于多态,继承和封装基本最好都有个自我意识的理解,也并非一定要把书上资料上写的能背出来。 最重要的是转化成自我理解。
    53.对于单例的理解
    • 基本能用熟悉的语言写出一个单例,以及可以运用到的场景或是你编程中碰到过运用的此种模式的框架类等。 进一步点,考虑下如何在多线程访问单例时的安全性。
    
    @interface PBPerson() <NSCopying>
    
    @end
    
    @implementation PBPerson
    
    static PBPerson *_person;
    
    + (instancetype)allocWithZone:(struct _NSZone *)zone
    {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            _person = [super allocWithZone:zone];
        });
        return _person;
    }
    
    + (instancetype)sharedPerson
    {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            _person = [[self alloc] init];
        });
        return _person;
    }
    
    - (id)copyWithZone:(NSZone *)zone
    {
        return _person;
    }
    @end
    
    54. 是否在一个视图控制器中嵌入两个tableview控制器?
    • 一个视图控制只提供了一个 View 视图,理论上一个 tableViewController 也不能放吧, 只能说可以嵌入一个 tableview 视图。当然,题目本身也有歧义,如果不是我们定性思维认为的 UIViewController , 而是宏观的表示视图控制者,那我们倒是可以把其看成一个视图控制者,它可以控制多个视图控制器,比如 TabbarController 那样的感觉。
    55. 一个tableView是否可以关联两个不同的数据源?你会怎么处理?
    • 首先我们从代码来看,数据源如何关联上的,其实是在数据源关联的代理方法里实现的。
    • 因此我们并不关心如何去关联他,他怎么关联上,方法只是让我返回根据自己的需要去设置如相关的数据源。
    • 因此,我觉得可以设置多个数据源啊,但是有个问题是,你这是想干嘛呢?想让列表如何显示,不同的数据源分区块显示?
    56. Object -c 的类可以多重继承么?可以实现多个接口么?重写一个类的方式用继承好还是分类 好?为什么?

    答案: Objective-c 只支持单继承,如果要实现多继承的话,可以通过类别和协议的方式来实现, cocoa 中所有的类都是 NSObject 的子类,多继承在这里是用 protocol 委托代理来实现的。

    57. id 声明的对象有什么特性?
    • id 是个很重要的类型,是个可以指向任何类型的指针或者可以理解为指向任何未知类型的指针。
    58. 自动释放池跟GC (垃圾回收)有什么区别?iPhone上有GC么?[poolrelease] 和[pooldrain]有什么区别?
    • iPhone 上没有 GC 。 iPhone 开发的时候没有垃圾回收机制。
    • 在垃圾回收环境中,release 是一个空操作。
    • 因此, NSAutoreleasePool 提供了 drain 方法,在引用计数环境中,该方法的作用等同于调用 release ,但在垃圾回收环境中,它会触发垃圾回收(如果自上次垃圾回收以来分配的内存大于当前的阈值)。
    • 因此,在通常情况下,我们应该使用 drain 而不是 release 来销毁自动释放池。
    59. 线程与进程的区别和联系?
    • 进程和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性。
    • 进程和线程的主要差别在于它们是不同的操作系统资源管理方式。
    • 进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。
    • 线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。
    60. ios 平台怎么做数据的持久化?coredata 和sqlite有无必然联系?coredata是一个关系型数据库吗?
    • iOS 中可以有四种持久化数据的方式:
    • 属性列表
    • 对象归档
    • SQLite3
    • Core Data
    • core data可以使你以图形界面的方式快速的定义 app 的数据模型,同时在你的代码中容易获取到它。 coredata 提供了基础结构去处理常用的功能,例如保存,恢复,撤销和重做,允许你在 app 中继续创建新的任务。在使用 core data的时候,你不用安装额外的数据库系统,因为 core data 使用内置的 sqlite 数据库。 core data 将你 app 的模型层放入到一组定义在内存中的数据对象。 coredata 会追踪这些对象的改变,同时可以根据需要做相反的改变,例如用户执行撤销命令。当 core data 在对你 app 数据的改变进行保存的时候, core data 会把这些数据归档,并永久性保存。
    • mac os x 中sqlite库,它是一个轻量级功能强大的关系数据引擎,也很容易嵌入到应用程序。可以在多个平台使用, sqlite 是一个轻量级的嵌入式 sql 数据库编程。与 core data 框架不同的是, sqlite 是使用程序式的, sql 的主要的 API 来直接操作数据表。
    • Core Data不是一个关系型数据库,也不是关系型数据库管理系统 (RDBMS) 。虽然 Core Dta 支持SQLite 作为一种存储类型,但它不能使用任意的 SQLite 数据库。 Core Data 在使用的过程种自己创建这个数据库。 Core Data 支持对一、对多的关系。
    61. obj-c 有多重继承么? 如果没有什么替代方法?
    • cocoa 中所有的类都是NSObject 的子类,多继承在这里是用protocol 委托代理来实现的。不用去考虑繁琐的多继承,虚基类的概念。
    63. 假定输入的字符串中只包含字母和* 号。编写函数fun,功能是,除了中间和尾部的*号外,

    将字符串中其他* 号全部删除。编写时,不用c的其他函数。
    例:*****ABCDEFG**** 结果为:ABCDEFG****

    void fun (char *a)
     {
        int j=0;
        char *p=a;
        while (*p==’*')p++;
        while (*p)
        {
            a[j++]=*p;
            p++;
        }
        a[j]=0;
     }
    
    64. 截取字符串”20 |http://www.pacebill.com“ 中 ‘|’字符前面及后面的数据,分别输出它们。
    NSString *str = “20|http://www.pacebill.com”;
    NSRange range = [strrangeOfString:@"|"];
    int location = range.location;
    NSString *str1 = [strsubstringToIndex:location];
    NSString *str2 = [str substringFromIndex:location+1];
    
    65. 获取项目根路径,并在其下创建一个名称为userData 的目录。
    // 获取根路径
    NSArray *paths=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
    NSString *documentsDirectory = [paths objectAtIndex:];
    // 创建文件系统管理器
    NSFileManager *fileManager = [[NSFileManageralloc] init];
    // 判断userData 目录是否存在
    if(![fileManagerfileExistsAtPath:[NSStringstringWithFormat:@"%@/userData",documentsDirectory]]) {
    // 不存在, 创建一个userData目录
    [fileManagercreateDirectoryAtPath:[NSStringstringWithFormat:@"%@/userData",documentsDirectory]withIntermediateDirectories:falseattributes:nilerror:nil];
    }
    
    66. tableView 的重用机制?
    • UITableView 通过重用单元格来达到节省内存的目的:
    • 通过为每个单元格指定一个重用标识符(reuseIdentifier),即指定了单元格的种类,以及当单元格滚出屏幕时,允许恢复单元格以便重用.
    • 对于不同种类的单元格使用不同的ID,对于简单的表格,一个标识符就够了.
    67. 这段代码有什么问题吗
    @implementation Person
    i.(void)setAge:(int)newAge
    {
    self.age = newAge;
    }
    
    • 死循环
    69. 给定一个字符串,输出本字符串中只出现一次并且最靠前的那个字符的位置?

    比如”abaccddeeef” 则是b,输出2

    int find(char *_str)
    {
        char *p = _str;
        inti = 1;
        while (*p)
        {
            char *temp = _str;
            while (*temp)
            {
                if ((*p ==*temp)&&(p != temp))
                {
                    break;
                }
                temp++;
                if (*temp == 0) {
                    returni;
                }
            }
            i++;
            p++;
        }
        return-1;
    }
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    intfind_char(constchar* str)
    {
        staticintpos[256];
        const unsigned char* p =(const unsigned char*)str;
        inti = 0;
        if( (!str) || (!(*str)) )return -1;
        memset(pos,-1,sizeof(pos));
        while(*p){
            if(pos[*p] == -1){
                pos[*p] = p-(const unsigned char*)str;
            }else{
                pos[*p] = -2;
            }
            p++;
        }
        for(i=0;i<sizeof(pos)/sizeof(pos[0]);i++){
            if(pos[i]>=0)returnpos[i];
        }
        return -1;
    }
    int main()
    {
        constchar* p =”abaccddeeef”;
        intpos = find_char(p);
        printf(“%d, it is’%c’\n”,pos,pos!=-1?p[pos]:’ ‘);
        p =”abcdefghijklmnopqrstuvwxyz “
        “abcdefghijklmnopqrstuwxyz”;
        pos = find_char(p);
        printf(“%d, it is’%c’\n”,pos,pos!=-1?p[pos]:’ ‘);
        return0;
    }
    

    70. objective-c 中的数字对象都有哪些,简述它们与基本数据类型的区别是什么?

    • 在OC 中NSNumber是数字对象,可以进行拆装箱操作!
      // 将int 转为NSNumber
    • NSNumber *num = [NSNumber numberWithInt:123];
      // 得到一个int
      inttestNum = [numintValue];
    71. 用NSLog 函数输出一个浮点类型,结果四舍五入,并保留一位小数
    NSLog(@”%0.1f”,4.4324);
    
    
    72. objective-c 中的词典对象、可变词典对象是哪个,初始化一个含有两个键值对的可变词典对象,并动态的添加和删除一条记录,输出第一条记录.
    • 词典NSDictionary ,可变词典NSMutableDictionary,
    // 初始化一个可变词典,带有2 个键值对
    NSMutableDictionary *dic =[NSMutableDictionarydictionaryWithObjectsAndKeys:@"value1",@"key1",@"value2",@"key2",nil];
    // 添加
    [dicsetObject:@"value3"forKey:@"key3"];
    // 删除
    [dicremoveObjectForKey:@"key3"];
    // 获取(按key 获取)
    [dicobjectForKey:@"key1"];
    
    73. 获取项目根路径,并在其下创建一个名称为userData 的目录。
    // 获取根路径
    NSArray *paths=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
    NSString*documentsDirectory = [paths objectAtIndex:];
    // 创建文件系统管理器
    NSFileManager *fileManager= [[NSFileManageralloc] init];
    // 判断userData 目录是否存在
    if(![fileManagerfileExistsAtPath:[NSStringstringWithFormat:@"%@/userData",documentsDirectory]]) {
    // 不存在, 创建一个userData目录
    [fileManagercreateDirectoryAtPath:[NSStringstringWithFormat:@"%@/userData",documentsDirectory]withIntermediateDirectories:falseattributes:nilerror:nil];
    }
    
    74. do-while 与 while-do 的区别?
    • do-while 先执行循环体,然后判断条件,如果条件判断为ture ,则继续执行循环体,如果判断为false,则不执行循环体
    • while-do 是先判断条件是否正确,若正确则执行循环体,若不正确则不执行循环体。
    • 所以do-while 至少循环一次,而while-do有可能一次也不循环。
    75. 用C 语言,求2到100内的所有素数和。
    #include<stdio.h>
    intisPrime(int n)
    //求素数,这是最经典的算法代码。建议记住
    {
        inti;
        for(i=2;i*i<=n;i++)
            if(n%i==0)
                return 0;
        return 1;
    }
    int main()
    {
        inti,sum=0;
        for(i=2;i<100;i++)
            if( isPrime(i))
                sum+=i;
        printf(“%5d”,sum);
        return 0 ;
    }
    intisPrime(int n)
    {
        inti;
        for(i=2;i<=n/2;i++)
        {
            if(n%i==0)
                break;
        }
        if(i>n/2)
            return1;
        else
            return0;
    }
    
    76.单件实例是什么(10分)。
    • Foundation 和 Application Kit 框架中的一些类只允许创建单件对象,即这些类在当前进程中的唯一实 例。
    • 举例来说 ,NSFileManager 和NSWorkspace 类在使用时都是基于进程进行单件对 象的实例化。当向这些类请求实例的时候,它们会向您传递单一实例的一个引用,如果 该实例还不存在,则首先进行实例的分配和初始化。单件对象充当控制中心的角色, 负责指引或协调类的各种服务 。
    • 如果类在概念上只有一个实例(比如
      NSWorkspace),就应该产生一个单件实例,而不是多个实例;如果将来某一天可能有多个实例,您可以使用单件实例机制,而不是工厂方法或函数。

    相关文章

      网友评论

          本文标题:iOS 面试题

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