iOS基础知识(面试必备)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Forever_wj/article/details/51217839

iOS开发的设计模式

一、代理模式
应用场景:当一个类的某些功能需要由别的类来实现,但是又不确定具体会是哪个类实现。
优势:解耦合
敏捷原则:开放-封闭原则
实例:tableview的 数据源delegate,通过和protocol的配合,完成委托诉求:列表row个数delegate,自定义的delegate。

二、观察者模式
应用场景:一般为model层对,controller和view进行的通知方式,不关心谁去接收,只负责发布信息。
优势:解耦合
敏捷原则:接口隔离原则,开放-封闭原则
实例:Notification通知中心,注册通知中心,任何位置可以发送消息,注册观察者的对象可以接收;KVO,键值对改变通知的观察者。

三、MVC模式
应用场景:是一中非常古老的设计模式,通过数据模型,控制器逻辑,视图展示将应用程序进行逻辑划分。
优势:使系统,层次清晰,职责分明,易于维护
敏捷原则:对扩展开放-对修改封闭
实例:model-即数据模型,view-视图展示,controller进行UI展现和数据交互的逻辑控制。

四、单例模式
应用场景:确保程序运行期某个类,只有一份实例,用于进行资源共享控制。
优势:使用简单,延时求值,易于跨模块
敏捷原则:单一职责原则
实例:[UIApplication sharedApplication]。
注意事项:确保使用者只能通过 getInstance方法才能获得,单例类的唯一实例。object c中,重写allocWithZone方法,保证即使用户用 alloc方法直接创建单例类的实例,返回的也只是此单例类的唯一静态变量。

五、策略模式
应用场景:定义算法族,封装起来,使他们之间可以相互替换。
优势:使算法的变化独立于使用算法的用户
敏捷原则:接口隔离原则;多用组合,少用继承;针对接口编程,而非实现。
实例:排序算法,NSArray的sortedArrayUsingSelector;经典的鸭子会叫,会飞案例。
注意事项:
1,剥离类中易于变化的行为,通过组合的方式嵌入抽象基类;
2,变化的行为抽象基类为,所有可变变化的父类;
3,用户类的最终实例,通过注入行为实例的方式,设定易变行为
防止了继承行为方式,导致无关行为污染子类,完成了策略封装和可替换性。

六、工厂模式
应用场景:工厂方式创建类的实例,多与proxy模式配合,创建可替换代理类。
优势:易于替换,面向抽象编程,application只与抽象工厂和易变类的共性抽象类发生调用关系。
敏捷原则:DIP依赖倒置原则
实例:项目部署环境中依赖多个不同类型的数据库时,需要使用工厂配合proxy完成易用性替换。
注意事项:项目初期,软件结构和需求都没有稳定下来时,不建议使用此模式,因为其劣势也很明显,增加了代码的复杂度,增加了调用层次,增加了内存负担,所以要注意防止模式的滥用。

delegate与block的区别

delegate:
1、“一对一”,对同一个协议,一个对象只能设置一个代理delegate,所以单例对象就不能用代理;
2、代理更注重过程信息的传输:比如发起一个网络请求,可能想要知道此时请求是否已经开始、是否收到了数据、数据是否已经接受完成、数据接收失败。
3、公共接口,方法较多选择用delegate进行解耦:iOS有很多例子比如最常用tableViewDelegate,textViewDelegate;

block:
1、写法更简练,不需要写protocol、函数等;
2、block注重结果的传输:比如对于一个事件,只想知道成功或者失败,并不需要知道进行了多少或者额外的一些信息;
3、异步和简单的回调用block更好:iOS有很多例子比如常用的网络库AFNetwork,ASIHTTP库,UIAlertView类。
4、block需要注意防止循环引用:
ARC:

__weak typeof(self) weakSelf = self;
  [yourBlock:^(NSArray *repeatedArray, NSArray *incompleteArray) {
       [weakSelf doSomething];
    }];

非ARC:

__block typeof(self) weakSelf = self;
  [yourBlock:^(NSArray *repeatedArray, NSArray *incompleteArray) {
       [weakSelf doSomething];
    }];

补充:
__block和__weak修饰符的区别:
1.__block不管是ARC还是MRC模式下都可以使用,可以修饰对象,还可以修饰基本数据类型。
2.__weak只能在ARC模式下使用,也只能修饰对象(NSString),不能修饰基本数据类型(int)。
3.__block对象可以在block中被重新赋值,__weak不可以。

常用的三方库

