1七、iOS面试题·自整理·Two

  • 多线程的底层实现

    1.首先搞清楚是什么线程、什么是多线程
    2.Mach是第一个以多线程方式处理任务的系统,所以多线程的底层实现机制是基于Mach的线程
    3.开发中不多用Mach级的线程,由于Mach级的线程没有提供多线程的基本特征,线程之间是独立的
    4.开发中实现多线程的方案
    * C语言的POSIX接口:#include <pthread.h>
    * OC的NSThread
    * C语言的GCD接口(性能最好,代码更精简)
    * OC的NSOperation和NSOperationQueue(基于GCD)

  • weak和assign的区别

    weak:用于各类UI控件以及代理(PS:weak是在用Xib或者StoryBord拖拽的时候的默认属性,在本身用代码流定义控件的时候,在把控很差的状况下,用strong便可)
    assign:用于基本数据类型(PS:好比:NSInteger、long、int、float、double、BOOL)

  • Objective-C支持多继承么?

    Objective-C不支持多继承。能够经过遵循多个协议来实现多继承。

  • #import "XXX.h";和@class + 类名;的区别

    1.#import会包含这个类的全部信息,包括实体变量和方法;而@class只是告诉编译器,其后面声明的名称是类的名称。至关于,@class对当前类说:这些类是如何定义的,你暂时不用考虑知道,后面会再告诉你的。
    2.在头文件中,通常只须要知道被引用的类的名称就能够了。不须要知道其内部的实体变量和方法具体是啥。因此,在X的头文件(即X.h)中通常使用@class来声明这个名称是类的名称。而在X的实现类(即X.m)里面,由于会用到这个引用类的内部的实体变量和方法。因此须要使用#import来包含这个被引用类的头文件。
    3.从编译效率方面考虑,若是你有100个头文件都#import了同一个头文件,或者这些头文件是属于依次引用的关系,例如:A--->B,B--->C,C--->D,D--->E,……,这样的引用关系。当最开始的那个头文件有变化的话,后面全部引用它的类都须要从新编译,而此时刚好你的类不少不少的话,那将会耗费大量的时间。而,使用@class则不会。
    4.若是有循环依赖关系(即相互引用关系),例如:A--->B,B--->A,这样的相互依赖关系,此时再使用#import来相互包含,那么就会出现编译错误;若是使用@class在两个类的头文件(即X.h)中相互声明,则不会出现编译错误,而后再在两个类的实现文件(即X.m)中使用#import包含彼此的头文件,就能够用彼此类内部的实体变量和方法了。
    So,通常来讲,@class是放在interface中的,只是为了在interface中引用这个类,把这个类做为一个类型来用的。在实现这个接口的实现类中,若是须要引用这个类的实体变量或者方法之类的,仍是须要#import那个在@class中声明的类,放在实现类中。

  • 系统中有哪些对象是单例?请写个单例。

    系统中的单例对象是:NSNotification、UIApplication、NSUserDefaults、NSFileManager、NSURLCache、AVAudioSession
    *本身实现单例须要注意:
    1.不使用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; }
    2.使用GCD时(即考虑线程安全时):
    +(instancetype)sharedInstance{ static HCDSingleton *singleton = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ singleton = [[HCDSingleton alloc]init]; }); return singleton; }

  • 简单讲一下你对协议的理解。

    举个简单的例子吧。
    A须要某样物品,可是A因为某些缘由无法儿获得该物品,A委托B帮忙弄来这样物品,A制定一项协议,B愿意遵循A作的协议中的规定,这样B就能够提供给A其须要的那样物品。协议中包含了遵循方B所须要实现的方法,以及B能作的事情。换句话理解就是,B必须提供出这样的物品,并且,必须是合法途径。

  • 如何理解ARC自动引用计数机制?

    ARC的自动引用计数机制,并非相似于Java中的垃圾回收机制。ARC的自动引用计数机制,只是使引用计数消失掉,而是为咱们的代码自动加上ratain、release、autorelease语句。

  • 如何理解retain、copy、assign、release、autorelease、dealloc关键字?

    retain:调用retain函数,会让对象引用计数+1;
    release:调用release函数,会让对象引用计数-1;
    delloc:当对象引用计数为0时,会自动调用delloc将对象进行释放掉。即,对象在销毁的时候自动调用该函数,禁止手动调用。
    copy:当你不想让A与B共享一块内存的时候,让A和B有各自的内存。
    assign:在使用基本数据类型的时候,须要使用assign,assign会直接赋值,不会引发对象的引用计数+1。
    autorelease:自动释放、延迟释放。写了autorelease的对象指针,并不会当即释放,只是把这个对象指针放入到最近的autoreleasepool中,等这个池子释放的时候,会给池子中的全部对象指针发送一条真正的release消息,而后将它们release掉。

  • 请简述self.name = XXX与_name = XXX的区别。

    self.name其实是调用了set方法给变量赋值。
    _name是直接给变量赋值。

  • 请简述类别和继承有什么联系和区别。

    类别和继承都会使用父类中的原有方法和属性,类别是对父类进行扩展。继承是讲父类中的属性、方法等保留下来,根据本身的实际需求情况进行实现。
    继承能够增长、修改、删除方法,还能够增长属性。
    类别、类目、类的扩展,即category,只能增长方法。可是,经过runtime能够实现动态的增长属性。也便是成员变量。

  • 请简述你对strong和weak关键字的理解。

    strong:至关于retain,让对象引用计数+1,防止对象在异常状况下被提早释放,致使crash。
    weak:弱引用,防止产生循环引用致使没法释放对象和产生野指针。
    strong,强引用,在ARC中使用strong告诉编译器帮咱们自动插入retain关键字。
    weak,弱引用,是普通赋值,至关于MRC中的assign。

  • 如何实现ARC和MRC的混合编程?

    工程名---->Targets---->build settings---->Apple LLVM 7.0 – Language - Modules---->Objective-C Automatic Reference Counting---->YES~ARC模式/NO~MRC模式/-fno-objc-arc~ARC和MRC混编模式

  • Objective-C中变量默认是私有的吗?方法默认是私有的吗?

    Objective-C中变量默认是私有的,即private;
    方法默认是公有的,即public。

  • 请简述页面传值都有哪些实现方式?

    Block、代理、通知、单例、NSUserDefaults、属性

  • 请简述 深拷贝 和 浅拷贝的区别。

    举个例子①:
    往简单了来讲:浅拷贝就比如物体A的影子,物体A拿走了,物体A的影子也就没了;深拷贝就比如又拿来一个跟物体A如出一辙的物体B,就算物体A被拿走了,物体B仍然存在。
    举个例子②:
    你们都用过Windows,这里就举Windows下文件夹的操做来讲:
    浅拷贝就相似于存在于D盘内的X文件夹,建立到桌面快捷方式,若是D盘内的X文件夹存在,就能够经过桌面建立的X文件夹快捷方式打开;若是不存在,则经过桌面建立的X文件夹快捷方式也没法打开;
    深拷贝就相似于存在于D盘内的X文件夹,拷贝到桌面,就算 D盘里的X文件夹删除了,桌面拷贝的X文件夹依然能够打开,并且内容如出一辙。
    浅析原理:
    深拷贝会从新再堆上开辟一块内存空间,是一个全新的对象,指针地址和原来的不同。浅拷贝不会从新开辟一块内存空间,指针和原来是同样的。
    深拷贝和浅拷贝的本质区别是:若是地址相同,就是浅拷贝;若是地址不一样,就是深拷贝。
    浅拷贝操做后,并无进行真正的复制,而是另外一个指针也指向了同一个地址。深拷贝操做后,是真正的复制了一份,另外一个指针指向了拷贝后的地址。
    备注:
    retain:始终是浅复制。引用计数每次+1.返回对象是否可变与被复制的对象保持一致。
    copy:对于可变对象为深复制,引用计数不改变;对于不可变对象是浅复制,引用计数每次+1。不管被复制的对象是可变仍是不可变,最终都返回一个不可变对象。
    mutableCopy:始终是深复制,引用计数不改变。始终返回一个可变对象。
    不可变对象:值发生改变,其内存首地址随之改变。
    可变对象:不管值是否改变,其内存首地址都不随之改变。
    引用计数:为了让使用者清楚的知道,该对象有多少个拥有者(即有多少个指针指向统一内存地址)。

  • 请简述对MVC设计模式的理解。

    MVC:
    Model:负责存储、定义、操做数据;
    View:负责呈现画面以及与用户进行操做交互
    Controller:Model和View的协调者,Controller把Model中的数据拿过来给View用。
    Controller能够直接与Model和View进行通讯,而View不能和Controller直接通讯。View与Controller通讯须要利用代理协议的方式,当有数据更新时,Model也要与Controller进行通讯,这个时候就要用Notification和KVO,这个方式就像广播同样,Model发信号,Controller设置监听接收信号,当有数据更新时就发信号给Controller,Model和View不能直接进行通讯,这样会违背MVC设计模式。

  • iOS中哪些技术符合观察者模式?

    首先,先说明一下,什么是观察者模式。
    观察者模式,即Key-Value Observing,它提供一种机制,当指定的对象的属性被修改后,则对象就会接收到通知。每次指定的被观察的对象的属性被修改后,KVO自动通知相应的观察者。
    iOS中,通知(即NSNotification)符合观察者模式的一种。

  • 什么是代理模式?实现代理须要注意什么?

    代理模式:做为被委托方,帮助别人(即,委托方)完成别人(即,委托方)委托你完成的事情。
    你须要注意遵照别人(即,委托方)给你定的约定,和你是否拥有完成这件事的能力。

  • 请简述StoryBord和Xib的联系和区别。简述手动编写代码。

    StoryBord能够在上面实现整个项目界面的搭建,能够清楚得看到各个试图控制器之间的关系;Xib实现自定义要素和良好部件重用性复杂的UI。
    StoryBoard,方便整个项目界面的搭建。优势:能够看到界面效果,能同时进行多个界面的交互。缺点:不能进行界面的定制,缺乏灵活性。
    Xib,方便对界面进行编辑。能够在Xib上直接以托拉拽的方式添加各类视图。优势:直接看到界面的效果,操做简单。缺点:不方便对视图进行动态控制,不灵活。
    手动编写代码,继承(主要是UIView、UIViewController)。优势:能够对视图进行定制,灵活控制方便。缺点:不能立刻看到效果、复杂。

  • 请简述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]; }

  • 如何使用UIStrollView实现无限加载多张图片?

    1.添加并设置定时器
    2.设置定时器的调用方法
    ①. 获取当前正在展现的位置
    ②. 计算出下一个须要展现的位置
    ③. 经过动画滚动到下一个位置
    注意点:须要进行判断。
    定时器的说明:
    当用户在处理其余事情的时候,定时器会中止工做。应该吧定时器添加到runloop中,告诉系统在处理其余事情的时候分一部分空间给它。
    3.添加页码控件
    4.监听collectionView的滚动,当手动触摸CollectionView,尝试拖拽的时候,把定时器停掉,当手指移开的时候,重启定时器。

  • 请简述视图控制器的生命周期。

    viewController的生命周期是:①—⑨。
    ①. initWithNib viewController会进行alloc,并init。
    ②. loadView 在这里会看它的子类是否有重写这个函数,若是重写了则调用子类的,不然就调用它本身的。 注意:这个时候视图仍是没有加载进来的。
    ③. viewDidLoad 这个时候视图已经存在了。能够在这里添加你想要添加的UI控件。
    ④. viewWillAppear 视图将出如今屏幕上。
    ⑤. viewDidAppear 视图已经成功在屏幕上渲染完成了。
    ⑥. viewWillDisappear 视图将要消失了。
    ⑦. viewDidDisappear 视图从屏幕上消失了。
    ⑧. viewDidUnLoad 当发生内存警告的时候,若是本视图不是当前正在显示的视图,则会执行这个函数。将子视图释放。
    ⑨. dealloc 释放viewController。
    而,view的生命周期则是:③—⑧。

  • 请简述iOS中的事件传递机制。(即iOS中的响应者链的工做原理)

    每个应用有一个响应者链,咱们的视图结构是一个N叉树(一个视图能够有多个子视图,一个子视图同一时刻只有一个父视图),而每个继承UIResponder的对象均可以在这个N叉树中扮演一个节点。
    当叶节点成为最高响应者的时候,从这个叶节点开始往其父节点开始追溯出一条链,那么对于这一个叶节点来说,这一条链就是当前响应者链。响应者链将系统捕获到的UIEvent与UITouch从叶节点开始层层向下分发,期间能够选择中止分发,也能够选择继续向下分发。

  • UITableView有哪些必需要实现的方法?

    必需要实现的2个数据源方法,分别是:
    1.-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section; //这个方法返回每一个分段的行数,不一样的分段返回不一样的行数能够用switch来作,若是是单个列表就直接返回单个你想要的函数便可。
    2.-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath; //这个方法返回咱们调用的每个单元格。经过咱们索引的路径的section和row来肯定。

  • 请简述HTTP协议中get请求和post请求的区别。

    get请求:参数在地址后拼接,没有请求数据,不安全(由于全部参数都拼接在地址后面),不适合传输大量数据(长度限制,为1024个字节)。get提交、请求的数据会附在URL以后,即把数据放置在HTTP协议头中。以?分割URL和传输数据,多个参数用&链接。若是数据时英文字母或数字,原样发送,若是是空格,转换为+,若是是中文/其余字符,则直接把字符串用BASE64加密。
    post请求:参数在请求数据区放着,相对get请求更安全,而且数据大小没有限制。把提交的数据放置在HTTP包的包体中。
    get提交的数据会在地址栏显示出来,而post提交,地址栏不会改变。
    传输数据的大小:
    get请求时,传输数据就会受到URL长度限制,POST因为不是经过URL传智,理论上不受限。
    安全性:
    post的安全性要比get的安全性高;
    经过get提交数据,用户名和密码将明文出如今URL上,好比登陆界面有可能被浏览器缓存。

  • 请简述你对同步/异步请求数据的理解。

    1.同步请求能够从网络请求数据,一旦发送同步请求,程序将中止与用户交互,直到服务器返回数据完成,才能够进行下一步操做;
    2.异步请求不会阻塞主线程,而会创建一个新的线程来操做,用户发出异步请求后,依然能够对UI进行操做,程序能够继续运行;

  • iOS中都有那些技术能够实现开辟线程?它们的联系和区别是什么?

    NSThread、GCD、NSOperation。
    三者抽象封装度层次从低到高,抽象封装度越高使用越简单。
    NSThread:每一个NSThread对象对应一个线程,量级较轻(真正的多线程)
    如下俩是苹果专门开发的“并发”技术,使得程序员能够再也不去关心线程的具体使用问题
    NSOperation/NSOperationQueue:面向对象的线程技术
    GCD——Grand Central Dispatch(派发):是基于C语言的框架,能够充分利用多核,是苹果推荐使用的多线程技术。
    NSThread:
    优势:比其余两种轻量级。
    缺点:须要本身管理线程的生命周期、线程同步。线程同步对数据的加锁会有必定的开销。
    Operation、GCD:
    优势:不须要关心线程管理,数据同步的事情。
    二者区别:NSOperationQueue能够方便的管理并发、NSOperation之间的优先级。GCD主要与block结合使用。代码简洁高效。
    1.性能:GCD更接近底层,而NSOperationQueue则更高级抽象,因此GCD在追求性能的底层操做来讲,是速度最快的。这取决于使用Instruments进行代码性能分析,若是有必要的话。
    2.从异步操做之间的事务性、顺序性、依赖关系。GCD须要本身写更多的代码来实现,而NSOperationQueue已经内建了这些支持。
    3.若是异步操做的过程须要更多地被交互和UI呈现出来,NSOperationQueue回事一个更好的选择。底层代码中,任务之间不太互相依赖,而须要更高的并发能力,GCD则更有优点。
    三种多线程技术的对比:
    NSThread:
    -优势:NSThread比其余两个轻量级,使用简单
    -缺点:须要本身管理线程的生命周期、线程同步、加锁、睡眠以及唤醒等。线程同步对数据的加锁会有必定的系统开销。
    NSOperation:
    -不须要关心线程管理,数据同步的事情,能够把精力放在本身须要执行的操做上
    -NSOperation是面向对象的
    GCD:
    -Grand Central Dispatch是由苹果开发的一个多核编程的解决方案。iOS4.0+才能使用,是替代NSThread,NSOperation的高效和强大的技术
    -GCD是基于C语言的。

  • NSThread中线程之间是如何实现通讯的?

    线程间通讯:在1个进程中,线程每每不是孤立存在的,多个线程之间须要常常进行通讯。
    线程间通讯的体现:1个线程传递数据给另1个线程。在1个线程中执行完特定任务后,转到另1个线程执行任务。
    线程间通讯经常使用方法:
    1.-(void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait; 该方法通常用于线程间相互通讯,即在一个线程中发送消息给另外一个线程。
    2.-(void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait; 注:每个线程都有本身的Runloop,但非主线程的Runloop默认是关闭的,当须要进行非主线程的通讯时,须要确保通讯线程的Runloop是开启的,不然发送给通讯线程的消息就不会被执行。

  • GCD中有哪些建立线程的方式?

    1.主线程队列:主线程队列,在该队列中放置的全部任务都在主线程执行
    dispatch_get_main_queue();
    2.全局并行队列:在该队列上提交的每一个任务,都会生成一个线程,并行的执行(不会等到另外一个执行完才执行)
    dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND,0);
    3.串行队列:在该队列上提交的任务,生成一个线程,在该线程上顺序执行,一个执行完后一个才能执行
    dispatch_queue_create(“”,DISPATCH_QUEUE_SERIAL);

  • iOS中有哪些技术能够保证线程安全?

    线程锁、NSLock

  • ASIHttpRequest的父类是什么?

    NSOperation

  • 请简述AFNetwork的实现原理。

    基于NSURL.采用block的方法处理请求,直接返回的是json、xml数据。AFNetwork直接操做对象是AFHTTPClient,是一个实现了NSCoding和NSCoping协议的NSObject子类。AFHTTPClient是一个封装了一系列操做方法的工具类。AFNetWorking默认没有封装同步请求,若是开发者须要使用同步请求,须要重写相关的方法getPath:parameters:failure,对AFHTTPRequestOperation进行同步处理。

  • 请简述TCP和UDP的区别。

    TCP为传输控制层协议,为面向链接、可靠的、点到点的通讯;
    UDP为用户数据报协议,非链接不可靠的点到多点的通讯;
    TCP侧重可靠传输,UDP侧重快速传输。

  • 请简述SDWebImage的实现原理。

    调用类别的方法:
    从内存中(字典)找图片(当这个图片在本次程序加载过),找到直接用;
    从沙盒中找,找到直接使用,缓存到内存。
    从网络上获取,使用,缓存到内存,缓存到沙盒。

  • 请简述线程和进程有什么联系和区别。

    一个程序至少要有一个进程,一个进程至少要有一个线程。
    进程:
    资源分配的最小独立单元,进程是具备必定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。
    线程:
    进程下的一个分支,是进程的实体,是CPU调度和分派的基本单元,它是比进程更小的能独立运行的基本单位,线程本身基本不拥有系统资源,只拥有一点在运行中必不可少的资源(程序计数器、一组寄存器、栈),可是它可与同属一个进程的其余线程共享进程所拥有的所有资源。
    进程和线程都是由操做系统所提供的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性。
    进程和线程的主要差异在于它们是不一样的操做系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其余进程产生影响,而线程只是一个进程中的不一样执行路径。线程有本身的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,因此多线程的程序要比多线程的程序健壮,但在进程切换时,耗费资源比较大,效率要差一些。
    但对于一些要求同时进行而且又要共享某些变量的并发操做,只有用线程,不能用进程。

  • 请简述什么是主键?什么是外键?

    主键是本张表的主键,是惟一且非空的,而外键是另外一张表中与这张表的某个字段的类型、字段名相同的字段,通常是用做关联两张或者两张以上的数据表时用的。
    如下面三张表为例:
    有三张表,一张表是读者信息,有一个属性为readno;一张表是图书的信息,有一个属性是bookno;一张表是借阅关系,有两个属性分别以读者信息表中的readno,和图书信息表中的bookno为外键。那么,在借阅关系表中插入数据时须要写入readno和bookno么?这样,设外键还有什么做用?
    外键取值规则:空值或参照的主键值。
    1.插入非空值时,若是主键表中没有这个值,则不能插入。
    2.更新时,不能改成主键表没有的值。
    3.删除主键表记录时,你能够在建外键时选定外键记录一块儿级联删除仍是拒绝删除。
    4.更新主键记录时,一样有级联更新和拒绝执行的选择。
    简言之:
    起约束做用,就是在借阅关系表中只能插入读者/图书信息表中存在的值,否则会出错。
    做用在于,若是你插入的readno或者bookno在两个表中没有,就会插不进去。

  • 请简述iOS的沙盒机制。(或者说,你对沙盒的理解)

    每一个iOS应用都被限制在“沙盒”中,沙盒至关于一个加了仅主人可见权限的文件夹,既是在应用程序安装过程当中,系统为每一个单独的应用程序生成它的主目录和一些关键的子目录。
    苹果对沙盒有几条限制:
    1.应用程序在本身的沙盒中运做,可是不能访问任何其余应用程序沙盒;
    2.应用之间不能共享数据,沙盒里的文件不能被复制到其余应用程序的文件夹中,也不能把其余应用文件夹复制到沙盒中;
    3.苹果禁止任何读写沙盒之外的文件,禁止应用程序将内容写到沙盒之外的文件夹中;
    4.沙盒目录里面有三个文件夹:Documents——存储;应用程序的数据文件,存储用户数据或其余按期备份的信息;Library下有两个文件夹,Caches存储应用程序再次启动所需的信息,Preferences包含应用程序的偏好设置;temp存放临时文件即应用程序再次启动不须要的文件。
    获取沙河根目录的方法,有几种方法:用NSHomeDirectory获取。
    获取Document路径:
    NSSearchPathForDirectotiesInDomains(NSDocumentDirectory,NSUserDomainMask,YES)

  • 如何实现真机调试?

    (Xcode 7.0以后能够不用配置开发者证书直接进行真机测试。)
    1.首先须要用钥匙串建立一个钥匙(key);
    2.将钥匙串上传到官网,获取iOS Development证书;
    3.建立App ID即咱们应用程序中的Boundle ID;
    4.添加Device ID即UDID;
    5.经过勾选前面所建立的证书:Apple ID、Device ID;
    6.生成mobileprovision文件;
    7.先决条件:申请开发者帐号99美刀。

  • 如何查找项目中的内存泄漏?

    使用内存分析工具:
    1、静态分析(不用运行程序时就能分析)
    使用Analyze工具:在Xcode菜单栏中,点击Product-->Alalyze以后,Xcode就会帮你编译一次,而且找出你工程中有缺陷的代码,这个工具在当年非ARC的时候,很是火,只是如今的做用鸡毛蒜皮了。分析内存泄漏shift+command+b。
    2、动态分析(运行程序时分析)
    静态有时候不能把全部的内存泄漏检查出来,有的内存泄漏是在运行时,用户操做时才产生的。那就须要用到Instruments了。
    Instruments工具操做流程:在Xcode菜单栏中,点击Product-->Profile-->build成功后跳出Instruments工具-->选择Leaks选项-->choose-->选择要检测的app-->点击红色按钮开始运行,进行检查。
    程序跑起来以后,能够开始各类点击调试试用。
    红色的圆圈里的菱形表示内存泄漏了。
    如何经过Instruments这个工具看到在哪出现内存泄漏了?
    如今工具栏按下暂停按钮,把工具监视内存的活动停下来。
    选择Leak Checks,而后选择Call Tree(Details后面的那个选项)
    选中右边栏,中间的按钮,选中中间的两项,而后会在中间的地方显示内存泄漏的地方,双击就能够跳转到对应的代码。最后解决内存泄漏问题。

  • 项目中的支付环节如何实现的?

    1.先与支付宝签约,得到商户ID(partner)和帐号(seller);
    2.下载相应的公钥私钥文件(加密签名用);
    3.下载支付宝SDK;
    4.生成订单信息;
    5.调用支付宝客户端,由支付宝客户端跟支付宝安全服务器打交道;
    6.支付完毕后返回支付结果给商户客户端和服务,SDK里有集成支付宝功能的一个Demo,集成支付功能的具体操做方式,能够参考Demo。
    //生成订单信息及签名请求参数没有return_URL这个参数,商户能够根据自身状况选择签名方法 //点击获取product实例,并初始化订单信息 //订单ID //商品标题 //商品描述 //商品价格 //回调URL

  • 如何实现项目上线到AppStore?

    1.登陆应用发布网站添加应用信息;
    2.下载安装发布证书;
    3.选择发布证书,使用Archive编译发布包,用Xcode将代码(发布包)上传到服务器;
    4.等待审核经过;
    5.生成IPA:菜单栏-->Product-->Archive。

  • 请简述你在项目中遇到过哪些问题,如何解决的?

    举个当初本身在项目中解决接口问题的例子:
    当时,拿着提供的接口,在浏览器中用JSON解析的工具看数据,没有任何问题。可是,放到工程中解析,第一次运行,没问题,是最新的数据。如果,稍等半天,再去刷新,依旧是第一次运行时的数据。可是,浏览器打开接口,倒是最新的数据。后来,不管是打印,仍是打断点,一直找不到问题所在。
    我就尝试开始从接口的拼接中找问题。后来发现拼接中的一个数字若是是不断变化的话,就会显示出最新的数据。而后,就在接口的拼接过程当中,将那个固定数字修改成随着点击而随机产生的数字。刚开始觉得,能解决问题,后来发现,刷新到必定次数后,就会出现依旧仍是旧数据的问题。只好再做调整。就给数字以逐渐累加的形式,来变化不一样的数字。如此,作尝试,却发现,每次变化范围过小,依旧会出现数据不更新的状况。后来,最终肯定一个大范围值,才解决了数据不更新的问题。

  • 如何实现流媒体格式的视频边播边放边缓存?

    视频播放器处理流程:
    1.当开始播放视频时,经过视频url判断本地cache中是否已经缓存当前视频;若是有,则直接播放本地cache中视频;
    2.若是本地cache中没有视频,则视频播放器向代理请求数据;
    3.加载视频时展现正在加载的提示(动画:如旋转的小菊花);
    4.若是能够正常播放视频,则去掉加载提示,播放视频;若是加载失败,去掉加载提示并显示失败提示;
    5.在播放过程当中若是因为网络国漫或拖拽缘由致使没有播放数据时,要展现加载提示,跳转到第4步;
    代理对象处理流程:
    1.当视频播放器向代理请求dataRequest时,判断代理是否已经向服务器发起了请求,若是没有,则发起下载整个视频文件的请求;
    2.若是代理已经和服务器创建链接,则判断当前的dataRequest请求的offset是否大于当前已经缓存的文件的offset;若是大于,则取消当前与服务器的请求,并从offset开始到文件尾向服务器发起请求(此时应该是因为播放器向后拖拽,而且超过了已缓存的数据时才会出现);
    3.若是当前的dataRequest请求的offset小于已经缓存的文件的offset,同事大于代理向服务器请求的range的offset,说明有一部分已经缓存的数据能够传给播放器,则将这部分数据返回给播放器(此时应该是因为播放器向前拖拽,请求的数据已经缓存过才会出现);
    4.若是当前的dataRequest请求的offset小于代理向服务器请求的range的offset,则取消当前与服务器的请求,并从offset开始到文件尾向服务器发起请求(此时应该是因为播放器向前拖拽,而且超过了已缓存的数据时才会出现);
    5.只要代理从新想服务器发起请求,就会致使缓存的数据不连续,则加载结束后不用将缓存的数据放入到本地cache;
    6.若是代理和服务器的连接超时,重试一次。若是仍是错误,则通知播放器网络错误;
    7.若是服务器返回其它错误,则代理通知播放器网络错误;

  • 请简述xml和json数据各有哪些优点?分析json、xml的区别。json、xml解析方式的底层是如何处理的?

    json:键值对,数据小,不复杂,便于解析,有框架支持,适合轻量级传输,做为数据包个数传输的时候效率更高;
    xml:标签套内容,xml数据比较大,比较复杂,适合大数据量的传输,xml有丰富的编码工具,好比:Dom4j,JDom.解析方式有两种,一是经过文芳模型解析,另一种遍历节点。
    区别:

    (1)可读性方面:基本相同,xml的可读性比较好

    (2)可扩展性方面:都具备很好的扩展性

    (3)编码难度方面:相对而言:JSON的编码比较容易
    (4)解码难度:json的解码难度基本为零,xml须要考虑子节点和父节点
    (5)数据体积方面:json相对于xml来说,数据体积小,传递的速度跟快些
    (6)数据交互方面:json与JavaScript的交互更加方面,更容易解析处理,更好的数据交互
    (7)数据描述方面:xml对数据描述性比较好

    (8)传输速度方面:json的速度远远快于xml
    JSON底层原理:
    遍历字符串中的字符,最终根据格式规定的特殊字符,好比{}号,[]号, : 号 等进行区分,{}号是一个字典 的开始,[]号是一个数组的开始, : 号是字典的键和值的分水岭,最终乃是将json数据转化为字典,字典中值多是字典,数 组,或字符串而已。

    XML底层原理:
    XML解析经常使用的解析方法有两种:DOM解析和SAX解析。DOM 采用创建树形结构的方式访问 XML 文档,而 SAX 采用的事件模型。 。DOM 解析把 XML 文档转化为一个包含其内容的树,并能够对树进行遍历。使用 DOM 解析器的时候需 要处理整个 XML 文档,因此对性能和内存的要求比较高。SAX在解析 XML 文档的时候能够触发一系列的事件,当发现给定的tag 的时候,它能够激活一个回调方法,告诉该方法制定的标签已经找到。SAX 对内存的要求一般会比较低,由于它让开发人员本身来决 定所要处理的tag。特别是当开发人员只须要处理文档中所包含的部分数据时,SAX 这种扩展能力获得了更好的体现。
    延伸:
    SAX与DOM的区别:
    一、SAX处理的优势很是相似于流媒体的优势。分析可以当即开始,而不是等待全部的数据被处理。并且因为应用程序只是 在读取数据时检查数据,所以不须要将数据存储在内存中。这对于大型文档来讲是个巨大的优势。事实上,应用程序甚至不 必解析整个文档;它能够在某个条件获得 知足时中止解析。通常来讲,SAX 还比它的替代者 DOM 快许多。另外一方面,由 于应用程序没有以任何方式存储数据,使用 SAX 来更改数据或在数据流中日后移是不可能的。
二、DOM 以及广义的基于树的处理具备几个优势。首先,因为树在内存中是持久的,所以能够修改它以便应用程序能对数 据和结构做出更改。它还能够在任什么时候候在树中上下 导航,而不是像 SAX 那样是一次性的处理。DOM 使用起来也要简单 得多。另外一方面,在内存中构造这样的树涉及大量的开销。大型文件彻底占用系统内存容量的状况并不鲜见。此外,建立一 棵 DOM 树多是一个缓慢的过程。
三、选择 DOM 仍是选择 SAX,这取决于下面几个因素:
应用程序的目的:若是打算对数据做出更改并将它输出为 XML,那么在大多数状况下,DOM 是适当的选择。并非说使 用 SAX 就不能更改数据,可是该过程要复杂得多,由于您必须对数据的一份拷贝而不是对数据自己做出更改。
数据容量: 对于大型文件,SAX 是更好的选择。数据将如何使用:若是只有数据中的少许部分会被使用,那么使用 SAX 来将该部分数据提取到应用程序中可能更好。 另外一方面,若是您知道本身之后会回头引用已处理过的大量信息,那么 SAX 也许不是恰当的选择。
对速度的须要:SAX 实现一般要比 DOM 实现更快。
SAX 和 DOM 不是相互排斥的,记住这点很重要。您可使用 DOM 来建立 SAX 事件流,也可使用 SAX 来建立 DOM 树。事实上,用于建立 DOM 树的大多数解析器实际上都使用 SAX 来完成这个任务。
相关文章
相关标签/搜索