IOS面试

(一)
1.简述你对协议的理解:

a想做一件事却因为一些原因不能做,于是让b遵循a的一些约定,这样b就可以帮助a做事了。协议中包括了遵循方b需要实现的一些方法,以及b能够做的事情。

2.如何理解ARC自动引用计数机制:

ARC--自动引用计数 可以用来管理对象的使用以及了解对象的使用情况,当对象引用计数不为0时,对象不会被释放,当对象引用计数为0时 dealloc函数被调用 对象将会被释放。

3.如何理解retain/copy/assign/release/autorelease/dealloc关键字:

retain让对象引用计数加1,release让对象引用计数减1,当对象引用计数为0时会调用dealloc 将对象进行释放。copy是你不想让a和b共享一块内存时候,让a和b有各自的内存。在使用基本数据类型的时候需要使用assgin,assgin是直接赋值,会引起对象引用计数加1.

(1)assign:普通赋值,一般用于基本数据类型,防止循环引用。
(2)retain:保留计数,获得用户的所有权。
(3)copy:用来赋值对象,一般字符串使用copy,Foundation中的不可变对象使用copy效果相当于retain,只是引用计数+1.
(4)nonatomic:非原子性访问,不加同步,多线程并发访问会提高性能。

4.请简述类别和继承有什么联系和区别 以及weak和assgin的区别:

类别和继承 都会使用父类的中原有的方法和属性,类别是对父类进行扩展,继承是将父类中的属性、方法等保留下来,根据自己的实际情况进行实现。 weak用于各种UI控件和代理,assgin用于基本数据类型。

继承可以增加,修改,删除方法,还可以增加属性;

category只能添加属性;

strong:
@property (nonatomic, strong) NSString *string1;   
@property (nonatomic, strong) NSString *string2;
self.string1 = @"String 1";   
self.string2 = self.string1;   
self.string1 = nil;  
NSLog(@"String 2 = %@", self.string2);  
 结果是:String 2 = String 1由于string2是strong定义的属性,所以引用计数+1,使得它们所指向的值都是@"String 1"
weak:
@property (nonatomic, strong) NSString *string1;   
@property (nonatomic, weak) NSString *string2; 
 self.string1 = @"String 1";   
self.string2 = self.string1;   
self.string1 = nil;  
NSLog(@"String 2 = %@", self.string2);  
结果是:String 2 = null
 分析一下,由于self.string1与self.string2指向同一地址,且string2没有retain内存地址,而self.string1=nil释放了内存,所以string1为nil。声明为weak的指针,指针指向的地址一旦被释放,这些指针都将被赋值为nil。这样的好处能有效的防止野指针。

5.请简述你对strong和weak关键字的理解 以及_unsafe_unretained与weak的区别:

strong相当于retain 让对象引用计数加1,防止对象在异常情况下被提前释放,导致crash。weak 弱引用防止产生循环应用无法释放对象和产生野指针。

strong叫做强引用,在ARC中使用strong告诉编译器帮组我们自动插入retain,weak是普通赋值相当于手动管理内存的assign。
_unsafe_unretained与weak功能一致,区别在于当指向的对象销毁后,weak会将变量重置为nil,防止调用野指针,产生EXC_BAD_ACCESS这类的错误。

6.如何实现ARC和MRC的混合编程:

在targets的build phases选项下Compile Sources下选择要使用arc编译的文件:  在targets的build phases选项下Compile Sources下选择要不使用arc编译的文件, 就会出报错。方法如下,双击它 输入 -fno-objc-arc 即可。
如果在ARC 工程中 加MRC 加 -fno-objc-arc 如果在MRC 工程中 加 ARC 加 -fobjc-arc

7.Objective-C是否支持多继承:

不支持多继承 因为消息机制名字查找发生在运行时而非编译时,很难解决多个基类可能导致的二义性问题 。可以通过消息转发 协议 类别实现与多继承相似的功能。

8.Objective-C中变量默认是私有的么?方法默认是私有的么?

变量默认是private,方法默认是public。

9.#import"".h 和@class+类名的区别:

import"".h为导入头文件,@class+类名 为前向引用申明。

1.import会包含这个类的所有信息,包括实体变量和方法,而@class只是告诉编译器,其后面声明的名称是类的名称,至于这些类是如何定义的,暂时不用考虑,后面会再告诉你。
2.在头文件中, 一般只需要知道被引用的类的名称就可以了。 不需要知道其内部的实体变量和方法,所以在头文件中一般使用@class来声明这个名称是类的名称。 而在实现类里面,因为会用到这个引用类的内部的实体变量和方法,所以需要使用#import来包含这个被引用类的头文件。
3.在编译效率方面考虑,如果你有100个头文件都#import了同一个头文件,或者这些文件是依次引用的,如A–>B, B–>C, C–>D这样的引用关系。当最开始的那个头文件有变化的话,后面所有引用它的类都需要重新编译,如果你的类有很多的话,这将耗费大量的时间。而是用@class则不会。
4.如果有循环依赖关系,如:A–>B, B–>A这样的相互依赖关系,如果使用#import来相互包含,那么就会出现编译错误,如果使用@class在两个类的头文件中相互声明,则不会有编译错误出现。
所以,一般来说,@class是放在interface中的,只是为了在interface中引用这个类,把这个类作为一个类型来用的。 在实现这个接口的实现类中,如果需要引用这个类的实体变量或者方法之类的,还是需要import在@class中声明的类进来.

10.请简述页面传值都有哪些实现方法:

Block、 委托协议、 通知、 单例、NSUserDefaults

11.请简述深拷贝和浅拷贝的区别:

深拷贝会重新在堆上开辟一块内存空间 是一个全新的对象 指针地址和原来不一样 浅拷贝不会重新开辟一块内存空间 指针和原来是一样的。
深拷贝和浅拷贝的本质是地址相同,就是浅拷贝,地址不同就是深拷贝。
浅拷贝是拷贝操作后,并没有进行真正的复制,而是另一个指针也指向了同一个地址。深拷贝操作后,是真正的复制了一份,另一个指针指向了拷贝后的地址。