1、jsonjson编码解码
2、GTMBase64 base64编码解码
3、TouchXML 解析
4、SFHFKeychainUtils 安全保存用户密码到keychain中
5、MBProgressHUD很棒的一个加载等待特效框架
6、ASIHTTPRequest 等相关协议封装
7、EGORefreshTableHeaderView 下拉刷新代码
8、AsyncImageView 异步加载图片并缓存代码
9、类似setting的竖立也分栏程序
10、MBProgressHUD——进展指示符库
11、Flurry——详尽的使用统计
12、CorePlot——2D图形绘图仪
13、GData client——iPhone上所有Google相关服务的类库
14、SDWebImage——简化网络图片处理
15、RegexKitLite——正则表达式支持

网络请求GET与POST的区别

1、GET请求:将参数直接写在访问路径上,操作简单, 不过容易让外界看到, 安全性不高, 地址最多 255 字节;POST 请求: 将参数放到 body 里面, POST请求的操作相对复杂, 需要将参数和地址分开, 不过安全性高,参数放在body里面, 不容易被捕获。
2、一个URL地址,它用于描述一个网络上的资源,而HTTP中的GET,POST,PUT,DELETE就对应着对这个资源的查 ,改 ,增 ,删 4个操作。因此GET一般用于获取、查询资源信息,而POST一般用于更新资源信息。
3、GET使用URL或Cookie传参,而POST将数据放在BODY中。
4、GET的URL会有长度上的限制,则POST的数据则可以非常大。
5、POST比GET安全,因为数据在地址栏上不可见。

GCD队列dispatch_queue_t的生成方式

//生成一个串行队列,队列中的block按照先进先出(FIFO)的顺序去执行,实际上为单线程执行。第一个参数是队列的名称,在调试程序时会非常有用,所有尽量不要重名了。
dispatch_queue_t queue = dispatch_queue_create("com.dispatch.serial", DISPATCH_QUEUE_SERIAL); 

//生成一个并发执行队列,block被分发到多个线程去执行        
dispatch_queue_t queue = dispatch_queue_create("com.dispatch.concurrent", DISPATCH_QUEUE_CONCURRENT); 

//获得程序进程缺省产生的并发队列,可设定优先级来选择高、中、低三个优先级队列。由于是系统默认生成的,所以无法调用dispatch_resume()和dispatch_suspend()来控制执行继续或中断。
//需要注意的是,三个队列不代表三个线程,可能会有更多的线程。并发队列可以根据实际情况来自动产生合理的线程数,也可理解为dispatch队列实现了一个线程池的管理,对于程序逻辑是透明的。        
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 

//官网文档解释说共有三个并发队列,但实际还有一个更低优先级的队列,设置优先级为DISPATCH_QUEUE_PRIORITY_BACKGROUND。Xcode调试时可以观察到正在使用的各个dispatch队列。
dispatch_queue_t queue = dispatch_get_main_queue(); //获得主线程的dispatch队列,实际是一个串行队列。同样无法控制主线程dispatch队列的执行继续或中断。

线程和进程的联系与区别

1、进程和线程都是由操作系统所体现的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性(并发是指两个或多个任务在同一时间间隔内发生,但是在任意一个时间点CPU只会处理一个任务),进程是线程的容器,真正完成代码执行的过程,而进程则作为线程的执行环境。

2、两者的主要区别在于它们是不同的操作系统资源管理方式。进程有2立的地址空间,一个进程崩溃后,在保护模式的影响下不会对其他进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等同于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。

Block发生循环引用和解决方案

发生情况:定义 block 的时候,会对外部变量做一次copy,而将block属性设为了strong, 完成回调时强引用self。

解决办法:

    // 在ARC下,由于__block抓取的变量一样会被Block retain,所以必须用弱引用才可以解决循环引用问题,iOS 5之后可以直接使用__weak,之前则只能使用__unsafe_unretained了,__unsafe_unretained缺点是指针释放后自己不会置空。
    __weak typeof(self) weakSelf = self;
    self.myBlock = ^(int paramInt) {
         //使用weakSelf访问self成员
         [weakSelf doSomething];
    };

    //在非ARC下,显然无法使用弱引用,这里就可以直接使用__block来修饰变量,它不会被Block所retain的。
    __block typeof(self) weakSelf = self;
    self.myBlock = ^(int paramInt) {
        //使用weakSelf访问self成员
        [weakSelf doSomething];
    };

