iOS面试整理

协议:

Protocols Define Messaging Contracts

A class interface declares the methods and properties associated with that class. A protocol, by contrast, is used to declare methods and properties that are independent of any specific class.

译:协议用来定义 消息契约 (暂且这么翻译)

一个类接口声明与类相关的方法和属性。一个协议,相比之下,用于声明的方法和属性是独立于任何特定的类。


总结一下:

(1)协议相当于没有与类相关联的接口(网上也有说 协议是一个方法签名的列表注释1),他申明一组方法,列出他的参数和返回值,共享给其他类使用,然后不进行实现,让用它的类来实现这些方法

(2)在任何一个类中,只要声明了协议,都可以实现协议里的方法。

(3)协议不是一个类,且独立于任何特定的类。

(4)@protocol关键字声明一个协议

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

Cocoa采用了引用计数(reference 

counting)机制,每一个对象有一个关联的整数retainCount”用于记录对象的使用情况。对象被引用时retaincount+1,外部

环境结束对象的使用后retainCount-1.retaincount0的时候,该对象被销毁。

        当我们使用allocnew或者copy的我们需要销毁这个对象。release函数,只是将对象的retainCount值减1,并不是删除对象。当retainCount==0的时候,系统会发给对象一个dealloc消息,另外:千万不要手动调用dealloc,因为我们不知道何时,何地,何人还会使用该对象。应该老老实实依赖引用计数机制完成内存管理

        释放对象所有权的函数除了release还有autorelease,这是一种延迟操作。


iOS 中调用 self.name= _name="" 的区别

self.name= yang”name= “yang”的关系

self.name 表示调用 setter 调用一个函数   这个表示调用setter函数

name=”year”表示给字段 field 赋值   这个表示只是给变量赋值

1 类别(category)和继承的区别?

*类别:类别是对一个功能完备的类的一种补充,就像是一个东西的主要基本功能都完成了,可以用类别为这个类添加不同的组件,使得这个类能够适应不同情况的需求。比如animal这个类,具有eatrun等方法,想给这个类添加一个bark的方法,可以用类别。


*继承:多个类具有相同的实例变量和方法时,考虑用继承。即子类可以继承父类的相同特性。如animal具有年龄和体重两个属性,dog也具有年龄和体重两 个属性,dog可以继承animal的这两个属性,即为继承。


共同点:都是给一个类进行扩展


区别:1.类别是对方法的扩展,不能添加成员变量。继承可以在原来父类的成员变量的基础上,添加新的成员变量

      2.类别只能添加新的方法,不能修改和删除原来的方法。继承可以增加、修改和删除方法。

      3.类别不提倡对原有的方法进行重载。继承可以通过使用super对原来方法进行重载。

      4.类别可以被继承,如果一个父类中定义了类别,那么其子类中也会继承此类别。

strong和weak的区别

weakstrong)不同的是 当一个对象不再有strong类型的指针指向它的时候 它会被释放 ,即使还有weak型指针指向它。

  一旦最后一个strong型指针离去 ,这个对象将被释放,所有剩余的weak型指针都将被清除。

  可能有个例子形容是妥当的。

  想象我们的对象是一条狗,狗想要跑掉(被释放)。

  strong型指针就像是栓住的狗。只要你用牵绳挂住狗,狗就不会跑掉。如果有5个人牵着一条狗(5strong型指针指向1个对象),除非5个牵绳都脱落 ,否着狗是不会跑掉的。

  weak型指针就像是一个小孩指着狗喊到:看!一只狗在那只要狗一直被栓着,小孩就能看到狗,(weak指针)会一直指向它。只要狗的牵绳脱落,狗就会跑掉,不管有多少小孩在看着它。

  只要最后一个strong型指针不再指向对象,那么对象就会被释放,同时所有的weak型指针都将会被清除。 


如何实现ARCMRC的混编

 OS5.0以后就开始可以使用ARC Automatic Reference Counting:自动引用计数 )来代替之前的MRCManual Reference Counting:人工引用计数)。使用ARC会减少很多代码和忘了释放对象的苦恼。但是事情都有两面性。使用了ARC之后如果你想复用以前写过的使用MRC的类, 就会出报错。这时候怎么办?方法比较简单, 只需要做下面的一个步骤就可以解决:


  在targetsbuild phases选项下Compile Sources下选择要不使用arc编译的文件,双击它,输入 -fno-objc-arc 即可

  


  MRC工程中也可以使用ARC的类。方法如下:


  在targetsbuild phases选项下Compile Sources下选择要使用arc编译的文件,双击它,输入 -fobjc-arc 即可


oc不支持多继承,怎么办

什么是Category

Category模式用于向已经存在的类添加方法从而达到扩展已有类的目的,在很多情形下Category也是比创建子类更优的选择。新添加的方法 同样也会被被扩展的类的所有子类自动继承。当知道已有类中某个方法有BUG,但是这个类是以库的形式存在的,我们无法直接修改源代码的时 候,Category也可以用于替代这个已有类中某个方法的实体,从而达到修复BUG的目的。然而却没有什么便捷的途径可以去调用已有类中原有的那个被替 换掉方法实体了。需要注意的是,当准备有Category来替换某一个方法的时候,一定要保证实现原来方法的所有功能,否则这种替代就是没有意义而且会引 起新的BUG。和子类不同的是,Category不能用于向被扩展类添加实例变量。Category通常作为一种组织框架代码的工具来使用。