浅拷贝:在复制操作时,对于被复制的对象的每一层复制都是指针复制。
深拷贝:在复制操作时,对于被复制的对象至少有一层复制是对象复制。 完全复制:在复制操作时,对于被复制的对象的每一层复制都是对象复制。

浅拷贝好比你的影子,你没了,你的影子也没有了;

深拷贝好比你的克隆人,你没了,你的克隆人还在 ;

备注:
retain:始终是浅复制。引用计数每次加一。返回对象是否可变与被复制的对象保持一致。
copy:对于可变对象为深复制,引用计数不改变;对于不可变对象是浅复制,引用计数每次加一。始终返回一个不可变对象。
mutableCopy:始终是深复制,引用计数不改变。始终返回一个可变对象。
不可变对象:值发生改变,其内存首地址随之改变。
可变对象:无论值是否改变,其内存首地址都不随之改变。
引用计数:为了让使用者清楚的知道,该对象有多少个拥有者(即有多少个指针指向同一内存地址)。

12.系统中有哪些对象是单例:

NSTimer、NSNotification、UIWindow、UIApplication
自己写单例需要注意:
不使用GCD:

 // 单例模式实现要点:
// 1. 废掉构造方法(调用的时候抛出异常)
// 2. 提供一个类方法向外界返回该类的唯一实例
- (instancetype)init {
    @throw [NSException exceptionWithName:@"CDSingleton" reason:@"不允许调用构造方法" userInfo:nil];
    // return nil;
}
// 此方法由于没有在.h文件中暴露接口相当于是私有方法
- (instancetype) initPrivate {
    if(self = [super init]) {
        _value = arc4random();
    }
    return self;
}
+ (instancetype) sharedInstance {
    // static类型的变量拥有全局的生命周期
    static CDSingleton *instance = nil;
    // 使用同步块保证在多线程环境下仍然是单例
    //同步加锁,在多线程中使用,可以使线程安全
    @synchronized(self) {
        if(!instance) {
            instance = [[self alloc] initPrivate];
        }
    }
    return instance;
}

使用GCD:

+(instancetype)sharedInstance{
    static HCDSingleton *singleton = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        singleton = [[HCDSingleton alloc]init];
    });
    return singleton;
}

13.简述你对MVC设计模式的理解:

MVC : Model - View - Controller 模型负责数据任务 试图负责呈现 以及和用于进行交互 控制器用来控制试图

model 模型:主要负责存储和操作数据
view 视图:主要负责展⽰示数据和⽤用户交互
controller 主要负责将model和view联系起来:
从网络获取数据->赋值给数据模型->将model的数据传递给view展⽰示(响应view的delegate和datasource⽅方法)->刷新view

14.IOS中那些技术符合观察者模式:

Key-Value Observing,它提供一种机制,当指定的对象的属性被修改后,则对象就会接受到通知。每次指定的被观察的对象的属性被修改后,KVO自动通知相应的观察者。

model中定义:
@interface StockData : NSObject { NSString * stockName; float price;}
@end
@implementation StockData
@end
controller中使用,这里相当于跟模型说,我要收听你的更新广播
- (void)viewDidLoad{
 [super viewDidLoad]; 
stockForKVO = [[StockData alloc] init];
 [stockForKVO setValue:@"searph" forKey:@"stockName"]; 
[stockForKVO setValue:@"10.0" forKey:@"price"]; 
[stockForKVO addObserver:self forKeyPath:@"price" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:NULL];
 myLabel = [[UILabel alloc]initWithFrame:CGRectMake(100, 100, 100, 30 )];
 myLabel.textColor = [UIColor redColor];
 myLabel.text = [stockForKVO valueForKey:@"price"]; 
[self.view addSubview:myLabel]; 
UIButton * b = [UIButton buttonWithType:UIButtonTypeRoundedRect];
 b.frame = CGRectMake(0, 0, 100, 30); 
[b addTarget:self action:@selector(buttonAction) forControlEvents:UIControlEventTouchUpInside];
 [self.view addSubview:b];
}
用户单击View中的button调用控制器中的action去更改模型中的数据
-(void) buttonAction{
 [stockForKVO setValue:@"20.0" forKey:@"price"];
}
控制器需要实现的回调,相当于收到广播后我应该做啥事
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{ 
    if([keyPath isEqualToString:@"price"])
     {
       myLabel.text = [stockForKVO valueForKey:@"price"];
     }
}
注意使用通知和KVO一定要记着移除,否则会导致crash
视图dealloc需要取消观察
- (void)dealloc{
 [super dealloc];
 [stockForKVO removeObserver:self forKeyPath:@"price"]; [stockForKVO release];
}

15.简述你对工厂方法的理解:

创建对象的时候,我们一般是alloc一个对象,如果需要创建100个这样的对象,如果是在一个for循环中还好说,直接一句alloc就行了,但是事实并不那么如意,我们可能会在不同的地方去创建这个对象,那么我们可能需要写100句alloc 了,但是如果我们在创建对象的时候,需要在这些对象创建完之后,为它的一个属性添加一个固定的值,比方说都是某某学校的学生,那么可能有需要多些100行重复的代码了,那么,如果写一个-(void)createObj方法,把创建对象和学校属性写在这个方法里边,那么就是会省事很多,也就是说我们可以alloc 创建对象封装到一个方法里边,直接调用这个方法就可以了,这就是简单工厂方法。

16.什么是代理模式,实现代理需要注意什么:

代理模式:帮助别人完成别人委托你完成的事情。你需要注意遵守别人给你定的约定,和你是否拥有完成这件事的能力。

17.简述StoryBoard和Xib的联系和区别:

StoryBoard可以在上面实现整个项目界面的搭建,可以清楚得看到各个试图控制器之间的关系,XIB实现自定义要素和良好部件重用性复杂的UI。

18.请简述UITableView对CELL的重用机制:

比如一个屏幕可以放下5个UITableViewCell  总共会创建6个  设置CELL的重用标志符  一旦可以重用就重用  不能重用再创建,减少内存的消耗。
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    static NSString *cellIdentifier = @"healthNewsTableViewCell";
    healthNewsTableViewCell *cell = [myTableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
    if (!cell) {
        cell = (healthNewsTableViewCell*)[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier: @"healthNewsTableViewCell"];
    }
    return cell;
}
//再将数据绑定写在WillDisPlayCell中
//让UITableView稍微顺滑点的方法  在显示cell前被调用
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{
    healthNewsTableViewCell *MyCell = (healthNewsTableViewCell *)cell;
    MyCell.model = dataArray[indexPath.row];
    MyCell.backgroundColor = [UIColor colorWithRed:0.936 green:0.941 blue:0.936 alpha:1.000];
    
}