用CATextLayer实现一个UILabel

    CATextLayer *textLayer = [CATextLayer layer];
    textLayer.frame = CGRectMake(100,100,100,100);
    [self.view.layer addSublayer:textLayer];

    textLayer.foregroundColor = [UIColor blackColor].CGColor;
    textLayer.alignmentMode = kCAAlignmentJustified;
    textLayer.wrapped =YES;

    UIFont *font = [UIFontsystemFontOfSize:15];

    CFStringRef fontName = (__bridgeCFStringRef)font.fontName;
    CGFontRef fontRef = CGFontCreateWithFontName(fontName);
    textLayer.font = fontRef;
    textLayer.fontSize = font.pointSize;
    CGFontRelease(fontRef);

    NSString *text = @"Cupid laid by his brand, and fell asleep";

    textLayer.string = text;

    textLayer.contentsScale = [UIScreen mainScreen].scale; // 在Retina显示

参考文章:http://www.jianshu.com/p/7429bb12e10c

Cocoa Touch的框架

  • Address Book UI 框架:Objective-C的编程接口,可以显示创建或者编辑联系人的标准系统界面。简化了应用程序显示联系人信息所需的工作,也可以确保应用程序使用的界面和其他应用程序相同,进而保证跨平台一致性。

  • Game Kit 框架:该框架支持点对点连接及游戏内语音功能,您可以通过该框架为应用程序增加点对点网络功能。

  • Event Kit UI 框架:提供一个视图控制键可以展现查看并编辑事件的标准系统界面。

  • iAd 框架:通过该框架在应用程序中发布横幅广告,广告会被放入到标准视图,您可以将这些视图加入到用户界面,并在合适的时机向用户展现。这些视图和苹果的公告服务相互协作,自动处理广告内容的加载和展现,同时也可以响应用户对广告的点击。

  • Map Kit 框架:iOS 3.0导入了 Map Kit框架 (MapKit.framework) ,该框架供一个可被嵌入到应用程序的地图界面,该界面包含一个可以滚动的地图视图。可以在视图中添加定制信息,并可将其嵌入到应用程序视图,通过编程的方式设置地图的各种属性(包括当前地图显示的区域以及用户的方位)。也可以使用定制标注或标准标注(例如使用测针标记)突出显示地图中的某些区域或额外的信息。在iOS 4.0系统中,该框架开始支持可拖动标注以及定制覆盖层。可拖动标注允许您通过编程方式或通过用户交互方式重定位某个标注的位置。覆盖层可用于创建多个点组成的复杂地图标注。地图表面诸如公交路线、选举地图、公园边界或者气象信息(例如雷达数据)等可以使用覆盖层进行显示。

  • Message UI 框架:您可以利用该框架撰写电子邮件,并将其放入到用户的发件箱排队等候发送。该框架提供一个视图控制器界面,您可以在应用程序中展现该界面,让用户通过该界面撰写邮件。界面的字段可以根据待发送信息的内容生成。例如您可以设置接收人、主题、邮件内容并可以在邮件中包含附件。这个界面允许用户先对邮件进行编辑,然后再选择接受。在用户接受邮件内容后,相应的邮件就会放入用户的发件箱排队等候发送。

  • UIKit 框架:UIKit框架 (UIKit.framework)的Objective-C编程接口为实现iOS应用程序的图形及事件驱动提供关键基础。iOS系统所有程序都需要通过该框架实现下述核心功能:应用程序管理,用户界面管理,图形和窗口支持,多任务支持,处理触摸及移动事件,代表标准系统视图和控件的对象,文本和web内容相关操作,剪切、复制以及粘贴,使用动画显示用户界面内容,通过URL方式将其他应用程序整合到系统,苹果推送通知服务支持,为残疾用户供辅助功能,本地通知的调度和发送,创建PDF,使用定制输入视图(其行为类似系统键盘),创建和系统键盘进行交互的定制文本视图。当然还有加速器数据,内置相机(存在相机的设备),用户的图片库,设备名称和模型信息,电池状态信息,距离感应器信息,
    来自绑定听筒的远程控制信息。

  • 媒体层:
    1、Core Graphics (也被称为Quartz),用于处理本地2D向量渲染和图片渲染。
    2、Core Animation ( Quartz Core框架的一部分),为动画视图和其他内容提供更高级别支持。
    3、OpenGL ES,为使用硬件加速接口的2D和3D渲染提供支持。
    4、Core Text,提供一个精密的文本布局和渲染引擎。
    5、Image I/O,提供读取及编写大多数图形格式的接口。
    6、资产库框架(Assets Library framework),可用于访问用户照片库中的照片和视频。

  • 音频技术:
    1、媒体播放器框架。该框架可以让访问用户的iTume库变得很容易,并且支持播放曲目和播放列表。
    2、AV Foundation框架。它提供一组简单易用的Objective-C接口,可用于管理音频的播放或录制。.
    3、OpenAL框架。它提供一组跨平台,用于发布方位音频的接口。
    4、Core Audio框架。它提供的接口简单而精密,可用于播放或录制音频内容。您可以使用这些接口播放系统的警报声音、触发备的震动功能、管理多声道的缓冲和播放、对音频内容进行流化处理。

  • 视频技术:
    1、媒体播放器框架,它提供一组易于使用的接口,可用于播放应用程序中全屏或部分屏的电影。
    2、AV Foundation框架,它提供一组Objective-C接口,可以对电影的捕捉和播放进行管理。
    3、Core Media框架,它对较高级框架使用的底层类型进行描述,同时也提供一些底层接口,它们用于对媒体进行处理。