Category的用途

1.      在不创建继承类的情况下实现对已有类的扩展。

2.      简化类的开发工作(当一个类需要多个程序员协同开发的时候,Category可以将同一个类根据用途分别放在不同的源文件中,从而便于程序员独立开发相应的方法集合)。

3.      将常用的相关的方法分组。

4.      在没有源代码的情况下可以用来修复BUG

Category的用法

Obj-C中,声明某一个已有类的Category扩展的方法如下:


[html] view plaincopy


  1. @interface ClassName (CategoryName)  
  2. -methodName1  
  3. -methodName2  
  4. @end  


上面的声明通常是在.h文件中,然后我们在.m文件中实现这些方法:


[html] view plaincopy


  1. @implementation ClassName (CategoryName)  
  2. -methodName1  
  3. -methodName2  
  4. @end  


我们创建一个iOS Single View Applciation名为CategoryExample。然后为创建一个NSString类的category扩展。 File->New->File然后选择 Cocoa Touch Objective-C category.命名为ReverseNSString.系统会自动生成一个固定格式ClassName+CategoryName.h.m文件。

声明Category

打开NSString+ReverseNSString.h文件,在里面添加如下代码:

[html] view plaincopy


  1. #import   
  2. @interface NSString (ReverseNSString)  
  3. + (NSString*) reverseString:(NSString*)strSrc;  
  4. @end  

实现Category

NSString+ReverseNSString.m文件中实现reverseString方法

objective c中有私有方法和私有变量吗

objective c中既有私有方法,也有私有变量。

先说私有方法,
由于Objective-C动态消息传递机制,OC中不存在真正意义上的私有方法。
但是如果你不在.h文件中声明,只在.m文件中实现,或在.m文件的Class Extension里声明,那么基本上和私有方法差不多。

#import@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中声明的类进来.


传值的方式:

属性传值,代理传值,单例传值,通知传值,Block传值

(一)属性传值 

第二个界面中的lable显示第一个界面textField中的文本

首先我们建立一个RootViewControllers和一个DetailViewControllers,在DetailViewControllers中声明一个textString属性,用于接收传过来的字符串,

(二)Block传值

block传值也是从第二个界面给第一个界面传值

(三)代理传值

RootViewControllers页面pushDetailViewControllers页面,如果 DetailViewControllers页面的信息想回传(回调)到RootViewControllers页面,用代理传值,其中 DetailViewControllers定义协议和声明代理,RootViewControllers确认并实现代 理,RootViewControllers作为DetailViewControllers的代理

(四)单例传值

单例传值(实现共享)

AppStatus.h  创建一个单例类 AppStatus

(五)通知传值

谁要监听值的变化,谁就注册通知  特别要注意,通知的接受者必须存在这一先决条件

iOS页面间传值的方式(NSUserDefault/Delegate/NSNotification/Block/单例)

实现了以下iOS页面间传值:1.委托delegate方式;2.通知notification方式;3.block方式;4.UserDefault或者文件方式;5.单例模式方式;6.通过设置属性,实现页面间传值

iOS 深浅拷贝

深拷贝 ,alloc一个新的地址返回,为它赋值,

浅拷贝,并不创建新的内存空间,直接把原地址返回


ios系统中有哪些对象是单例

iOS系统的单例类:

UIApplication(应用程序实例

NSNotificationCenter(消息中心):     

NSFileManager(文件管理):    

NSUserDefaults(应用程序设置):     

NSURLCache(请求缓存)   

NSHTTPCookieStorage(应用程序cookies): 


简述mvc模式

MVC是一种使用 MVCModel View Controller 模型-视图-控制器)设计创建 Web 应用程序的模式:

Model(模型)表示应用程序核心(比如数据库记录列表)。

View(视图)显示数据(数据库记录)。

Controller(控制器)处理输入(写入数据库记录)。

MVC 模式同时提供了对 HTMLCSS  JavaScript 的完全控制。

Model(模型)是应用程序中用于处理应用程序数据逻辑的部分。

通常模型对象负责在数据库中存取数据。

View(视图)是应用程序中处理数据显示的部分。

通常视图是依据模型数据创建的。

Controller(控制器)是应用程序中处理用户交互的部分。

通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据。

MVC 分层有助于管理复杂的应用程序,因为您可以在一个时间内专门关注一个方面。例如,您可以在不依赖业务逻辑的情况下专注于视图设计。同时也让应用程序的测试更加容易。

MVC 分层同时也简化了分组开发。不同的开发人员可同时开发视图、控制器逻辑和业务逻辑


ios中哪些技术符合观察者模式

而在IOS开发中我们可能会接触到的经典观察者模式的实现方式,有这么几种:NSNotificationCenterKVODelegate


工厂模式简述 