19.如何使用UIScrollView实现无限加载多张图片:

写一个NSTimer 每隔0.5秒 执行以下回调方法changPic 如果图片数量有限 进行一个if判断 当超过图片总数时候,显示第一张,重新开始从第一张显示。

20.请简述试图控制器的生命周期:

当一个视图控制器被创建,并在屏幕上显示的时候。 代码的执行顺序

1、 alloc 创建对象,分配空间
2、init (initWithNibName) 初始化对象,初始化数据
3、loadView 从nib载入视图 ,通常这一步不需要去干涉。除非你没有使用xib文件创建视图
4、viewDidLoad 载入完成,可以进行自定义数据以及动态创建其他控件
5、viewWillAppear 视图将出现在屏幕之前,马上这个视图就会被展现在屏幕上了
6、viewDidAppear 视图已在屏幕上渲染完成

当一个视图被移除屏幕并且销毁的时候的执行顺序,这个顺序差不多和上面的相反

1、viewWillDisappear 视图将被从屏幕上移除之前执行
2、viewDidDisappear 视图已经被从屏幕上移除,用户看不到这个视图了
3、dealloc 视图被销毁,此处需要对你在init和viewDidLoad中创建的对象进行释放

21.UITableView有哪些优化方式:

1.图片使用异步加载如SDWebImage。
2.使用重用标识符reuseIdentifier,将重用标识标示符static NSString *CellIdentifier = @"XXX";
3.将数据绑定写在WillDisPlay这个协议方法中。
4.尽量在CELL中少使用不透明的View。
5.如果不是必须,减少使用reloadData全部cell。

22.简述IOS中的事件传递机制:

举例:如果view是控制器的view,就传递给控制器;如不是,则将其传递给它的父视图 在视图层次结构的最顶级视图,如果也不能处理收到的事件或消息,则其将事件或消息传递给window对象进行处理 如果window对象也不处理,则其将事件或消息传递给UIApplication对象 如果UIApplication也不能处理该事件或消息,则将其丢弃

注意:为什么用队列管理事件,而不用栈?

队列先进先出,能保证先产生的事件先处理。栈先进后出。

23.UITableView有哪些必须要实现的数据源方法:

// 获得section包含的cell个数
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section; 
//创建UITableViewCell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
//看情况实现的数据源方法:
//TableView中分组数目
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView; 
//分组头的标题
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section;   
//分组尾的标题
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section;
个人习惯在此方法中实现给模型绑定数据
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath

24.简述Http协议中get请求和post请求的区别:

get 是从服务器获取数据 ,post是向服务器发送数据

GET安全性较低,POST安全性较高。因为GET在传输过程,数据被放在请求的URL中,而如今现有的很多服务器、代理服务器或者用户代理都会将请求URL记录到日志文件中,然后放在某个地方,这样就可能会有一些隐私的信息被第三方看到。另外,用户也可以在浏览器上直接看到提交的数据,一些系统内部消息将会一同显示在用户面前。POST的所有操作对用户来说都是不可见的。

备注:

GET请求,将参数直接写在访问路径上。操作简单,不过容易被外界看到,安全性不高,地址最多255字节;
POST请求,将参数放到body里面。POST请求操作相对复杂,需要将参数和地址分开,不过安全性高,参数放在body里面,不易被捕获。

25.简述你对异步请求数据的理解:

直白点 更好的用户体验: 减少卡顿 假死的现象。因为异步请求数据 不会一直等待某个任务完成才执行另外一个任务,可以执行其他的操作。

26.IOS中有哪些技术可以实现开辟线程,他们之间有什么联系:
由一个单例方法的实现推出多线程使用:

第一种,使用@synchronized(self)
static LocationController *sharedInstance;
+ (LocationController *)sharedInstance {
     @synchronized(self)//使用一个同步保护 保证一个线程使用时,其他线程无法进入。  
 {
     if (!sharedInstance)
     sharedInstance=[[LocationController alloc] init];
 }
 return sharedInstance;
}
第二种,使用GCD(Grand Central Dispatch:宏中心派发)
当你调用dispatch_async,你通过一个dispatch队列,在这个队列上存有很多block,先进先出,依次执行。
这个队列可以使用dispatch_create自己创建,也可以调用主线程队列dispatch_get_main_queue。
这里建立的队列名称是onceToken。
static LocationController *sharedInstance;
+ (LocationController *)sharedInstance {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if (!sharedInstance)
            sharedInstance = [[self alloc] init];
    });
    return sharedInstance;
   }
第三种,使用NSOperationQueue
static LocationController *sharedInstance;
+ (LocationController *)sharedInstance {
    NSOperationQueue *onceToken=[[NSOperationQueue alloc] init];
    [onceToken addOperationWithBlock:^(){
      if (!sharedInstance)
            sharedInstance = [[self alloc] init];
    });
    return sharedInstance; 
    }];
    }

正式列举实现单例的常用的3种方法:

  • NSThread:

创建方式主要有两种:

//下面为两种NSThread的创建方法:
[NSThread detachNewThreadSelector:@selector(myThreadMainMethod:) toTarget:self withObject:nil];
NSThread* myThread = [[NSThread alloc] initWithTarget:selfselector:@selector(myThreadMainMethod:)object:nil];
[myThread start]; //启动线程

这两种方式的区别是:前一种一调用就会立即创建一个线程来做事情;而后一种虽然你 alloc 了也 init了,但是要直到我们手动调用 start 启动线程时才会真正去创建线程。这种延迟实现思想在很多跟资源相关的地方都有用到。后一种方式我们还可以在启动线程之前,对线程进行配置,比如设置 stack 大小,线程优先级。此外还有一种间接的方式:利用NSObject的方法performSelectorInBackground:withObject: 来创建一个线程:

