iOS面试题库(精华版)

这篇博客汇总了iOS面试中常见的问题,涵盖Objective-C的类继承、内存管理、属性特性、线程、内存管理机制、数据库操作、网络通信、UI设计等多个方面。深入探讨了类别的使用、继承与分类的区别、内存管理的三种方式、线程创建方法、KVO和KVC的概念,以及Objective-C的动态运行时特性。此外,还讨论了字符串类型转换、数据结构、线程安全和数据库优化策略。博客旨在帮助iOS开发者全面准备面试,理解并掌握核心知识点。
摘要由CSDN通过智能技术生成

dispatch_async(dispatch_get_main_queue(), ^{ }); dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ });


1.Object-c的类可以多重继承么?可以实现多个接口么?Category是什么?重写一个类的方式用继承好还是分类好?为什么?
Object-c的类不可以多重继承;可以实现多个接口,通过实现多个接口可以完成C++的多重继承;Category是类别,一般情况用分类好,用Category去重写类的方法,仅对本Category有效,不会影响到其他类与原有类的关系。


2.#import 跟#include 有什么区别,@class呢, #import<> 跟 #import””有什么区别?
#import是Objective-C导入头文件的关键字,#include是C/C++导入头文件的关键字,使用#import头文件会自动只导入一次,不会重复导入,相当于#include和#pragma once;@class告诉编译器某个类的声明,当执行时,才去查看类的实现文件,可以解决头文件的相互包含;#import<>用来包含系统的头文件,#import””用来包含用户头文件。


3.属性readwrite,readonly,assign,retain,copy,nonatomic 各是什么作用,在那种情况下用?
①. readwrite 是可读可写特性;需要生成getter方法和setter方法时
②. readonly 是只读特性 只会生成getter方法 不会生成setter方法 ;不希望属性在类外改变
③. assign 是赋值特性,setter方法将传入参数赋值给实例变量;仅设置变量时;
④. retain 表示持有特性,setter方法将传入参数先保留,再赋值,传入参数的retaincount会+1;
⑤. copy 表示赋值特性,setter方法将传入对象复制一份;需要完全一份新的变量时。
⑥. nonatomic 非原子操作,决定编译器生成的setter getter是否是原子操作,atomic表示多线程安全,一般使用nonatomic


4.写一个setter方法用于完成@property (nonatomic,retain)NSString *name,写一个setter方法用于完成@property(nonatomic,copy)NSString *name
- (void) setName:(NSString*) str
{
  [str retain];
  [name release];
  name = str;
}
- (void)setName:(NSString *)str
{
  id t = [str copy];
  [name release];
  name = t;
}


5.对于语句NSString*obj = [[NSData alloc] init]; obj在编译时和运行时分别时什么类型的对象?
编译时是NSString的类型;运行时是NSData类型的对象


6.常见的objective-c的数据类型有那些, 和C的基本数据类型有什么区别?如:NSInteger和int
object-c的数据类型有NSString,NSNumber,NSArray,NSMutableArray,NSData等等,这些都是class,创建后便是对象,而C语言的基本数据类型int,只是一定字节的内存空间,用于存放数值;NSInteger是基本数据类型,并不是NSNumber的子类,当然也不是NSObject的子类。NSInteger是基本数据类型Int或者Long的别名(NSInteger的定义typedef long NSInteger),它的区别在于,NSInteger会根据系统是32位还是64位来决定是本身是int还是Long。


7.id 声明的对象有什么特性?
id 声明的对象具有运行时的特性,即可以指向任意类型的objcetive-c的对象;