工厂模式的特点其实也是将抽象操作和具体类型隔离,将抽象操作放在基类,具体类型放在子类。例如我们定义一个汽车组装类,每种汽车都有 组装流程,但是我们可以抽象出一系列操作,例如冲压外壳,喷漆,安装发动机,安装内饰等。这些操作可以对应于一个抽象的汽车类,这样就可以把全部的抽象放 在两个基类里面:装配类和汽车类。 然后在实现的时候可以定义具体的汽车型号。例如设计了一款家用的MPV车,就继承自抽象汽车类,然后实现一个MPV组装类,继承自汽车组装类,在里面 new一个MPV车实例,而汽车组装的过程因为各个车都是一致的,所以不用实现了,就通过基类的一系列操作实现即可。 


Objective-c 代理模式(delegate


  一、什么事代理模式?

        代理模式是在oc中经常遇到的一种设计模式,那什么叫做代理模式呢? 举个例子:有一个婴儿,他本身不会自己吃饭和洗澡等等一些事情,于是婴儿就请了一个保姆,于是婴儿和保姆之间商定了一个协议,协议中写明了保姆需要做什么事情, 而保姆就是这个代理人,  即:婴儿和保姆之间有个协议,保姆继承该协议,于是保姆就需要实现该协议中的条款成为代理人。


二、 代理模式的关键点:

     A完成一件事,但是自己不能完成,于是他找个代理人B 替他完成这个事情,他们之间便有个协议 protocol),B继承该协议来完成A代理给他的事情。 



storyboardxib的区别

xibstoryboard的比较,一个轻量级一个重量级。

共同点:

都用来描述软件界面

都用Interface Builder工具来编辑

不同点:

Xib是轻量级的,用来描述局部的UI界面

Storyboard是重量级的,用来描述整个软件的多个界面,并且能展示多个界面之间的跳转关系 


简述uitableViewCell的重用机制

TableView的重用机制,为了做到显示和数据分离,IOS tableView的实现并且不是为每个数据项创建一个tableCell。而是只创建屏幕可显示最大个数的cell,然后重复使用这些cell,对 cell做单独的显示配置,来达到既不影响显示效果,又能充分节约内容的目的。下面简要分析一下它的实现原理。

重用实现分析:

  查看UITableView头文件,会找到NSMutableArray*  visiableCells,和NSMutableDictnery* reusableTableCells两个结构。visiableCells内保存当前显示的cellsreusableTableCells保存可重 用的cells

  TableView显示之初,reusableTableCells为空,那么tableView dequeueReusableCellWithIdentifier:CellIdentifier返回nil。开始的cell都是通过 [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]来创建,而且cellForRowAtIndexPath只是调用最大显示cell数的 次数。

  比如:有100条数据,iPhone一屏最多显示10cell。程序最开始显示TableView的情况是:

  1. [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]创建10cell,并给cell指定同样的重用标识(当然,可以为不同显示类型的 cell指定不同的标识)。并且10cell全部都加入到visiableCells数组,reusableTableCells为空。

  2. 向下拖动tableView,当cell1完全移出屏幕,并且cell11(它也是alloc出来的,原因同上)完全显示出来的时候。cell11加入到 visiableCellscell1移出visiableCellscell1加入到reusableTableCells

  3. 接着向下拖动tableView,因为reusableTableCells中已经有值,所以,当需要显示新的 cellcellForRowAtIndexPath再次被调用的时候,tableView dequeueReusableCellWithIdentifier:CellIdentifier,返回cell1cell1加入到 visiableCellscell1移出reusableTableCellscell2移出visiableCellscell2加入到 reusableTableCells。之后再需要显示的Cell就可以正常重用了。

  所以整个过程并不难理解,但需要注意正是因为这样的原因:配置Cell的时候一定要注意,对取出的重用的cell做重新赋值,不要遗留老数据。


阐述下UIViewController生命周期函数

第一步 alloc init创建

第二步 需要把界面显示到屏幕上的时候 

第1  loadView 

第2  ViewDidLoad

第3  viewWillAppear(显示)

第4   viewDidAppear

从下一次再显示同一个那么只执行

第1  viewWillAppear

第2   viewDidAppear

第三步 界面离开屏幕的时候

第1  viewWillDisAppear(消失)

第2   viewDidDisAppear


如何优化UITableView的性能

  1. 使用不透明视图。     不透明的视图可以极大地提高渲染的速度。因此如非必要,可以将table cell及其子视图的opaque属性设为YES(默认值)。其中的特例包括背景色,它的alpha值应该为1(例如不要使用clearColor);图像的alpha值也应该为1,或者在画图时设为不透明。
  2. 不要重复创建不必要的table cell。     前面说了,UITableView只需要一屏幕的UITableViewCell对象即可。因此在cell不可见时,可以将其缓存起来,而在需要时继续使用它即可。而UITableView也提供了这种机制,只需要简单地设置一个identifier即可:


static NSString *CellIdentifier = @"xxx";

UITableViewCell *cell = [tableViewdequeueReusableCellWithIdentifier:CellIdentifier];

if (cell == nil) {

    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];

}

