iOS面试题目

来源:互联网 发布:加密db数据库怎么打开 编辑:程序博客网 时间:2024/06/08 18:14

面试 题  


1、BLOCK

如果要在block内修改block外声明的栈变量,那么一定要对该变量加__block标记

block引起了实例与block之间的循环引用(retain-cycle),并且给出解决方案:不直接使用self而先将self赋值给一个临时变量,然后再使用这个临时变量。


但是,大家注意,我们一定要为这个临时变量增加__block标记


2、线程

1.1 iOS有三种多线程编程的技术,分别是:


Cocoa operation 

优点:不需要关心线程管理,数据同步的事情,可以把精力放在自己需要执行的操作上。

Cocoa operation 相关的类是 NSOperation ,NSOperationQueue。NSOperation是个抽象类,使用它必须用它的子类,可以实现它或者使用它定义好的两个子类:NSInvocationOperation 和 NSBlockOperation。创建NSOperation子类的对象,把对象添加到NSOperationQueue队列里执行。

GCD

Grand Central Dispatch (GCD)是Apple开发的一个多核编程的解决方法。在iOS4.0开始之后才能使用。GCD是一个替代诸如NSThread, NSOperationQueue, NSInvocationOperation等技术的很高效和强大的技术。



1、NSThread的使用

 NSThread 有两种直接创建方式:

- (id)initWithTarget:(id)target selector:(SEL)selector object:(id)argument

+ (void)detachNewThreadSelector:(SEL)aSelector toTarget:(id)aTarget withObject:(id)anArgument

第一个是实例方法,第二个是类方法

[cpp] view plaincopy

1、[NSThread detachNewThreadSelector:@selector(doSomething:) toTarget:self withObject:nil];  

2、NSThread* myThread = [[NSThread alloc] initWithTarget:self  

                                        selector:@selector(doSomething:)  

                                        object:nil];  

[myThread start];  

2.2参数的意义:

selector :线程执行的方法,这个selector只能有一个参数,而且不能有返回值。

target  :selector消息发送的对象

argument:传输给target的唯一参数,也可以是nil


用NSObject的类方法  performSelectorInBackground:withObject: 创建一个线程:

[Obj performSelectorInBackground:@selector(doSomething) withObject:nil];


2.4 下载图片的例子:


-(void)downloadImage:(NSString *) url{  

    NSData *data = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:url]];  

    UIImage *image = [[UIImage alloc]initWithData:data];  

    if(image == nil){  

          

    }else{  

        [self performSelectorOnMainThread:@selector(updateUI:) withObject:image waitUntilDone:YES];  

    }  

}  

  

-(void)updateUI:(UIImage*) image{  

    self.imageView.image = image;  

}  

  

  

- (void)viewDidLoad  

{  

    [super viewDidLoad];  

      

//    [NSThread detachNewThreadSelector:@selector(downloadImage:) toTarget:self withObject:kURL];  

    NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(downloadImage:) object:kURL];  

    [thread start];  

}  

  

- (void)didReceiveMemoryWarning  

{  

    [super didReceiveMemoryWarning];  

    // Dispose of any resources that can be recreated.  

}  

  

@end  

2.4.2线程间通讯

线程下载完图片后怎么通知主线程更新界面呢?

[self performSelectorOnMainThread:@selector(updateUI:) withObject:image waitUntilDone:YES];

performSelectorOnMainThread是NSObject的方法,除了可以更新主线程的数据外,还可以更新其他线程的比如:

用:performSelector:onThread:withObject:waitUntilDone: 

    



2、GCD


dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{


        dispatch_async(dispatch_get_main_queue(), ^{


        });

});


dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);  

dispatch_group_t group = dispatch_group_create();  

dispatch_group_async(group, queue, ^{  

    [NSThread sleepForTimeInterval:1];  

    NSLog(@"group1");  

});  

dispatch_group_async(group, queue, ^{  

    [NSThread sleepForTimeInterval:2];  

    NSLog(@"group2");  

});  

dispatch_group_async(group, queue, ^{  

    [NSThread sleepForTimeInterval:3];  

    NSLog(@"group3");  

});  