8.Objective-C如何对内存管理的,说说你的看法和解决方法?
Objective-C的内存管理主要有三种方式ARC(自动内存计数)、手动内存计数、内存池。
①.自动内存计数:这种方式和java类似,在你的程序的执行过程中。始终有一个高人在背后准确地帮你收拾垃圾,你不用考虑它什么时候开始工作,怎样工作。你只需要明白,我申请了一段内存空间,当我不再使用从而这段内存成为垃圾的时候,我就彻底的把它忘记掉,反正那个高人会帮我收拾垃圾。遗憾的是,那个高人需要消耗一定的资源,在携带的移动设备里面,资源是紧俏商品所以iPhone不支持这个功能。
解决: 通过alloc – init方式创建的, 创建后引用计数+1, 此后每retain一次引用计数+1, 那么在程序中做相应次数的release就好了.
②. (Reference Counted)手动内存计数:就是说,从一段内存被申请之后,就存在一个变量用于保存这段内存被使用的次数,我们暂时把它称为计数器,当计数器变为0的时候,那么就是释放这段内存的时候。比如说,当在程序A里面一段内存被成功申请完成之后,那么这个计数器就从0变成1(我们把这个过程叫做alloc),然后程序B也需要使用这个内存,那么计数器就从1变成了2(我们把这个过程叫做retain)。紧接着程序A不再需要这段内存了,那么程序A就把这个计数器减1(我们把这个过程叫做release);程序B也不再需要这段内存的时候,那么也把计数器减1(这个过程还是release)。当系统(也就是Foundation)发现这个计数器变成了0,那么就会调用内存回收程序把这段内存回收(我们把这个过程叫做dealloc)。顺便提一句,如果没有Foundation,那么维护计数器,释放内存等等工作需要你手工来完成。
解决:一般是由类的静态方法创建的, 函数名中不会出现alloc或init字样, 如[NSString string]和[NSArray arrayWithObject:], 创建后引用计数+0, 在函数出栈后释放, 即相当于一个栈上的局部变量. 当然也可以通过retain延长对象的生存期.
③. (NSAutoRealeasePool)内存池:可以通过创建和释放内存池控制内存申请和回收的时机.
解决:是由autorelease加入系统内存池, 内存池是可以嵌套的, 每个内存池都需要有一个创建释放对, 就像main函数中写的一样. 使用也很简单, 比如[[[NSString alloc]initialWithFormat:@”Hey you!”] autorelease], 即将一个NSString对象加入到最内层的系统内存池, 当我们释放这个内存池时, 其中的对象都会被释放.


9. 原子(atomic)跟非原子(non-atomic)属性有什么区别?
①. atomic提供多线程安全。是防止在写未完成的时候被另外一个线程读取,造成数据错误
②. non-atomic:在自己管理内存的环境中,解析的访问器保留并自动释放返回的值,如果指定了 nonatomic ,那么访问器只是简单地返回这个值。


10.Object C中创建线程的方法是什么?如果在主线程中执行代码,方法是什么?如果想延时执行代码、方法又是什么?
线程创建有三种方法:使用NSThread创建、使用GCD的dispatch、使用子类化的NSOperation,然后将其加入NSOperationQueue;在主线程执行代码,方法是performSelectorOnMainThread,如果想延时执行代码可以用performSelector:onThread:withObject:waitUntilDone:


11. 浅复制和深复制的区别?
答案:浅层复制:只复制指向对象的指针,而不复制引用对象本身。
深层复制:复制引用对象本身。
意思就是说我有个A对象,复制一份后得到A_copy对象后,对于浅复制来说,A和A_copy指向的是同一个内存资源,复制的只不过是是一个指针,对象本身资源
还是只有一份,那如果我们对A_copy执行了修改操作,那么发现A引用的对象同样被修改,这其实违背了我们复制拷贝的一个思想。深复制就好理解了,内存中存在了
两份独立对象本身。
用网上一哥们通俗的话将就是:
浅复制好比你和你的影子,你完蛋,你的影子也完蛋
深复制好比你和你的克隆人,你完蛋,你的克隆人还活着。