[myObj performSelectorInBackground:@selector(myThreadMainMethod) withObject:nil];
 //在后台运行某一个方法其效果与 NSThread 的 detachNewThreadSelector:toTarget:withObject: 是一样的。
  • NSOperationQueue (操作队列)

@interface ViewController () {
    // 操作队列
    NSOperationQueue *queue;
}
@end
@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    // 并发队列(队列中的操作会并发执行)
    queue = [[NSOperationQueue alloc] init];
    queue.maxConcurrentOperationCount = 5;
 for (int i = 0; i < 5; i++) {
        CDCar *myCar = [[CDCar alloc] initWithX:20 + 70 * i andY:10];
        [myCar draw:self.view];
          NSOperation *op = [NSBlockOperation blockOperationWithBlock:^{
            [myCar run];
        }];
        [queue addOperation:op];
    }
}
@end
  • GCD

dispatch_async(dispatch_get_global_queue(0, 0), ^{     
// 耗时的操作   比如网络数据数据请求
});  
dispatch_async(dispatch_get_main_queue(), ^{         
// 更新界面      
 }); 

27.NSThread中线程是如何实现通信的:
28.GCD中有哪些创建线程的方式:

dispatch_async(dispatch_get_global_queue(0, 0), ^{     
// 耗时的操作   比如网络数据数据请求
});  
dispatch_async(dispatch_get_main_queue(), ^{         
// 更新界面      
 }); 

29.IOS中哪些技术可以保证线程的安全:

1.使用互斥锁 互斥锁使用格式

@synchronized(锁对象)
 { 
// 需要锁定的代码 
 }
注意:锁定1份代码只用1把锁,用多把锁是无效的
  • 互斥锁的优缺点
    优点:能有效防止因多线程抢夺资源造成的数据安全问题
    缺点:需要消耗大量的CPU资源
    互斥锁的使用前提:多条线程抢夺同一块资源
    相关专业术语:线程同步,多条线程按顺序地执行任务
    互斥锁,就是使用了线程同步技术

OC在定义属性时有nonatomic和atomic两种选择
atomic:原子属性,为setter方法加锁(默认就是atomic)
nonatomic:非原子属性,不会为setter方法加锁

@property (assign, atomic) int age;
 - (void)setAge:(int)age;
 {  
     @synchronized(self)
      { 
          _age = age;  
      }
 }
  • 原子和非原子属性的选择
    nonatomic和atomic对比
    atomic:线程安全,需要消耗大量的资源
    nonatomic:非线程安全,适合内存小的移动设备

30.ASIHttpRequest的父类是什么:

ASIHTTPRequest是一款极其强劲的HTTP访问开源项目。让简单的API完成复杂的功能,
如:异步请求,队列请求,GZIP压缩,缓存,断点续传,进度跟踪,上传文件,HTTP认证。

它是NSOperationQueues的扩展,小而强大。
但也与它的父类略有区别。
如,仅添加到队列中其实并不能执行请求,只有调用[queue go]才会执行;
一个正在运行中的队列,并不需要重复调用[queue go ]。
默认情况下,队列中的一个请求如果失败,它会取消所有未完成的请求。
可以设置[queue setShouldCancel];

31.简述AFNetWork的实现原理:

AFNetwork是一个轻量级的网络请求api类库。是以NSURLConnection, NSOperation和其他方法为基础的。

  • AFNewWork的基本使用:
    //创建一个下载任务
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
NSURL *URL = [NSURL URLWithString:@"http://example.com/download.zip"];NSURLRequest *request = [NSURLRequest requestWithURL:URL];
NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:nil destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) { 
NSURL *documentsDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil];
 return [documentsDirectoryURL URLByAppendingPathComponent:[response suggestedFilename]];
} completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) {
 NSLog(@"File downloaded to: %@", filePath);
}];
[downloadTask resume];

//创建一个上传任务

NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
NSURL *URL = [NSURL URLWithString:@"http://example.com/upload"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
NSURL *filePath = [NSURL fileURLWithPath:@"file://path/to/image.png"];
NSURLSessionUploadTask *uploadTask = [manager uploadTaskWithRequest:request fromFile:filePath progress:nil completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) { 
if (error) { 
NSLog(@"Error: %@", error);
 } else { 
NSLog(@"Success: %@ %@", response, responseObject); }
}];
[uploadTask resume];

//带进度的上传任务

NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"POST" URLString:@"http://example.com/upload" parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
 [formData appendPartWithFileURL:[NSURL fileURLWithPath:@"file://path/to/image.jpg"] name:@"file" fileName:@"filename.jpg" mimeType:@"image/jpeg" error:nil];
 } error:nil];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
NSURLSessionUploadTask *uploadTask;
uploadTask = [manager uploadTaskWithStreamedRequest:request progress:^(NSProgress * _Nonnull uploadProgress) { 
// This is not called back on the main queue. // You are responsible for dispatching to the main queue for UI updates dispatch_async(dispatch_get_main_queue(), ^{ 
//Update the progress view 
[progressView setProgress:uploadProgress.fractionCompleted]; 
}); } completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) { 
if (error) { 
NSLog(@"Error: %@", error);
 } else {
 NSLog(@"%@ %@", response, responseObject); 
} }];
[uploadTask resume];

//请求数据的任务

NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
NSURL *URL = [NSURL URLWithString:@"http://httpbin.org/get"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
NSURLSessionDataTask *dataTask = [manager dataTaskWithRequest:request completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
 if (error) { 
NSLog(@"Error: %@", error); 
} else { 
NSLog(@"%@ %@", response, responseObject); 
}}];
[dataTask resume];

32.如何理解Block,block有什么用途:

void (^block)() = ^(){};//实质就是保存一段代码
//定义:
typedef void (^Block)();

@property (strong,nonatomic) Block 

Block是没有名字的匿名函数,类似于C语言中的函数指针。



可以用于页面间传值 进行回调...
举例:
//第二个页面:

.h
// 定义Block类型的属性(用来保存一段回调代码)
// 属性修饰符必须写copy因为要从栈将Block拷贝到堆上
@property (nonatomic, copy) void(^myBlock)(NSString *);