dispatch_group_notify(group, dispatch_get_main_queue(), ^{  

    NSLog(@"updateUi");  

});  

dispatch_release(group);  



dispatch_barrier_async是在前面的任务执行结束后它才执行,而且它后面的任务等它执行完成之后才会执行

例子代码如下:

[cpp] view plaincopy

dispatch_queue_t queue = dispatch_queue_create("gcdtest.rongfzh.yc", DISPATCH_QUEUE_CONCURRENT);  

dispatch_async(queue, ^{  

    [NSThread sleepForTimeInterval:2];  

    NSLog(@"dispatch_async1");  

});  

dispatch_async(queue, ^{  

    [NSThread sleepForTimeInterval:4];  

    NSLog(@"dispatch_async2");  

});  

dispatch_barrier_async(queue, ^{  

    NSLog(@"dispatch_barrier_async");  

    [NSThread sleepForTimeInterval:4];  

  

});  

dispatch_async(queue, ^{  

    [NSThread sleepForTimeInterval:1];  

    NSLog(@"dispatch_async3");  

}); 


执行某个代码片段N次。

dispatch_apply(N, globalQ, ^(size_t index) {


});





3、NSOperation


- (void)viewDidLoad  

{  

    [super viewDidLoad];  

    NSInvocationOperation *operation = [[NSInvocationOperation alloc]initWithTarget:self  

                                                                           selector:@selector(downloadImage:)  

                                                                             object:kURL];  

      

    NSOperationQueue *queue = [[NSOperationQueue alloc]init];  

    [queue addOperation:operation];  

    // Do any additional setup after loading the view, typically from a nib.  

}  

  

-(void)downloadImage:(NSString *)url{  

    NSLog(@"url:%@", url);  

    NSURL *nsUrl = [NSURL URLWithString:url];  

    NSData *data = [[NSData alloc]initWithContentsOfURL:nsUrl];  

    UIImage * image = [[UIImage alloc]initWithData:data];  

    [self performSelectorOnMainThread:@selector(updateUI:) withObject:image waitUntilDone:YES];  

}  

-(void)updateUI:(UIImage*) image{  

    self.imageView.image = image;  

}  



如何控制线程池中的线程数

队列里可以加入很多个NSOperation, 可以把NSOperationQueue看作一个线程池,可往线程池中添加操作(NSOperation)到队列中。线程池中的线程可看作消费者,从队列中取走操作,并执行它。

通过下面的代码设置:

[queue setMaxConcurrentOperationCount:5];

线程池中的线程数,也就是并发操作数。默认情况下是-1,-1表示没有限制,这样会同时运行队列中的全部的操作



XML解析


如何通过URL获取XML数据

xml解析使用AFXMLRequestOperation,需要实现苹果自带的NSXMLParserDelegate委托方法,XML中有一些不需要的协议格式内容,所以就不能像json那样解析,还得实现委托。我之前有想过能否所有的XML链接用一个类处理,而且跟服务端做了沟通,结果很不方便,效果不好。XML大多标签不同,格式也不固定,所以就有问题,使用json就要方便的多。

第一步;在.h文件中加入委托NSXMLParserDelegate

第二步;在.m文件方法中加入代码

    NSURL *url = [NSURL URLWithString:@"http://113.106.90.22:5244/sshopinfo"];

    NSURLRequest *request = [NSURLRequest requestWithURL:url];

    AFXMLRequestOperation *operation =

    [AFXMLRequestOperation XMLParserRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, NSXMLParser *XMLParser) {

        XMLParser.delegate = self;

        [XMLParser setShouldProcessNamespaces:YES];

        [XMLParser parse];

    }failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, NSXMLParser *XMLParser) {

        NSLog(@"%@",error);

    }];

    [operation start];

第三步;在.m文件中实现委托方法

    //在文档开始的时候触发

-(void)parserDidStartDocument:(NSXMLParser *)parser{

    NSLog(@"解析开始!");

}

//解析起始标记

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{

    NSLog(@"标记:%@",elementName);

    

}

//解析文本节点

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{

    NSLog(@"值:%@",string);

}

//解析结束标记

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{

    NSLog(@"结束标记:%@",elementName);

}

//文档结束时触发