12.类别的作用?继承和类别在实现中有何区别?
category 可以在不获悉,不改变原来代码的情况下往里面添加新的方法,只能添加,不能删除修改。
并且如果类别和原来类中的方法产生名称冲突,则类别将覆盖原来的方法,因为类别具有更高的优先级。
类别主要有3个作用:
  (1)将类的实现分散到多个不同文件或多个不同框架中。
  (2)创建对私有方法的前向引用。
  (3)向对象添加非正式协议。
继承可以增加,修改或者删除方法,并且可以增加属性。


13. 类别和类扩展的区别。
category和extensions的不同在于 后者可以添加属性。另外后者添加的方法是必须要实现的。extensions可以认为是一个私有的Category。


14. 什么是KVO和KVC?
kvc:键 – 值编码是一种间接访问对象的属性使用字符串来标识属性,而不是通过调用存取方法,直接或通过实例变量访问的机制。
很多情况下可以简化程序代码。apple文档其实给了一个很好的例子。
kvo:键值观察机制,他提供了观察某一属性变化的方法,极大的简化了代码。
具体用看到嗯哼用到过的一个地方是对于按钮点击变化状态的的监控。
比如我自定义的一个button
[self addObserver:self forKeyPath:@"highlighted" options:0 context:nil];
  #pragma mark KVO
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
 {
  if ([keyPath isEqualToString:@"highlighted"] ) {
  [self setNeedsDisplay];
  }
 }

对于系统是根据keypath去取的到相应的值发生改变,理论上来说是和kvc机制的道理是一样的。
对于kvc机制如何通过key寻找到value:
“当通过KVC调用对象时,比如:[self valueForKey:@”someKey”]时,程序会自动试图通过几种不同的方式解析这个调用。首先查找对象是否带有 someKey 这个方法,如果没找到,会继续查找对象是否带有someKey这个实例变量(iVar),如果还没有找到,程序会继续试图调用 -(id) valueForUndefinedKey:这个方法。如果这个方法还是没有被实现的话,程序会抛出一个NSUndefinedKeyException异常错误。(cocoachina.com注:Key-Value Coding查找方法的时候,不仅仅会查找someKey这个方法,还会查找getsomeKey这个方法,前面加一个get,或者_someKey以及_getsomeKey这几种形式。同时,查找实例变量的时候也会不仅仅查找someKey这个变量,也会查找_someKey这个变量是否存在。)设计valueForUndefinedKey:方法的主要目的是当你使用-(id)valueForKey方法从对象中请求值时,对象能够在错误发生前,有最后的机会响应这个请求。这样做有很多好处,下面的两个例子说明了这样做的好处。“来至cocoa,这个说法应该挺有道理。因为我们知道button却是存在一个highlighted实例变量.因此为何上面我们只是add一个相关的keypath就行了,可以按照kvc查找的逻辑理解,就说的过去了。


15. 我们说的OC是动态运行时语言是什么意思?
多态。 主要是将数据类型的确定由编译时,推迟到了运行时。
这个问题其实浅涉及到两个概念,运行时和多态。
简单来说,运行时机制使我们直到运行时才去决定一个对象的类别,以及调用该类别对象指定方法。
多态:不同对象以自己的方式响应相同的消息的能力叫做多态。意思就是假设生物类(life)都用有一个相同的方法-eat;
那人类属于生物,猪也属于生物,都继承了life后,实现各自的eat,但是调用是我们只需调用各自的eat方法。
也就是不同的对象以自己的方式响应了相同的消息(响应了eat这个选择器)。因此也可以说,运行时机制是多态的基础。


16.自己写函数,实现strlen功能(C语言第四讲 一维数组与字符数组)

注意:判断的时候使用“\0”

#include <stdio.h>
#include <string.h>
int mystrlen(char *a)
{
 int n=0;
while(*a++!='\0')
  n++;
 return n;

}