.m
- (IBAction)buttonClicked:(id)sender {
   if (_myBlock) {
        // 调用Block 语法跟调用C函数是一致的
        _myBlock([NSString stringWithFormat:@"你好, %@", _nameField.text]);
    }
    [self dismissViewControllerAnimated:YES completion:^{
        NSLog(@"回到第一个视图控制器!!!");
    }];
}

//第一个页面 (接收页面)

.m
- (IBAction)buttonClicked:(UIButton *)sender {
     CDSecondViewController *secondVC = [[CDSecondViewController alloc] init];
    // 给第二个视图控制器的Block变量赋值
    secondVC.myBlock = ^(NSString *str) {
        _myLabel.text = str;
    };
    [self presentViewController:secondVC animated:YES completion:^{
        // NSLog(@"搞定第二个视图控制器!!!");
    }];
}


具体使用block:

#import "ViewController.h"

typedef void (^otherBlock) ();

typedef void(^ResultBlock)(BOOL suc,NSString *plat,NSString *info);

@interface ViewController ()

//属性定义block
@property (nonatomic,copy) void(^someBlock)();
//alias定义block
@property (nonatomic,copy) otherBlock oBlock;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
}

-(void)getDataFromServerWithResult:(otherBlock)oBlock{
    
}

-(void)getData:(ResultBlock)shareBlock{
    
}

- (void)pullDownRefreshWithFinishedCallBack:(void(^)())finishCallBack{
    
}

@end


33.简述TCP和UDP的区别:

TCP传输可靠有保证,它有三次握手机制,这一机制保证校验了数据,保证了他的可靠性。而UDP就没有了,所以不可靠。不过UDP的速度是TCP比不了的,而且UDP的反应速度更快,QQ就是用UDP协议传输的,HTTP是用TCP协议传输的。

34.如何保证定位更省电:

desiredAccuracy,这个属性用来控制定位精度,精度越高耗电量越高,所以应该看实际情况设置这个属性的值。

35.简述SDWebImage的实现原理:

  • SDWebImage加载图片的流程:
1.入口 setImageWithURL:placeholderImage:options: 会先把 placeholderImage 显示,然后 SDWebImageManager 根据 URL 开始处理图片。
2.进入 SDWebImageManager-downloadWithURL:delegate:options:userInfo:,交给 SDImageCache 从缓存查找图片是否已经下载 queryDiskCacheForKey:delegate:userInfo:。
3.先从内存图片缓存查找是否有图片,如果内存中已经有图片缓存,SDImageCacheDelegate 回调 imageCache:didFindImage:forKey:userInfo: 到 SDWebImageManager。
4.SDWebImageManagerDelegate 回调 webImageManager:didFinishWithImage: 到 UIImageView+WebCache 等前端展示图片。
5.如果内存缓存中没有,生成 NSInvocationOperation 添加到队列开始从硬盘查找图片是否已经缓存。
6.根据 URLKey 在硬盘缓存目录下尝试读取图片文件。这一步是在 NSOperation 进行的操作,所以回主线程进行结果回调 notifyDelegate:。
7.如果上一操作从硬盘读取到了图片,将图片添加到内存缓存中(如果空闲内存过小,会先清空内存缓存)。SDImageCacheDelegate 回调 imageCache:didFindImage:forKey:userInfo:。进而回调展示图片。
8.如果从硬盘缓存目录读取不到图片,说明所有缓存都不存在该图片,需要下载图片,回调 imageCache:didNotFindImageForKey:userInfo:。
9.共享或重新生成一个下载器 SDWebImageDownloader 开始下载图片。
10.图片下载由 NSURLConnection 来做,实现相关 delegate 来判断图片下载中、下载完成和下载失败。
11.connection:didReceiveData: 中利用 ImageIO 做了按图片下载进度加载效果。
12.connectionDidFinishLoading: 数据下载完成后交给 SDWebImageDecoder 做图片解码处理。
13.图片解码处理在一个 NSOperationQueue 完成,不会拖慢主线程 UI。如果有需要对下载的图片进行二次处理,最好也在这里完成,效率会好很多。
14.在主线程 notifyDelegateOnMainThreadWithInfo: 宣告解码完成,imageDecoder:didFinishDecodingImage:userInfo: 回调给 SDWebImageDownloader。
15.imageDownloader:didFinishWithImage: 回调给 SDWebImageManager 告知图片下载完成。
16.通知所有的 downloadDelegates 下载完成,回调给需要的地方展示图片。
17.将图片保存到 SDImageCache 中,内存缓存和硬盘缓存同时保存。写文件到硬盘也在以单独 NSInvocationOperation 完成,避免拖慢主线程。
18.SDImageCache 在初始化的时候会注册一些消息通知,在内存警告或退到后台的时候清理内存图片缓存,应用结束的时候清理过期图片。
19.SDWI 也提供了 UIButton+WebCache 和 MKAnnotationView+WebCache,方便使用。
20.SDWebImagePrefetcher 可以预先下载图片,方便后续使用。

36.简述XML和JSON数据各有哪些优势:

(1).可读性方面。JSON和XML的数据可读性基本相同,JSON和XML的可读性可谓不相上下,一边是建议的语法,一边是规范的标签形式,XML可读性较好些。
(2).可扩展性方面。XML天生有很好的扩展性,JSON当然也有,没有什么是XML能扩展,JSON不能的。
(3).编码难度方面。XML有丰富的编码工具,比如Dom4j、JDom等,JSON也有json.org提供的工具,但是JSON的编码明显比XML容易许多,即使不借助工具也能写出JSON的代码,可是要写好XML就不太容易了。
(4).解码难度方面。XML的解析得考虑子节点父节点,让人头昏眼花,而JSON的解析难度几乎为0。这一点XML输的真是没话说。
(5).流行度方面。XML已经被业界广泛的使用,而JSON才刚刚开始,但是在Ajax这个特定的领域,未来的发展一定是XML让位于JSON。到时Ajax应该变成Ajaj(Asynchronous Javascript and JSON)了。
(6).解析手段方面。JSON和XML同样拥有丰富的解析手段。
(7).数据体积方面。JSON相对于XML来讲,数据的体积小,传递的速度更快些。
(8).数据交互方面。JSON与JavaScript的交互更加方便,更容易解析处理,更好的数据交互
(9).数据描述方面。JSON对数据的描述性比XML较差。
(10).传输速度方面。JSON的速度要远远快于XML。