-(void) parserDidEndDocument:(NSXMLParser *)parser{

    NSLog(@"解析结束!");

}




iOS  适配


layout 


NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:firstButton attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqualtoItem:self.view attribute:NSLayoutAttributeLeading multiplier:1.0f constant:20.f];

 

[self.view addConstraint:constraint];



Auto Layout用一个公式来计算界面之间的关系:


A = B * m + c


或者


viewA.attribute = viewB.attributs*multiplier + constant


在这个例子中公式如下:

 

firstButton.NSLayoutAttributeLeading = self.view.NSLayoutAtrributeLeading * 1.0f + 20f


按钮左边的位置等于父视图左边距减掉20.


把下面的约束添加到viewDidLoad里


constraint = [NSLayoutConstraint constraintWithItem:firstButton attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqualtoItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0f constant:30.f];

 

[self.view addConstraint:constraint];


该约束将会使按钮距离父视图上面30个点。Build and Run。这个按钮距离左边20个点,上面30个点。




地图 相关 


------------CLLocation

CLLocation类代表一个位置信息,其中还包括了方向和速度。比如我在长安街188号以5公里/小时的速度往西走。CLLocation具有下面的属性和方法:

@property  CLLocationCoordinate2D coordinate; //以经度和纬度表示的位置信息

@property CLLocationDistance altitude;  //海拔

@property CLLocationAccuracy horizontalAccuracy; //水平精度(如:精确到米)

@property CLLocationAccuracy verticalAccuracy; //垂直精度

@property CLLocationDirection course; //方向

@property CLLocationSpeed speed; //速度

-(NSDate *)timeStamp;

//两个位置之间的距离

-(CLLocationDistance)distanceFromLocation:(CLLocation *)location;



-------------CLLocationManager

CLLocationManager类管理和提供位置服务。它的属性和方法有:

@property CLLocation *location; //位置

@property id<CLLocationManagerDelegate> delegate;

@property CLLocationDistance distanceFilter; //距离过滤,比如:500以内

@property CLlocationAccuracy verticalAccuracy; //垂直精度

-(void) startUpdatingLocation; //开始更新位置(比如:你在往某个地方走)

-(void)stopUpdatingLocation; //停止更新位置

-(void)startUpdatingHeading; //开始更新方向(比如:你改往东走)

-(void)stopUpdatingHeading; //停止更新方向

CLLocationManagerDelegate是一个委托类。你的应用程序需要使用这个委托类。当用户改变位置的时候,CLLocationManager回调的方法是:

-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation;

当用户改变方向的时候,所调用的方法是:

-(void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLLHeading *)newHeading;

当iPhone无法获得当前位置的信息时,所回调的方法是:

-(void)locationManager: (CLLocationManager *)manager didFailLoadWithError:(NSError *)error;



=========================================================================

下面我们来看一个位置类的基本步骤:

一、启动定位服务

CLLocationManager *locManager = [[CLLocationManager alloc] init];

locManager.delegate = self;

[locManager startUpdatingLocation];

二、获得位置信息

-(void)locationManager:(CLLocationManager *)manager

didUpdateToLocation:(CLLocation *)newLocation fromLocation: (CLLocation *)oldLocation

{

NSTimeInterval howRecent = [newLocation.timestamp timeIntervalSinceNow];

if(howRecent < -10) return ; //离上次更新的时间少于10秒

if(newLocation.horizontalAccuracy > 100) return; //精度> 100米

//经度和纬度

double lat = newLocation.coordinate.latitude;

double lon = newLocation.coordinate.longitude;

}

三、获得方向信息(比如往南走)