#import与@class的区别

  • “#import”会将此类的所有文件全部导入,而@class只是告诉编译器有这么一个类,引用类名,一般用在.h文件@interface之前;简而言之,就是当只需要定义此类时,只需要@class类名即可,而需要用到此类的方法或变量时,就需要用#import来包含整个类的文件;

  • 如果只需要@class ,而用了#import是不会报错的,但是会大大影响程序的效率,因为这样在编译过程中必须将import的所有类都编译一遍,尤其是引用的类比较多时;比如你在A类中import了B类,而B类中又import了c、d类,那程序在编译时要将A,B,c,d类全部编译一遍,而用@class则不会耗费大量时间。

  • 如果有循环依赖关系,如:A–>B, B–>A这样的相互依赖关系,如果使用#import来相互包含,那么就会出现编译错误,如果使用@class在两个类的头文件中相互声明,则不会有编译错误出现。

如何解决滑动TableView时卡顿的问题

tableView 滑动卡的问题主要是因为:从缓存中或者是从本地读取图片给UIImage的时候耗费的时间比较长。需要在子线程中添加:

NSData *imgData = [NSData dataWithContentsOfURL:[NSURL URLWithString:app.icon]]; //得到图像数据  
UIImage *image = [UIImage imageWithData:imgData];

然后在主线程中将image的值赋值给相应的imageView.image;
当然,这是主要的问题解决,如果想更好地解决,还有最好使用不透明视图以及不要重复创建不必要的table cell等优化的地方。

UIView的父类与子类

UIButton的父类是UIControl
UIControl的父类是UIView
UIView的父类是 UIResponder

Objective-C中的self和super

当使用self调用方法时,会从当前类的方法列表中开始找,如果没有,就从父类中再找;当使用super时,则从父类的方法列表中开始找,然后调用这个方法。

Objective-C中的copy与retain区别

copy是内容拷贝,对象指向不同的地址,而retain是指针拷贝,指向相同的地址,计数加1。

Objective-C中的assign与retain的区别

assign是直接赋值,如果两个对象共享一内存地址,不能直接释放这块内存地址,否则会引起崩溃现象;当数据为int、 float等原生类型时,使用assign则不会;
使用retain则可以给上面的内存地址分配引用计数,retain引起引用计数加1,release引起引用计数减1,当引用计数为0时,dealloc函数被调用,内存被回收。

Objective-C中的weak与strong的区别

1、在对象属性上使用weak 和strong时,strong就相当于retain属性,让引用计数+1,而weak相当于assign则不会。
2、只有一种情况需要使用weak(默认是strong),就是为了避免retain cycles(就是父类中含有子类{父类retain了子类},子类中又调用了父类{子类又retain了父类},这样都无法release)
3、声明为weak的指针,指针指向的地址一旦被释放,这些指针都将被赋值为nil,这样的好处能有效的防止野指针。

写一个NSString类的实现

+ (id)initWithCString:(const char*)nullTerminatedCString encoding:(NSStringEncoding)encoding;

+ (id) stringWithCString: (constchar*)nullTerminatedCString encoding: (NSStringEncoding)encoding { 
    NSString *obj; 
    obj = [self allocWithZone:NSDefaultMallocZone()]; 
    obj = [obj initWithCString:nullTerminatedCString encoding: encoding]; 
    return AUTORELEASE(obj);
}

Objective-C语言的优缺点

Objective-C优点:
1) Cateogies
2) Posing
3) 动态识别
4) 指标计算
5) 弹性讯息传递
6) 不是一个过度复杂的 C 衍生语言
7) Objective-C 与 C++ 可混合编程
Objective-C缺点:
1) 不支援命名空間
2) 不支持运算符重载
3) 不支持多重继承
4) 使用动态运行时类型,所有的方法都是函数调用,所以很多编译时优化方法都用不到(如内联函数等),性能低劣。

猜你喜欢

转载自blog.csdn.net/Forever_wj/article/details/51217839
今日推荐