37.简述线程和进程有什么联系和区别:

看到过一篇博客 博客上面,在这里引用博客中对线程和进程的理解:

1.计算机的核心是CPU,它承担了所有的计算任务。它就像一座工厂,时刻在运行。
2.假定工厂的电力有限,一次只能供给一个车间使用。也就是说,一个车间开工的时候,其他车间都必须停工。背后的含义就是,单个CPU一次只能运行一个任务。
3.进程就好比工厂的车间,它代表CPU所能处理的单个任务。任一时刻,CPU总是运行一个进程,其他进程处于非运行状态。
4.一个车间里,可以有很多工人。他们协同完成一个任务。线程就好比车间里的工人。一个进程可以包括多个线程。
5.车间的空间是工人们共享的,比如许多房间是每个工人都可以进出的。这象征一个进程的内存空间是共享的,每个线程都可以使用这些共享内存。
6.可是,每间房间的大小不同,有些房间最多只能容纳一个人,比如厕所。里面有人的时候,其他人就不能进去了。这代表一个线程使用某些共享内存时,其他线程必须等它结束,才能使用这一块内存。
7.一个防止他人进入的简单方法,就是门口加一把锁。先到的人锁上门,后到的人看到上锁,就在门口排队,等锁打开再进去。这就叫"互斥锁"(Mutual exclusion,缩写 Mutex),防止多个线程同时读写某一块内存区域。
8.还有些房间,可以同时容纳n个人,比如厨房。也就是说,如果人数大于n,多出来的人只能在外面等着。这好比某些内存区域,只能供给固定数目的线程使用。
9.这时的解决方法,就是在门口挂n把钥匙。进去的人就取一把钥匙,出来时再把钥匙挂回原处。后到的人发现钥匙架空了,就知道必须在门口排队等着了。这种做法叫做"信号量"(Semaphore),用来保证多个线程不会互相冲突。
不难看出,mutex是semaphore的一种特殊情况(n=1时)。也就是说,完全可以用后者替代前者。但是,因为mutex较为简单,且效率高,所以在必须保证资源独占的情况下,还是采用这种设计。

38.简述NSUserDefaults的使用场景和使用注意事项:

对于NSUerdefaults来说 一般可以用来保存用户的偏好设置 比如登陆账号 密码这些。 除此之外 我们还可以用它来保存图片, 字符串 , 数字 和对象。它被保存到项目中的Plists文件里面里。保存图片 一般用它里面的两个方法 图片保存可以用PNG或者JPG对应的方法 先转换成NSData 再用NSUerdefaults保存 保存的时候为了让它马上存下来要用synchronize 。它还可以用来在程序间进行反向传值。

39.IOS中数据库是用什么技术实现的:

Sqlite 3

40.简述什么是主键 什么是外键:

主键是用来唯一确定一条记录的唯一标记,如身份证号码。外键是用来关联其他表,可以通过这个外键唯一确定另外一张表上面的字段。如:A表中有个字段是B表中的主键,那么这个字段就是A的外键。

41.IOS中如何实现数据模型的存储:
42.简述IOS的沙盒机制:

IOS中的沙盒机制(SandBox)是一种安全体系,它规定了应用程序只能在为该应用创建的文件夹内读取文件,不可以访问其他地方的内容。所有的非代码文件都保存在这个地方,比如图片、声音、属性列表和文本文件等。
1.每个应用程序都在自己的沙盒内
2.不能随意跨越自己的沙盒去访问别的应用程序沙盒的内容
3.应用程序向外请求或接收数据都需要经过权限认证

43.如何实现真机调试:

Xcode7以后可以不用配置开发者证书直接进行真机测试 嘿嘿

44.如何查找项目中的内存泄露:

使用Instruments来查找程序中的内存泄露,以及NSZombieEnabled。

45.项目中支付环节如何实现的:

注意需要配置Apple ID 其他按照微信支付或者支付宝文档进行配置

46.如何实现项目上线到AppStore
47.简述你在项目中遇到过哪些问题:

以前做一个项目时,项目中使用了高德地图,当时时每点击进入一个单元格就进入地图,后来发现点击和退出的速度加快后,程序会crash。后来找了好久,发现 每次创建地图会占用很大的内存,而你每次还没有创建完毕就退出,就会导致崩溃,所以最后把创建地图的那一部分代码转移到了创建单元格哪里(前一个页面中),这样保证每次都只有一个地图。而不会因为地图还没有创建好就退出导致crash。

48.如何实现流媒体格式的视频边播放边缓存:
49.简述self.name = xxx 与_name=xxx的区别:

(1)self.name 有getter 和sett er 方法
(2)self.name 可以被kvo 监听到 (set 方法 和kvc方法)
(3)self.name 考虑了内存管理 是一个对象指针

前者是调用了setter方法,后者是普通的赋值。

50.#include与#import的区别、#import与@class的区别:

(1)#include与#import区别:#include和#import效果相同,只是后者不会引起交叉编译,确保头文件只会被导入一次。
(2)#import和@class的区别:import会导入类的所有信息,包括变量和方法,而@class只是告诉编译器,后面的名称是类的名称。推荐使用#import,编译效率更高,防止相互包含的编译错误。

(二)
1.IOS中是否支持垃圾回收机制:

IOS开发只支持手动内存管理和ARC,Mac开发支持GC垃圾回收机制,10.8之后弃用了GC,推荐使用ARC。

2.用户自定义了一个对象,如何实现拷贝(可变和不可变拷贝)

必须实现copying和mutableCopying协议,表示返回一个不可变和可变的对象。否则程序将会出现异常。

-(id)copyWithZone:(NSZone*)zone{
Person *person = [[self Class] allocWithZone:zone];
person->age = self.age;
person->name = self.name;
return person;
}
-(id)mutableCopyWithZone(NSZone*)zone;

3.释放对象的时候为什么要调用[super dealloc]:

因为子类继承父类,子类中一些对象(实例变量)也是继承父类的,因此我们需要调用父类的方法,将父类所拥有的实例进行释放。

4.简述常见的设计模式:

单例设计、代理设计、观察者(通知)、工厂方法。