值得一提的是,cell被重用时,它内部绘制的内容并不会被自动清除,因此你可能需要调用setNeedsDisplayInRect:或setNeedsDisplay方法。此 外,在添加table cell的时候,如果不需要动画效果,最好不要使用insertRowsAtIndexPaths:withRowAnimation:方法,而是直接调 用reloadData方法。因为前者会对所有indexPaths调用tableView:cellForRowAtIndexPath:方法,即便该 cell并不需要显示(不知道是不是bug),这就可能创建大量多余的cell。勘误:只是在模拟器上测试如此,真机调试时没有这种bug

3.减少视图的数目。

     UITableViewCell包含了textLabel、detailTextLabel和imageView等view,而你还可以自定义一些视图放在它的contentView里。然而view是很大的对象,创建它会消耗较多资源,并且也影响渲染的性能。如果你的table cell包含图片,且数目较多,使用默认的UITableViewCell会非常影响性能。奇怪的是,使用自定义的view,而非预定义的view,明显会快些。当然,最佳的解决办法还是继承UITableViewCell,并在其drawRect:中自行绘制:

- (void)drawRect:(CGRect)rect {

    if (image) {

        [image drawAtPoint:imagePoint];

        self.image =nil;

    } else {

        [placeHolder drawAtPoint:imagePoint];

    }

    

    [text drawInRect:textRect withFont:font lineBreakMode:UILineBreakModeTailTruncation];

}

      不过这样一来,你会发现选中一行后,这个cell就变蓝了,其中的内容就被挡住了。最简单的方法就是将cell的selectionStyle属性设为UITableViewCellSelectionStyleNone,这样就不会被高亮了。此 外还可以创建CALayer,将内容绘制到layer上,然后对cell的contentView.layer调用addSublayer:方法。这个例 子中,layer并不会显著影响性能,但如果layer透明,或者有圆角、变形等效果,就会影响到绘制速度了。解决办法可参见后面的预渲染图像。

4.不要做多余的绘制工作。

     在实现drawRect:的时候,它的rect参数就是需要绘制的区域,这个区域之外的不需要进行绘制。例如上例中,就可以用CGRectIntersectsRect、CGRectIntersection或CGRectContainsRect判断是否需要绘制image和text,然后再调用绘制方法。

5.预渲染图像。

     你会发现即使做到了上述几点,当新的图像出现时,仍然会有短暂的停顿现象。解决的办法就是在bitmap context里先将其画一遍,导出成UIImage对象,然后再绘制到屏幕,详细做法可见《利用预渲染加速iOS设备的图像显示》。

6.不要阻塞主线程。

     做到前几点后,你的table view滚动时应该足够流畅了,不过你仍可能让用户感到不爽。常见的现象就是在更新数据时,整个界面卡住不动,完全不响应用户请求。出现这种现象的原因就是主线程执行了耗时很长的函数或方法,在其执行完毕前,无法绘制屏幕和响应用户请求。其中最常见的就是网络请求了,它通常都需要花费数秒的时间,而你不应该让用户等待那么久。解 决办法就是使用多线程,让子线程去执行这些函数或方法。这里面还有一个学问,当下载线程数超过2时,会显著影响主线程的性能。因此在使用 ASIHTTPRequest时,可以用一个NSOperationQueue来维护下载请求,并将其 maxConcurrentOperationCount设为2。而NSURLRequest则可以配合GCD来实现,或者使用NSURLConnection的setDelegateQueue:方法。当然,在不需要响应用户请求时,也可以增加下载线程数,以加快下载速度:

-(void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {

    if (!decelerate) {

        queue.maxConcurrentOperationCount =5;

    }

}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {

    queue.maxConcurrentOperationCount =5;

}

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {

    queue.maxConcurrentOperationCount =2;

}

此外,自动载入更新数据对用户来说也很友好,这减少了用户等待下载的时间。例如每次载入50条信息,那就可以在滚动到倒数第10条以内时,加载更多信息:


- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {

    if (count - indexPath.row <10 && !updating) {

        updating = YES;

        [self update];

    }

}

// update方法获取到结果后,设置updating为NO

还有一点要注意的就是当图片下载完成后,如果cell是可见的,还需要更新图像:


NSArray *indexPaths = [self.tableView indexPathsForVisibleRows];

for (NSIndexPath *visibleIndexPathin indexPaths) {

    if (indexPath == visibleIndexPath) {

        MyTableViewCell *cell = (MyTableViewCell *)[self.tableView cellForRowAtIndexPath:indexPath];

        cell.image = image;

        [cell setNeedsDisplayInRect:imageRect];

        break;

    }

}


简述IOS的事件传递机制

iOS中事件传递首先从App(UIApplication)开始,接着传递到Window(UIWindow),在接着往下传递到View 前,Window会将事件交给GestureRecognizer,如果在此期间,GestureRecognizer识别了传递过来的事件,则该事件将 不会继续传递到View去,而是像我们之前说的那样交给Target(ViewController)进行处理。



UITableView常用的数据源方法和委托方法

返回脚本百事通

表视图继承自UIScrollView,这样的继承关系使得表视图可以实现上、下滚动。
UITableViewDatasource
:实例化表视图时,必须采用该方法来实现数据源的配置
UITableViewDelegate
:表视图的委托方法,一般用于处理表视图的基本样式以及捕捉选中单元格选中事件

表视图的结构:

表视图由头部、尾部视图,中间有一连串的单元格视图

表视图的头部由tableHeaderView属性设置,尾部视图通过tableFooterView属性设置

分组表格由一系列的section视图组成,每一个section又包含一个连续的单元格

每个section视图也由头部视图和尾部视图,通过委托方法代理

cell的使用:

首先定义一个标示符

其次,检查表视图中是否存在闲置的单元格,如果有取出来,没有则重新创建

第一、UITableViewDatasource 相关的方法

添加数据源的方法


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section; // 获得section包含的cell个数

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;  // Default is 1 if not implemented

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section;    // fixed font style. use custom view (UILabel) if you want something different


- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section;


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

{

    return [self.arrayList count];

}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

{

    NSLog(@"the section is %d",indexPath.section);

    

   static NSString *idendifier=@"cellIdentify";

    UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:idendifier];

    if (!cell) {

        cell=[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:idendifier];

    }

    cell.textLabel.text=[self.arrayList objectAtIndex:indexPath.row];

    return cell;

}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView

{

    return 1;

}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section

{

  return @"andy";

}

- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section

{

 return @"richard";

}



表视图的编辑、移动、删除等:



- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath;

- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath;

- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView;                                                 - (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index; // tell table which section corresponds to section title/index (e.g. "B",1))

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath;


- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath;

第二、UITableViewDelegate相关的方法


// Called before the user changes the selection. Return a new indexPath, or nil, to change the proposed selection.

- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath;

- (NSIndexPath *)tableView:(UITableView *)tableView willDeselectRowAtIndexPath:(NSIndexPath *)indexPathNS_AVAILABLE_IOS(3_0);

// Called after the user changes the selection.

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;

- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath

sample:


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

{

    DetailViewController *detailVC=[[[DetailViewController alloc] init] autorelease];

    [self.navigationController pushViewController:detailVC animated:YES];

    NSLog(@"clicked");

}



- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section;

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section;

sampleCode:


- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

{

  if(indexPath.row==1)

  {

      return 100;

  }else

  {

      return 50;

  }

}

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section

{

    return 50;

}

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section

{

    return 60;

}


- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section;   // custom view for header. will be adjusted to default or specified header height

- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section;   

sample code 



- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section

{

    UIView *headerView=[[[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 40)] autorelease];

    headerView.backgroundColor=[UIColor yellowColor];

    

    UILabel *label=[[[UILabel alloc] initWithFrame:CGRectMake(20, 20, 300, 30)] autorelease];

    label.text=@"header";

    [headerView addSubview:label];

    return headerView;

}

- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section

{

    UIView *headerView=[[[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 40)] autorelease];

    headerView.backgroundColor=[UIColor redColor];

    

    UILabel *label=[[[UILabel alloc] initWithFrame:CGRectMake(20, 20, 300, 30)] autorelease];

    label.text=@"foot";

    [headerView addSubview:label];

    return headerView;


}




HTTP协议中请求方法GetPost的区别是什么?

Get:是以实体的方式得到由请求URI所指定资源的信息,如果请求URI只是一个数据产生过程,那么最终要在响应实体中返回的是处理过程的结果所指向的资源,而不是处理过程的描述。


Post:用来向目的服务器发出请求,要求它接受被附在请求后的实体,并把它当作请求队列中请求URI所指定资源的附加新子项,Post被设计成用统一的方法实现下列功能:

1:对现有资源的解释

2:向电子公告栏新闻组、邮件列表或类似讨论组发信息。

3:提交数据块

4:通过附加操作来扩展数据库


从上面描述可以看出,Get是向服务器发索取数据的一种请求;而Post是向服务器提交数据的一种请求,要提交的数据位于信息头后面的实体中。




同步请求和异步请求的区别

 

先解释一下同步和异步的概念

同步是指:发送方发出数据后,等接收方发回响应以后才发下一个数据包的通讯方式。  
异步是指:发送方发出数据后,不等接收方发回响应,接着发送下个数据包的通讯方式。

 

同步通信方式与异步通信的概念

同步通信方式要求通信双方以相同的时钟频率进行,而且准确协调,通过共享一个单个时钟或定时脉冲源保证发送方和接收方的准确同步,效率较高;
异步通信方式不要求双方同步,收发方可采用各自的时钟源,双方遵循异步的通信协议,以字符为数据传输单位,发送方传送字符的时间间隔不确定,发送效率比同步传送效率低。

 

使用者用于调用WEB服务的通信选择:同步或异步。

使用者可以同步或异步实现服务调用。从使用者的观点来看,这两种方式的不同之处在于:

  • 同步——使用者通过单个线程调用服务;该线程发送请求,在服务运行时阻塞,并且等待响应。
  • 异步——使用者通过两个线程调用服务;一个线程发送请求,而另一个单独的线程接收响应。

术语同步 和异步 经常与顺序 和并发 混淆了。后面的这两个术语与执行单独的任务必须遵循的顺序有关,而同步和异步 与线程执行单个任务(如调用单个服务)的方式有关。理解同步和异步调用之间的不同的一种很好的方法是考虑崩溃恢复的后果:

  • 同步——如果使用者在服务运行的过程中阻塞时崩溃了,当它重新启动时,将无法重新连接到正在进行的调用,所以响应丢失了。使用者必须重复调用过程,并且期望这次不会崩溃。
  • 异步——如果使用者在发送了请求之后等待响应时崩溃了,当它重新启动时,可以继续等待响应,所以响应不会丢失。



1.iOS的三种多线程技术                    

1.NSThread 每个NSThread对象对应一个线程,量级较轻(真正的多线程)

2.以下两点是苹果专门开发的并发技术,使得程序员可以不再去关心线程的具体使用问题

ØNSOperation/NSOperationQueue 面向对象的线程技术

ØGCD —— Grand Central Dispatch(派发) 是基于C语言的框架,可以充分利用多核,是苹果推荐使用的多线程技术

 

以上这三种编程方式从上到下,抽象度层次是从低到高的,抽象度越高的使用越简单,也是Apple最推荐使用的,在项目中很多框架技术分别使用了不同多线程技术。

 

2.三种多线程技术的对比                     

•NSThread:

优点:NSThread 比其他两个轻量级,使用简单

缺点:需要自己管理线程的生命周期、线程同步、加锁、睡眠以及唤醒等。线程同步对数据的加锁会有一定的系统开销

 

•NSOperation

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

–NSOperation是面向对象的

 

•GCD

–Grand Central Dispatch是由苹果开发的一个多核编程的解决方案iOS4.0+才能使用,是替代NSThread NSOperation的高效和强大的技术



#import "ViewController.h"


@interface ViewController ()

@property (weak, nonatomic) IBOutlet UIImageView *imageView;


@end


@implementation ViewController


- (void)viewDidLoad {

    [super viewDidLoad];

}


- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event

{

    // 开启一条子线程,在子线程中,控制器将会执行download方法。

    [self performSelectorInBackground:@selector(download) withObject:nil];

}


- (void)download

{

    NSURL *url = [NSURL URLWithString:@"http://img.redocn.com/200906/2/321782_124390997641aY.jpg"];

    NSLog(@"-------begin");

    NSData *data = [NSData dataWithContentsOfURL:url]; // 这行会比较耗时

    NSLog(@"-------end");

    UIImage *image = [UIImage imageWithData:data];

    [self.imageView performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:NO];

    // 注意上面这句代码,是回到主线程,然后imageView执行perfom方法,imageView执行setImage方法。waitUntilDone:NO是指不等待setImage方法执行完毕。

    // 假如setImage方法耗时一秒钟,waitUntilDone设为YES的情况下,下面这句代码(随便打印一句话)将延时一秒执行。

    NSLog(@"随便打印一句话");

}


@end



4个术语比较容易混淆:同步、异步、并发、串行

同步和异步决定了要不要开启新的线程

同步:在当前线程中执行任务,不具备开启新线程的能力

异步:在新的线程中执行任务,具备开启新线程的能力

 

并发和串行决定了任务的执行方式

并发:多个任务并发(同时)执行

串行:一个任务执行完毕后,再执行下一个任务

ios哪些技术可以办证线程安全:

一、多线程的安全隐患

资源共享

1块资源可能会被多个线程共享,也就是多个线程可能会访问同一块资源

比如多个线程访问同一个对象、同一个变量、同一个文件

当多个线程访问同一块资源时,很容易引发数据错乱和数据安全问题

三、如何解决

 

互斥锁使用格式

@synchronized(锁对象) { // 需要锁定的代码  }

注意:锁定1份代码只用1把锁,用多把锁是无效的

互斥锁的优缺点

优点:能有效防止因多线程抢夺资源造成的数据安全问题

缺点:需要消耗大量的CPU资源

 

互斥锁的使用前提:多条线程抢夺同一块资源 

相关专业术语:线程同步,多条线程按顺序地执行任务

互斥锁,就是使用了线程同步技术

四:原子和非原子属性

 

OC在定义属性时有nonatomicatomic两种选择

atomic:原子属性,为setter方法加锁(默认就是atomic

nonatomic:非原子属性,不会为setter方法加锁

 

原子和非原子属性的选择

nonatomicatomic对比

atomic:线程安全,需要消耗大量的资源

nonatomic:非线程安全,适合内存小的移动设备

iOS开发的建议

所有属性都声明为nonatomic

尽量避免多线程抢夺同一块资源

尽量将加锁、资源抢夺的业务逻辑交给服务器端处理,减小移动客户端的压力

ASIHTTPRequest详解 

ASIHTTPRequest是一款极其强劲的HTTP访问开源项目。让简单的API完成复杂的功能,支持功能如: 

异步请求,队列请求,GZIP压缩,缓存,断点续传,进度跟踪,上传文件,HTTP认证,还加入了Objective-C闭包Block的支持。ASIHTTPRequest父类是MKNetworhEngine;


你如何理解block,他的用途:

Block除了能够定义参数列表、返回类型外,还能够获取被定义时的词法范围内的状态(比如局部变量),并且在一定条件下(比如使用__block变量)能够修改这些状态。此外,这些可修改的状态在相同词法范围内的多个block之间是共享的,即便出了该词法范围(比如栈展开,出了作用域),仍可以继续共享或者修改这些状态。

通常来说,block都是一些简短代码片段的封装,适用作工作单元,通常用来做并发任务、遍历、以及回调。

block作为回调函数,可以使得程序员在写代码更顺畅,不用中途跑到另一个地方写一个回调函数,有时还要考虑这个回调函数放在哪里比较合适。采用block,可以在调用函数时直接写后续处理代码,将其作为参数传递过去,供其任务执行结束时回调。另 一个好处,就是采用block作为回调,可以直接访问局部变量。比如我要在一批用户中修改一个用户的name,修改完成后通过回调更新对应用户的单元格 UI。这时候我需要知道对应用户单元格的index,如果采用传统回调方式,要嘛需要将index带过去,回调时再回传过来;要嘛通过外部作用域记录当前 操作单元格的index(这限制了一次只能修改一个用户的name);要嘛遍历找到对应用户。而使用block,则可以直接访问单元格的index



简述UDPTCP的区别?

1TCP是基于连接的,UDP是基于无连接 2。对系统资源的要求(TCP较多,UDP少) 3UDP程序结构较简单 4。流模式与数据报模式 5TCP保证数据正确性,UDP可能丢包,TCP保证数据顺序,UDP不保证 


3.XMLJSON的优缺点对比

(1).可读性方面。
JSON
XML的数据可读性基本相同,JSONXML的可读性可谓不相上下,一边是建议的语法,一边是规范的标签形式,XML可读性较好些。
(2).
可扩展性方面。
XML
天生有很好的扩展性,JSON当然也有,没有什么是XML能扩展,JSON不能的。
(3).
编码难度方面。
XML
有丰富的编码工具,比如Dom4jJDom等,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


进程和线程的区别

1、进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位


线程是进程的一个实体,CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源


一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行 

2、进程和线程的区别在于: 


简而言之,一个程序至少有一个进程,一个进程至少有一个线程


线程的划分尺度小于进程,使得多线程程序的并发性高。 


另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。 

线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。 


从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。 


NSUserDefaults类提供了一个与默认系统进行交互的编程接口。NSUserDefaults对象是用来保存,恢复应用程序相关的偏好设置,配置数据等等。默认系统允许应用程序自定义它的行为去迎合用户的喜好。你可以在程序运行的时候从用户默认的数据库中读取程序的设置。同时NSUserDefaults的缓存避免了在每次读取数据时候都打开用户默认数据库的操作。可以通过调用synchronize方法来使内存中的缓存与用户默认系统进行同步。


NSUserDefaults注意事项

并不是所有的东西都能往里放的。NSUserDefaults只支持: NSString, NSNumber, NSDate, NSArray, NSDictionary.


NSUserDefaults的方法中用来记录一下永久保留的数据非常方便,不需要读写文件,而是保留到一个NSDictionary字典里,由系统保存到文件里,系统会保存到该应用下的/Library/Preferences/gongcheng.plist文件中。

要注意的是如果程序意外退出,NSUserDefaults standardUserDefaults数据不会被系统写入到该文件,不过可以使用[[NSUserDefaults standardUserDefaults] synchronize]调用synchronize函数将立即更新这些默认值,而不是等待程序终止,避免数据的丢失


ios中数据库使用什么技术实现的

sqliteCoreData


常用数据库:    SQLServer 2000-----保存游戏的所有用户的信息

                        Oracle

                        mysql------网上php网站使用较多


                        特点: 网络数据库, 支持的功能多, 程序比较大


    移动开发常用:    sqlite数据库

                        特点:    足够小, 足够快(本地数据库), 使用比较简单


    常用软件:                    MesaSQlite数据库操作软件

    数据库操作语言:        SQL(结构化查询语言)

    常用开源库:                FMDB


简述什么是主键什么是外键

数据库中主键和外键是什么意思主键是表格里的(一个或多个)字段,只用来定义表格里的行;主键里的值总是唯一的。外键是一个用来建立两个表格之间关系的约束。 


建立外键后,在插入数据时候会检测数据在主键表中是否存在,如果不存在则无法插入,通过这可以提高维护数据库的完整性和一致性 


怎样实现IOS开发中的数据存储方式

iOS 开发中,一般有如下几种数据存储方式。需要根据具体的业务场景,选择 合适的数据存储方式。

1.(1)  用户默认设置这种情况通常不需要用户干预,如游戏通关信息,Video

播放记录,或者 App 退出之后,下次进入时,希望恢复到退出时的情况。

2.(2)  设置束(Settings Bundle)-- 提供了一个通过 iPhoneiPad的设置

(Settings)应用程序进行配置的接口。

3.(3)  直接访问文件系统读写属于当前 App iOS 文件系统部分的文件。

4.(4)  SQLite 数据库 -- 是嵌入式的和轻量级的 SQL 数据库,SQLite 是由 C实现的。

5.(5)  远端数据库 这个一般由 App 调用远端的 RESTFul WCF 服务,JSON

或者 XML 数据传递给远端的 Web 服务,读写数据库的逻辑完全在 Web 务端实现。比如,用户在iPhone/iPad 终端 App 提交了订单,订单数据当然需要写入远端 SQL Server Oracle 数据库


IOS沙盒机制 

出于安全的目的,应用程序只能将自己的数据和偏好设置写入到几个特定的位置上。当应用程序被安装到设备上时,系统会为其创建一个家目录,这个家目录就是应用程序的沙盒。所以的文件都要保存在此,例如图像,图标,声音,映像,属性列表,文本文件等。1、每个应用程序都有自己的存储空间 2、应用程序不能翻过自己的围墙去访问别的存储空间的内容 3、应用程序请求的数据都要通过权限检测,假如不符合条件的话,不会被放行。 sandbox是一种安全体系,应用程序的所有操作都要通过这个体系来执行,其中核心内容是:sandbox对应用程序执行各种操作的权限限制


IOS真机调试流程

真机调试前提是需要一个苹果开发者账号,才可以创建证书请求CSR

在申请真机调试证书之前,先对苹果真机调试所需的文件进行说明: 

苹果真机调试需要证书(Certificates)和描述文件(Provisoning Profiles) 

1、证书(Certificates 通过苹果自带的钥匙串生成后上传到Developer中再生成来完成

2、描述文件(Provisoning Profiles 生成描述文件时需要选择App ID(包含Bundle,必须与你程序的bundle保持一致,为了能同时调试多个程序,一般bundle填写时末尾用*号代替,后文会具体说明)选择证书(Certificates)及设备(Devices)三样东西 

所以如果想要真机调试成功,就必须App ID,证书(Certificates),描述文件(Provisoning Profiles),设备(Devices ),及你所要调试程序的Bundle Identifier保持一致

内存泄漏 

        内存泄漏是编程中常常见到的一个问题,内存泄漏往往会一种奇怪的方式来表现出来,基本上每个程序都表现出不同的方式。 但是一般最后的结果只有两个,一个是程序当掉,一个是系统内存不足。 还有一种就是比较介于中间的结果程序不会当,但是系统的反映时间明显降低,需要定时的Reboot才会正常。 

有一个很简单的办法来检查一个程序是否有内存泄漏。就是是用Windows的任务管理器(Task Manager)。运行程序,然后在任务管理器里面查看 内存使用虚拟内存大小两项,当程序请求了它所需要的内存之后,如果虚拟内存还是持续的增长的话,就说明了这个程序有内存泄漏问题。 当然如果内存泄漏的数目非常的小,用这种方法可能要过很长时间才能看的出来。 

原因

内存泄漏产生的原因一般是三种情况: 

1. 分配完内存之后忘了回收; 

2. 程序Code有问题,造成没有办法回收; 

3. 某些API函数操作不正确,造成内存泄漏。 


IOS 支付功能的实现

支付宝是第三方支付平台,简单来说就是协调客户,商户,银行三者关系的方便平台

使用支付宝进行一个完整的支付功能,大致有以下步骤:

a 与支付宝进行签约,获得商户IDpartner)和账号IDseller

b 下载相应的公钥私钥文件(加密签名用)

c 下载支付宝SDK

d 生成订单信息

e  调用支付宝客户端,有支付宝客户端跟支付宝安全服务器打交道

f  支付完毕后返回支付结果给客户端和服务器

支付功能的实现 有两种方式:

1  支付宝的应用可以 url 直接连接到 支付宝的官网 (当然后台是要进行处理的)

2  第二种就是添加支付宝的第三方了 首先 下载支付宝的demo 

iOS项目上传到AppStore步骤流程

1.登录developer.apple.com2.点击member center 进下图3.点击certificates Identifiers进下图4.点击Certificates进下图,首先创建App IDs5.其次创建相应的证书 Development是开发环境下的证书, Production是生产环境下的证书(往appStore上传),对应的推送证书 也不多说了。6.点击下一步后会让你选择 本地生成本地密钥和证书关联,见下图7.本地生成密钥文件。在LaunchPad里找到钥匙串访问,创建本地密钥文件见下图8.生成本地密钥文件后(该本地密钥适用 推送 发布 开发等环境证书的创建,建议创建完后不要删掉) ,接步骤6 完成证书创建。9.创建配置文件,见下图10.添加你的开发者账号和密码到项目中,见下图11.设置Build Settings,见下图。debug 对应的是开发证书和开发的配置文件,release对应的是发布证书和发布配置文件,development对应的是测试环境,production对应的是生产环境。请大家根据实际情况选择对应的证书和配置文件。12.修改bundle ID (与之前在developer上创建的bundle ID保持一致)和 bundle nameapp的名字15.archive打包 ,根据需求(上传或测试)选择证书、配置文件和scheme17.选择Export后,再选择第二个 save for ad hoc deployment ,生成本地ipa文件包 用于测试,next 倒出到本地即可。



你可能感兴趣的:(iOS面试)