-(void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading

{

//获得方向

CLLocationDirection heading = newHeading .trueHeading;

}

四、停止定位

[locManager stopUpdatingLocation];

你可以设置你想要的精度和距离过滤:

locManager.desiredAccuracy = kLLocationAccuracyBest;

locManager.distanceFilter = 1000;



MapKit框架:

     主要提供了四个功能:显示地图、CLLocation和地址之间的转换、支持在地图上做标记(比如标记北京天安门广场)、把一个位置解析成地址(比如我在水立方,想要知道确切的地址信息)。

 MKMapView类:主要是完成下述功能:

-------显示地图,比如:显示北京市的地图;

-------提供多种显示方式,比如标准地图格式,卫星地图等;

-------支持地图的放大缩小;

-------支持在地图上做标记,比如标记天安门广场;

-------在地图上显示手机所在的当前位置。

MKMapView类的属性有:

@property MKCoordinateRegin region; //地图所显示的区域

@property CLLocationCoordinate2D centerCoordinate; //经度和纬度确定的中心位置

@property MKMapView mapType; //地图的显示类型,如:卫星地图

@property NSArray *annotations; //地图上的标记

@property MKUserLocation userLocation; //用户位置

@property id <MKMapViewDelegate>delegate; //委托类



装载地图时的回调方法有:

-(void)mapViewWillStartLocationMap:(MKMapView *) mapView; //开始装载地图

-(void)mapViewDidFinishLocationMap:(MKMapView  *)mapView; //结束装载地图

-(void)mapVewDidFailLoadingMap:(MKMapView *)mapView withError:(NSError *)error; //装载失败



当位置发生转变时的回调方法:

-(void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated; //将要更改

-(void)mapView: (MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated; //已经更改



MKPlacemark、MKUserLocation和MKReverseGeocoder

在地图上做标记是通过MKPlacemark类来完成的。这个类使用(符合)MKAnnotation协议。MKAnnotation包含了多个属性,如:位置(经纬度,CLLocationCoordinate2D类型)、文字标记信息(NSString类型)等。

MKPlacemark保存了位置(经纬度)和地址(字典类)之间的映射。下面是它的初始化方法:

-(void)initWithCoordinate:(CLLocationCoordinate2D *)coordinate addressDictionary:(NSDictionary *)dictionary;

MKUserLocation就是指手机的当前位置,它是MKAnnotation的一个特别案例(因为MKAnnotation可以是地图上的任何标记,而MKUserLocation只是标记了地图上手机所在的当前位置)。这个类包含了多个属性:手机的位置(类型为CLLocation)、位置文字信息(类型为NSString)等。

MKPlacemark保存了位置(经纬度)和地址之间的映射。那么,有没有工具在这两者之间做转换呢?这就是MKRecerseGeocoder.给定一个位置信息,这个类可以返回相应的地址信息。MKReverseGeocoder的初始化方法为:

-(void)initWithCoodinate:(CLLocationCoordinate2D)coordinate;

下面是MKReverseGeocoder常用的一些属性和方法:

@property id <MKReverseGeocoderDelegate>delegate; //委托

-(void)start; //开始转换

-(void)cancel; //取消转换



回调的方法有:

-(void)reverseGeocoder:(MKReverseGeocoder *) geocoded didFindPlacemark:(MKPlacemark *)placemark;  //转换成功

-(void)reverseGeocoder : (MKReverseGeocoder *)geocoded didFailWithError:(NSError *)error; //转换失败



推送


Apple Push Notification的工作机制


自己的客户端发送消息到自己应用软件的apns,apns发送消息到你的手机。这个是根据令牌识别的。手机在发送消息到你的应用软件。


  首先是应用程序注册消息推送。

IOS跟APNS Server要deviceToken。应用程序接受deviceToken。

应用程序将deviceToken发送给PUSH服务端程序(Provider)。

服务端程序向APNS服务发送消息。

APNS服务将消息发送给iPhone应用程序。


/** 注册推送通知功能, */ 

    [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound)];  





- (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {  


    NSString* token = [NSString stringWithFormat:@"%@",deviceToken];  

    NSLog(@"apns -> 生成的devToken:%@", token);  

    //把deviceToken发送到我们的推送服务器  

    DeviceSender* sender = [[[DeviceSender alloc]initWithDelegate:self ]autorelease];  

    [sender sendDeviceToPushServer:token ];      

}  

 


- (void)application:(UIApplication *)app didFailToRegisterForRemoteNotificationsWithError:(NSError *)err {  


 


    NSLog(@"apns -> 注册推送功能时发生错误, 错误信息:\n %@", err);  

}

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo  

{  

    NSLog(@"\napns -> didReceiveRemoteNotification,Receive Data:\n%@", userInfo);  

    //把icon上的标记数字设置为0,  

    application.applicationIconBadgeNumber = 0;  

    if ([[userInfo objectForKey:@"aps"] objectForKey:@"alert"]!=NULL) {  

        UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"**推送消息**" 

                                                        message:[[userInfo objectForKey:@"aps"] objectForKey:@"alert"]  

                                                       delegate:self  

                                              cancelButtonTitle:@"关闭" 

                                              otherButtonTitles:@"处理推送内容",nil];  

        alert.tag = alert_tag_push;  

        [alert show];  

    }  

}  


一、什么是TCP连接的三次握手


  第一次握手:客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;


  第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;


  第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。


  握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。


  理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭连接之前,TCP 连接都将被一直保持下去。


  断开连接时服务器和客户端均可以主动发起断开TCP连接的请求,断开过程需要经过“四次握手”(过程就不细写了,就是服务器和客户端交互,最终确定断开)


  二、利用Socket建立网络连接的步骤


  建立Socket连接至少需要一对套接字,其中一个运行于客户端,称为ClientSocket ,另一个运行于服务器端,称为ServerSocket 。


  套接字之间的连接过程分为三个步骤:服务器监听,客户端请求,连接确认。


  1、服务器监听:服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态,等待客户端的连接请求。


  2、客户端请求:指客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。


  为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。


  3、连接确认:当服务器端套接字监听到或者说接收到客户端套接字的连接请求时,就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,双方就正式建立连接。


  而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。


TCP和UDP的区别


  1、TCP是面向链接的,虽然说网络的不安全不稳定特性决定了多少次握手都不能保证连接的可靠性,但TCP的三次握手在最低限度上(实际上也很大程度上保证了)保证了连接的可靠性;


  而UDP不是面向连接的,UDP传送数据前并不与对方建立连接,对接收到的数据也不发送确认信号,发送端不知道数据是否会正确接收,当然也不用重发,所以说UDP是无连接的、不可靠的一种数据传输协议。


  2、也正由于1所说的特点,使得UDP的开销更小数据传输速率更高,因为不必进行收发数据的确认,所以UDP的实时性更好。


  知道了TCP和UDP的区别,就不难理解为何采用TCP传输协议的MSN比采用UDP的QQ传输文件慢了,但并不能说QQ的通信是不安全的,


  因为程序员可以手动对UDP的数据收发进行验证,比如发送方对每个数据包进行编号然后由接收方进行验证啊什么的,


  即使是这样,UDP因为在底层协议的封装上没有采用类似TCP的“三次握手”而实现了TCP所无法达到的传输效率。




1. 你使用过Objective-C的运行时编程(Runtime Programming)么?如果使用过,你用它做了什么?你还能记得你所使用的相关的头文件或者某些方法的名称吗?  

Objecitve-C的重要特性是Runtime(运行时),在#import <objc/runtime.h> 下能看到相关的方法,用过objc_getClass()和class_copyMethodList()获取过私有API;使用  

```objective-c

Method method1 = class_getInstanceMethod(cls, sel1);

Method method2 = class_getInstanceMethod(cls, sel2);

method_exchangeImplementations(method1, method2);  

```   

代码交换两个方法,在写unit test时使用到。  

2. 你实现过多线程的Core Data么?NSPersistentStoreCoordinator,NSManagedObjectContext和NSManagedObject中的哪些需要在线程中创建或者传递?你是用什么样的策略来实现的?  

没实现过多线程的CoreData(待实践) 

<!--more--> 

3. Core开头的系列的内容。是否使用过CoreAnimation和CoreGraphics。UI框架和CA,CG框架的联系是什么?分别用CA和CG做过些什么动画或者图像上的内容。(有需要的话还可以涉及Quartz的一些内容)  

UI框架的底层有CoreAnimation,CoreAnimation的底层有CoreGraphics。    

UIKit | 

------------ | 

Core Animation | 

Core Graphics |

Graphics Hardware|  

使用CA做过menu菜单的展开收起(太逊了)  

4. 是否使用过CoreText或者CoreImage等?如果使用过,请谈谈你使用CoreText或者CoreImage的体验。

CoreText可以解决复杂文字内容排版问题。CoreImage可以处理图片,为其添加各种效果。体验是很强大,挺复杂的。

5. NSNotification和KVO的区别和用法是什么?什么时候应该使用通知,什么时候应该使用KVO,它们的实现上有什么区别吗?如果用protocol和delegate(或者delegate的Array)来实现类似的功能可能吗?如果可能,会有什么潜在的问题?如果不能,为什么?(虽然protocol和delegate这种东西面试已经面烂了…)

NSNotification是通知模式在iOS的实现,KVO的全称是键值观察(Key-value observing),其是基于KVC(key-value coding)的,KVC是一个通过属性名访问属性变量的机制。例如将Module层的变化,通知到多个Controller对象时,可以使用NSNotification;如果是只需要观察某个对象的某个属性,可以使用KVO。

对于委托模式,在设计模式中是对象适配器模式,其是delegate是指向某个对象的,这是一对一的关系,而在通知模式中,往往是一对多的关系。委托模式,从技术上可以现在改变delegate指向的对象,但不建议这样做,会让人迷惑,如果一个delegate对象不断改变,指向不同的对象。  

6. 你用过NSOperationQueue么?如果用过或者了解的话,你为什么要使用NSOperationQueue,实现了什么?请描述它和GCD的区别和类似的地方(提示:可以从两者的实现机制和适用范围来描述)。

使用NSOperationQueue用来管理子类化的NSOperation对象,控制其线程并发数目。GCD和NSOperation都可以实现对线程的管理,区别是 NSOperation和NSOperationQueue是多线程的面向对象抽象。项目中使用NSOperation的优点是NSOperation是对线程的高度抽象,在项目中使用它,会使项目的程序结构更好,子类化NSOperation的设计思路,是具有面向对象的优点(复用、封装),使得实现是多线程支持,而接口简单,建议在复杂项目中使用。

项目中使用GCD的优点是GCD本身非常简单、易用,对于不复杂的多线程操作,会节省代码量,而Block参数的使用,会是代码更为易读,建议在简单项目中使用。

更详细的答案见我的这篇文章

7. 既然提到GCD,那么问一下在使用GCD以及block时要注意些什么?它们两是一回事儿么?block在ARC中和传统的MRC中的行为和用法有没有什么区别,需要注意些什么?如何避免循环引用?

使用block是要注意,若将block做函数参数时,需要把它放到最后,GCD是Grand Central Dispatch,是一个对线程开源类库,而Block是闭包,是能够读取其他函数内部变量的函数。更详细的答案见我的这篇文章

8. 您是否做过异步的网络处理和通讯方面的工作?如果有,能具体介绍一些实现策略么?

使用NSOperation发送异步网络请求,使用NSOperationQueue管理线程数目及优先级,底层是用NSURLConnetion,详细可见开源框架[LWConnetion](https://github.com/xunyn/LWConnetionDemo)。  

9. 对于Objective-C,你认为它最大的优点和最大的不足是什么?对于不足之处,现在有没有可用的方法绕过这些不足来实现需求。如果可以的话,你有没有考虑或者实践过重新实现OC的一些功能,如果有,具体会如何做?

最大的优点是它的运行时特性,不足是没有命名空间,对于命名冲突,可以使用长命名法或特殊前缀解决,如果是引入的第三方库之间的命名冲突,可以使用link命令及flag解决冲突。  

10. 你实现过一个框架或者库以供别人使用么?如果有,请谈一谈构建框架或者库时候的经验;如果没有,请设想和设计框架的public的API,并指出大概需要如何做、需要注意一些什么方面,来使别人容易地使用你的框架。

抽象和封装,方便使用。首先是对问题有充分的了解,比如构建一个文件解压压缩框架,从使用者的角度出发,只需关注发送给框架一个解压请求,框架完成复杂文件的解压操作,并且在适当的时候通知给是哦难过者,如解压完成、解压出错等。在框架内部去构建对象的关系,通过抽象让其更为健壮、便于更改。其次是API的说明文档。


sdimage第三方框架的整体思路写出来!制一个不一样的方案完成同样功能!写出来

0 0
原创粉丝点击