void main()
{
 int m;
 char a[100];
 printf("please input a string!\n");
    
 gets(a);
 printf("%d",strlen(a));
 m=mystrlen(a);
 printf("%d",m);

}

17.用变量a写出以下定义

a、一个整型数   int a;

b、一个指向整型数的指针 int *a;

c、一个指向指针的指针,它指向的指针是指向一个整型数  int **a;

d、一个有10个整型数的数组  int a[10];

e、一个有10个指针的数组,该指针是指向一个整型数的  int *a[10];

f、一个指向有10个整型数数组的指针  int (*a)[10];

g、一个指向函数的指针,该函数有一个整型参数,并返回一个整型数 int(*a)(int);


18.类变量的@protected ,@private,@public,@package,声明各有什么含义?(OC第二讲  实例变量可见度与方法)
上面的几个声明表明的时类成员的作用域,@private作用范围只能在自身类(外界既不可访问,又不能继承);@protected作用范围在自身类和子类,如果什么都不加修饰,默认是@protected(外界不可访问,但是可以继承);@public作用范围最大,可以在任何地方被访问(外界即可访问,又可以继承);@package作用范围在某个框架内


19.用Object-C写一个冒泡排序

NSMutableArray *array = [NSMutableArray arrayWithArray:@[@"3",@"1",@"10",@"5",@"2",@"7",@"12",@"4",@"8"]];

    NSString  *tmp;

    for (int i = 0; i < array.count; i ++) {

        for (int j = 0; j < array.count  - 1 - i; j++) {

            if ([[array objectAtIndex:j] integerValue] > [[array objectAtIndex:j + 1] integerValue]) {

                tmp = [array objectAtIndex:j];

                [array replaceObjectAtIndex:j withObject:[array objectAtIndex:j + 1]];

                [array replaceObjectAtIndex:j + 1 withObject:tmp];

            }

        }

    }


20.简述OC中内存管理机制。与retain配对使用的方法是dealloc还是release,为什么?需要与alloc配对使用的方法是dealloc还是release,为什么?readwrite,readonly,assign,retain,copy,nonatomic 、atomic、strong、weak属性的作用? (OC第九讲 内存管理初级)
OC使用了一种叫做引用计数的机制来管理对象,如果对一个对象使用了alloc、[Mutable]copy,retain,那么你必须使用相应的realease或者autorelease。也可以理解为自己生成的对象,自己持有。非自己生成的对象,自己也能持有。不在需要自己持有的对象时释放。非自己持有的对象无法释放。生成并持有对象<alloc,new,copy,mutableCopy等>,持有对象<retain>,释放对象<release>,废弃对象<dealloc>。readwrite(默认):可读可写,表示既有getter方法,也有setter方法。readonly:表示只有getter方法,没有setter方法。nonatomic:不考虑线程安全。atomic(默认):线程操作安全。strong(默认):ARC下和MRC下retain一样,weak(ARC下):和(MRC下)assign类似,区别是当weak指向的内存释放掉后自动置为nil,防止野指针。

unsafe_unretained声明一个若引用,但不会自动置为nil,可能会出现野指针。

线程安全下的setter和getter方法:

-(NSString *)value{

@synchronized(self){

return [[_value retain] autorelease];

}

}

- (void)setValue:(NSString *)aValue{

@synchronized(self){

[aValue retain];

[_value release];

_value = aValue;

}

}



21. 简述应用程序按Home键进入后台时的生命周期,以及从后台回到前台时的生命周期?
应用程序的状态:
Not running:未运行,程序没启动
Inactive   :未激活,程序在前台运行,不过没接受到事件,没有事件处理的状态下通常处于这个状态。
Active         :激活   程序在前台并且接收到了事件
Backgound :后台   程序在后台而且能执行代码,大多数程序进入这个状态后会在在这个状态上停留一会。
Suspended :挂起  程序在后台不能执行代码。
- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    //告诉代理进程启动但还没进入状态保存
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
  // 告诉代

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值