5.内存管理中使用release方法好还是使用self.xxx = nil好:

使用self.xxx = nil 好,因为它会先调用release方法,而且将变量设置为nil,这样就可以更安全的释放对象,防止野指针调用。

6.事件响应者链的概念:

响应者链表示一系列的响应者对象。事件被交给第一响应者处理,如果第一响应者不处理,事件会沿着响应者链条向上传递,交给下一个响应者(next responder)。一般来说第一响应者是个视图或者其子类对象,当其被触摸后事件交给它处理,如果不处理,事件就会被传递到它的视图控制器(如果存在),然后是它的父视图(superview)(如果存在),以此类推,直到顶层视图。接下来会沿着顶层视图(top view)到窗口(UIWindow)再到UIApplication。如果整个过程都没有响应这个事件,该事件就会被丢弃。

7.static变量和static函数的区别:

(1)static变量表示静态存储变量,变量存储在静态存储区。
(2)加在函数前面表示该函数是内部连接,只在本文件中有效,别的文件中不能应用该函数。

static 全局变量与普通的全局变量有什么区别:static 全局变量只初使化一次,
防止在其他文件单元中被引用;
static 局部变量和普通局部变量有什么区别:static 局部变量只被初始化一次,
下一次依据上一次结果值;
static 函数与普通函数有什么区别:static 函数在内存中只有一份,普通函数
在每个被调用中维持一份拷贝

8.面向对象的三大支柱 以及如何理解动态绑定(多态):

三大支柱:封装、多态、继承
多态:
继承父类,实现方法,只看对象不看指针,不同的对象实现自己重写的不同的方法。

9.frame与bounds的区别:

(1)Frame:该view是在父view坐标系中的位置和大小(参照点是父视图的坐标系)当view做了transform时,该值不准确。
(2)Bounds:该view是在本身坐标系的位置和大小(参照点是本身的坐标系统)。

10.谈谈对Runloop的理解:

Run loop是线程相关的基础框架的一部分。一个run loop就是一个事件处理的循环,用来不停的调度工作以及处理输入事件。使用run loop的目的就是让你的线程在有工作的时候忙起来,没有工作的时候休眠。

11.SVN、Git协作开发,怎样防止代码文件冲突:

(1)防止代码冲突:不要同时多人修改同一个文件。例如A、B都同时修改一个文件,先让A修改,然后提交到服务器,然后B更新下来,在进行修改。
(2)服务器上的项目文件xcodeproj,仅让一个人管理提交,其他人只更新。防止此文件产生冲突。

12.断点续传如何实现的:

将下载的文件分成几个部分,通过http协议的请求头,设置每一部分下载的偏移量,然后通过多线程下载每一部分,下载完成以后 再组成为最终的完整文件。

13.堆和栈的区别 以及队列和栈的区别:

栈区(stack)由编译器自动分配释放,存放 方法(函数)的参数值、局部变量的值等、堆区(heap)一般由程序员分配和释放、若不释放,则内存溢出。
队列:先进先出 栈:先进后出

14.协议、代理的理解:

实际上是两个对象的相互调用
A类 B类 A中有B的对象 B.delegate=A

15.HTTP协议、TCP、UDP协议

数据请求:状态行、请求头、请求体
服务端响应:响应头(状态码:200;404资源没有找到;400客户端请求语法错误;500服务器错误;)响应体w3c school在线教程

16.IOS 6 与 IOS 7区别:

IOS 6 拟物化风格
IOS 7 扁平化风格

17.什么是指针:

type *p;
type:类数据类型。用来存储内存单元的编号指针 不完全等于 地址!有类型的标识很多类型的指针,指向数据、指向方法、void 型 。不同的编译环境,sizeof 可能不同。

18.写一个宏,输入两个参数返回其中较小的一个:

#define MIN(a,b) ((a)>(b)?(b):(a))

19.排序算法:

选择排序


-(void)bunbleSort:(NSMutableArray *)aData{
int count = 0;
for(int i = 0; i < [aData count]-1;i++)
{
for(int j = i+1; j < [aData count];j++)
{
if([[aData objectAtIndex:i] integerValue] < [[aDataobjectAtIndex:j]integerValue])
{
NSNumber *temp = [aData objectAtIndex:i];
[aData replaceObjectAtIndex:i withObject:[aData
objectAtIndex:j]];
[aData replaceObjectAtIndex:j withObject:temp];
count ++;}
}}
}

冒泡排序


-(void)sort2:(NSMutableArray *)resource{
//NSNumber小 -> 大
int count = [resource count];
for(int i = 0; i < count-1; i ++)
{
for(int j = 0; j < count-i-1; j ++)
{
if([[resource objectAtIndex:j] integerValue]>[[resource objectAtIndex:j+1] integerValue])
{
NSNumber *temp = [resource objectAtIndex:j];
[resource replaceObjectAtIndex:j
withObject:[resource objectAtIndex:j+1]];
[resource replaceObjectAtIndex:j+1
withObject:temp];
}
}}
}

快速排序


-(void)quickSortWithArray:(NSMutableArray *)aDataleft:(NSInteger)left right:(NSInteger)right
{
if (right > left) {NSInteger i = left;
NSInteger j = right + 1;
while (true) {
while (i+1 < [aData count] && [aData objectAtIndex:++i] <[aData objectAtIndex:left]) ;
while (j-1 > -1 && [aData objectAtIndex:--j] > [aDataobjectAtIndex:left]) ;
if (i >= j) 
{
break;
}
[self swapWithData:aData index1:i index2:j];
}
[self swapWithData:aData index1:left index2:j];

[self quickSortWithArray:aData left:left right:j-1];
[self quickSortWithArray:aData left:j+1 right:right];
}
}
-(void)swapWithData:(NSMutableArray *)aDataindex1:(NSInteger)index1 index2:(NSInteger)index2
{
NSNumber *tmp = [aData objectAtIndex:index1];
[aData replaceObjectAtIndex:index1 withObject:[aDataobjectAtIndex:index2]];
[aData replaceObjectAtIndex:index2 withObject:tmp];
}

20.写一个单链表,要求可以插入数据和删除单个数据:


struct QFInfo{
int num;
struct QFInfo *next;
};
struct QFInfo *qfinfo;
//链表头
void insert_AtFirst(struct QFInfo *head,struct QFInfo *insert)
{
insert->next = head->next;
head->next = insert;
}
//链表尾
void insert_AtEnd(struct QFInfo *head,struct QFInfo *insert)
{
struct QFInfo *temp = head->next;
while (temp->next != NULL) {
temp = temp->next;
}
insert->next = NULL;
temp->next = insert;
}
//删除
void delete_1(struct QFInfo *head,struct QFInfo *del)
{
struct QFInfo *temp = head->next;
while (temp->next != NULL && temp->next != del)
 {
temp = temp->next;
}
if(temp->next != NULL)
{
temp->next = temp->next->next;
}
}

21.下面的程序中,3次retainCount分别是什么,为什么:

NSMutableArray *arr = [[NSMutableArray array] retain]; 
NSString *str = [NSString stringWithFormat:@"test"];
 [str retain]; 
[arr addObject:str]; 
NSLog(@"%@%lu",str,[str retainCount]); 
[str retain]; 
[str release]; 
[str release]; 
NSLog(@"%@%lu",str,[str retainCount]);
 [arr removeObject:str];
 NSLog(@"%@%lu",str,[str retainCount]);
分别是3、2、1,因为初始化的时候retain  为1,retain的时候+1,往数组中add的时候+1,release的时候-1,从数组中删除的时候-1。

22.引用和指针的区别:

1 .从现象上看:指针在运行时可以改变其所指向的值,而引用一旦和某个对象绑定后就不再改变。引用访问一个变量是直接访问,而指针是间接访问。
2.从内存分配上看:程序为指针变量分配内存区域,而引用不分配内存区域。
3.从编译上看:程序在编译时分别将指针和引用添加到符号表上,符号表上记录的是变量名及变量所对应地址。指针变量在符号表上对应的地址值为指针变量的地址值,而引用在符号表上对应的地址值为引用对象的地址值。符号表生成后就不会再改,因此指针可以改变指向的对象(指针变量中的值可以改),而引用对象不能改。

23.如何将图片添加到相册:


UIImage *img = [UIImage imageWithNamed:@”123.ppng”];
 UIImageWriteToSavedPhotosAlbum(img, nil, nil, nil);

24.写一个获取日期的方法,输出格式为2016-08-08:


NSDate *date = [NSDate date];
NSDateFormatter *dateFm = [[NSDateFormatter alloc] init];
 dateFm.dateFormat = @"yyyy-MM-dd"; 
NSString *dateStr = [dateFm stringFromDate:date];
NSLog(@"dateStr:%@",dateStr);

25.将一组数据永久保存到手机里:

NSUserDefaults、plist、数据库、普通文件、归档

26.NSarray *array = @[@“a”,@“b”,@“c”,@“a”,@“d”....],里面有N个string元素,求出array中唯一元素,要求复杂度为N:

(分析:将重复的元素去掉拼接成一个字符串)
代码实例:
NSArray *arr = @[@"a",@"b",@"b",@"c"];
NSString *resultStr = [arr objectAtIndex:0];
for (NSString *str in arr) 
{
if ([resultStr rangeOfString:str].location == NSNotFound) {
resultStr = [resultStr stringByAppendingString:str];
}
}
NSLog(@"%@",resultStr);

27.写一个Block使用的例子,尽可能体现出block编程的语法和优势:

void(^myBlock)(NSString *msg);
myBlock = ^(NSString *str){
NSLog(@"%@",str);//line3
}
//使用block
//相当于把line3的代码放在这里执行。
myBlock(@"hello!");

28.nil和NULL有什么区别:

nil是一个对象,NULL是一个值

29.什么时候使用NSMutableArray,什么时候使用NSArray:

当数组在程序运行时,需要不断变化的,使用NSMutableArray,当数组在初始化后,便不再改变的,使用NSArray。需要指出的是,使用NSArray只表明的是该数组在运行时不发生改变,即不能往NSAarry的数组里新增和删除元素,但不表明其数组內的元素的内容不能发生改变。NSArray是线程安全的,NSMutableArray不是线程安全的,多线程使用到NSMutableArray需要注意。

30.如果我们不创建内存池,是否有内存池提供给我们:

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

31.类NSObject的那些方法经常被使用:

NSObject是Objetive-C的基类,其由NSObject类及一系列协议构成。
其中类方法alloc、class、description 对象方法init、dealloc、– performSelector:withObject:afterDelay:等经常被使用。

32.什么是谓词:

谓词是通过NSPredicate,是通过给定的逻辑条件作为约束条件,完成对数据的筛选。
predicate = [NSPredicate predicateWithFormat:@"customerID == %d",n];
a = [customers filteredArrayUsingPredicate:predicate];

33.简述内存分区情况:

1).代码区:存放函数二进制代码
2).数据区:系统运行时申请内存并初始化,系统退出时由系统释放。存放全局变量、静态变量、常量
3).堆区:通过malloc等函数或new等操作符动态申请得到,需程序员手动申请和释放
4).栈区:函数模块内申请,函数结束时由系统自动释放。存放局部变量、函数参数

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,802评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,109评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,683评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,458评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,452评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,505评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,901评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,550评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,763评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,556评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,629评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,330评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,898评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,897评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,140评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,807评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,339评论 2 342

推荐阅读更多精彩内容

  • *面试心声:其实这些题本人都没怎么背,但是在上海 两周半 面了大约10家 收到差不多3个offer,总结起来就是把...
    Dove_iOS阅读 27,118评论 29 470
  • C 部分 1.static 关键字的作用? 第一个作用:隐藏。 当我们同时编译多个文件时,所有未加static前缀...
    pingui阅读 4,347评论 2 48
  • 多线程、特别是NSOperation 和 GCD 的内部原理。运行时机制的原理和运用场景。SDWebImage的原...
    LZM轮回阅读 2,001评论 0 12
  • iOS面试小贴士 ———————————————回答好下面的足够了------------------------...
    不言不爱阅读 1,955评论 0 7
  • 史上最全的iOS面试题及答案 iOS面试小贴士———————————————回答好下面的足够了----------...
    Style_伟阅读 2,342评论 0 35