iphone开发中,自定义协议有什么用?
iphone开发中,自定义协议
自定义协议语法如下:
@protocol 协议名称
方法之声明
@end

Objective-C2.0中协议的新特性:(1)@optional预编译指令:表示可以选择实现的方法(2)@required预编译指令:表示必须强制实现的方法。 例如:


@protocol FrameworkDelegate <NSObject>
 @optional //可选的(正式协议) 有这个做标志
 -(void)didReceiveCM:(Framework*)framework ChatMessage:(ChatMessage*)cm;
 -(void)QUserArrived:(Framework*)framework AddressBook:(NSMutableArray*)ab;
//如果@optional 放在此处,表示上面2个方法内部必须实现,下面2个方法可选
 -(void)AllUserArrived:(Framework*)framework AddressBook:(NSMutableArray*)ab;
 -(void)ConversationListChanged:(Framework*)framework ConversationList:(NSMutableArray*)cl;
 
@end




本帖属于 CocoaChina会员发表,转帖请写明来源和帖子地址


协议表示了方法可以被任何类所实现。协议本身不是类。他们只是简单定义了一个其他对象可以实现的接口。当你的类实现了协议中的某个方法的时候也就是说你的类实现了那个协议。



Objective-C的另一个扩展称为协议,它非常象Java中的接口。两者都是通过一个简单的方法声明列表发布一个接口,任何类都可以选择实现。协议中的方法通过其它类实例发送的消息来进行调用。



iPhone程序开发里,object-c里的delegate怎么理解?

答:设置代理

然后就可以实现协议了。

相当于C++里实现一个接口,或Java里实现一个抽象类里的抽象方法。

有些类里不仅可以设置代理,还可以为其设置数据源(比如一些模态窗口UIActionSheet之类的)。


有很多时候是需要在B类口中来完成一些对A类的操作, 这时就需要A设个代理让B来完成了,这个在应用中很常见也很实用。




NSTimer定时器的基本操作方式
NSTimer是Cocoa中比较常用的定时器类,基本操作如下:
handleTimer方法可以自行定义。在需要的地方创建timer即可,handleTimer就可以每0.5秒执行一次。


- (void) handleTimer: (NSTimer
 
{
 
//在这里进行处理
 
} 
 
 
NSTimer *timer;
 

 
timer = [NSTimer scheduledTimerWithTimeInterval:  0.5
 
 
target: self
 
selector: @selector(handleTimer:)
 
 
userInfo: nil
 
repeats: YES];




在Cocoa中使用JSON(重要基础知识)

JSON是一种新的用于在互联网上进行数据交换的标准格式。由于它的冗余、可读性和可解析性都比XML要好,因此JSON这种数据交换格式越来越广泛地运用于Web应用,尤其是Ajax应用中。
在Cocoa中使用JSON也很简单,目前有两个JSON的框架,都很容易使用,而且都对NSDictionary进行了扩展,您可以选择其一将JSON“揉”到您的Cocoa应用程序里。

一个叫做BSJSonAdditions,由Blake Seely开发。将NSDictionary对象转成JSON字符串只需要进行如下转换:
[dict jsonStringValue];
就可以返回一个NSString的JSON格式。
反过来如果希望将JSON字符串转成NSDictionary,只需要进行如下转换:
[NSDictionarydictionaryWithJSONString:jsonString]
就可以返回NSDictionary的对象了。
另一个叫做json-framework,参考了BSJSonAdditions,并且以framework的方式提供。
json-framework的用法同样类似,使用NSDictionary或者NSArray的JSONRepresentation方法来获取JSON的NSString字符串,用NSString的JSONValue方法来获取转换后的NSDictionary或者NSArray对象。



Objective-C 内存管理的几点总结(非常重要的基础知识)
1.当你使用 new、alloc 或 copy 创建对象时,对象的 count retain 到 1。你一定要负责把这个对象 release 或 autolease 掉。这样当它的生命周期结束时,它才能清空。
2.当你使用其他方法获得一个对象时,你可以认为它已经 retain 了一个 count,并且 autolease 掉了。你不用考虑和它相关的清理问题。但是如果你想保留这个对象,那么你需要 retain 它,并且要确保之后你 release 了这个对象。
3.如果你 retain 一个对象,你最终总是需要 release 或者 autolease 它。
这三条规则在写代码的时候一定要遵守,一旦遵守了一般也就不会有内存泄露的问题。



在iphone的平台下,要进行socket开发其实有很多种的方法,开源的库Asyncsocket,官方的CFSocket,还有BSD的socket。 



视图里两个事件的区别(重要语法知识)
viewdidload事件就是只有产生的时候才响应,重新打开的时候是没响应的。
viewWillAppear就是每次出现的时候的消息,在load之后。


顺道写下image的一些 用法

UIImage *iamge=[UIImage imageNamed:@"***.png"];
cell.imageView.image=image;



iphone开发-NSTimer定时器的基本操作方式
NSTimer是Cocoa中比较常用的定时器类,基本操作如下:handleTimer方法可以自行定义。在需要的地方创建timer即可,handleTimer就可以每0.5秒执行一次。 - (void ) handleTimer: ( NSTimer *) timer { // 在这
NSTimer是Cocoa中比较常用的定时器类,基本操作如下:
handleTimer方法可以自行定义。在需要的地方创建timer即可,handleTimer就可以每0.5秒执行一次。

- (void)handleTimer: (NSTimer *)timer //
 
{
 
//在这里进行处理
 
}
 
NSTimer *timer;
 
timer = [NSTimer scheduledTimerWithTimeInterval: 0.5
 
target: self
 
selector: @selector(handleTimer:)
 
userInfo: nil
 
repeats: YES];


repeates设置成YES的时候会隔0.5s就做一次handleTimer,调试的时候就会发现,timer所在的函数和handleTimer是来回执行的,个人理解是在这个函数执行完之后才执行这个handleTimer的,设置成NO时,handletTimer就只执行一次.

theConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self]; 

nt 
=[ 
NSTimer scheduledTimerWithTimeInterval 
: 
20 target 
: 
self selector 
: 
@selector 
( 
handleTimer 
) userInfo 
: 
nil repeats 
: 
NO 
]; 

-(void)handleTimer{ 

 } 

 -( 
void)connection:( 
NSURLConnection *)connectiondidReceiveResponse:( 
NSURLResponse *)response 

 { 

[ 
webData setLength 
: 
0 
]; 

NSLog 
(@"connection:didReceiveResponse:1" 
); 

 } 

 -( 
void)connection:( 
NSURLConnection *)connectiondidReceiveData:( 
NSData*)data 

 { 

 [ 
webData 
appendData:data]; 

NSLog 
(@"connection:didReceiveData:2" 
); 

 } 


//如果电脑没有连接网络,则出现此信息(不是网络服务器不通) 

 -( 
void)connection:( 
NSURLConnection *)connectiondidFailWithError:( 
NSError*)error 

 { 

 //NSLog(@"ERROR with theConenction"); 

[theConnection 
release 
]; 

 theConnection 
= 
nil 
; 

[webData 
release 
]; 

 webData 
= 
nil 
; 

 } 


 -( 
void) connectionDidFinishLoading:( 
NSURLConnection*) connection 

 { 


 }

上面是我在用的时候所涉及的代码,只写出了函数,可以自己实验下,看函数的执行顺序以及同异步的关系




@Propery讲解
property是一个属性访问声明,扩号内支持以下几个属性:
1,getter=getterName,setter=setterName,设置setter与getter的方法名
2,readwrite,readonly,设置可供访问级别
2,assign,setter方法直接赋值,不进行任何retain操作,为了解决原类型与环循引用问题
3,retain,setter方法对参数进行release旧值再retain新值,所有实现都是这个顺序(CC上有相关资料)
4,copy,setter方法进行Copy操作,与retain处理流程一样,先旧值release,再Copy出新的对象,retainCount为1。这是为了减少对上下文的依赖而引入的机制。
5,nonatomic,非原子性访问,不加同步,多线程并发访问会提高性能。注意,如果不加此属性,则默认是两个访问方法都为原子型事务访问。锁被加到所属对象实例级(我是这么理解的...)。

经常备用到的参数是 copy/reain/assign。在其中选择一个来确定属性的setter如何处理这个属性。很多Objective-C中的object最好使用用retain,一些特别的object(例如:string)使用copy。
assign关键字代表setter直接赋值,而不是复制或者保留它。这种机制非常适合一些基本类型,比如NSInteger和CGFloat,或者你并不直接拥有的类型,比如delegates。
readonly关键字代表setter不会被生成, 所以它不可以和 copy/retain/assign组合使用。我们把 summary 定义为 readonly 是因为它并不需要一个专门的类变量,相应的,我们会在用到的时候动态生成它:



定时器
设置定时器下面显示的定时器将在一秒钟后触发,并一直重复直到定时器被禁用。定时器每次激活时,就会调用发送选择器消息的目标来进行初始化。回调方法带有一个参数,就是定时器本身.要禁用一个定时器,给它发送invalidate消息,这将释放定时器对象并把它从当前运行循环中删除。

NSTime *timer ;
timer = [NSTimer scheduledTimerWithTimeInterval:1.0target:self selector:@selector(handlTimer:) userInfo:nilrepeats:YES];


- (void)handleTimer:(NSTimer *)timer{
printf("timer count: %d", count++);
if(count > 3)
{
[timer invalidate];

}



iphone开发之 - 启动页面设置(重要的iphone开发经验)不管是开发个人项目还是公司项目,大家通常都有一个需求,就是,在app启动的时候,指定一定的时间来显示自己的或者公司的logo,那么,我就将刚刚写好的启动加载页面设置代码贡献出来。
这里我需要用到NSTimer这个东西,相关的内容可以查看API,有比较详细的解释。
新建一个项目,随便是什么项目,我建立的是“view based application”,然后,命名为“Logo”,然后确定。
直接编辑“Resources"目录下的"LogoViewController.xib”。将背景颜色改称绿色,主要是为了当从logo页跳转过来的时候能有感觉到变化。
然后新建一个NSTimer.


logoviewcon*lo = [[logoviewconalloc] initWithNibName:@"logoviewcon"bundle:nil];
self.logo
[lo release];
[windowaddSubview:self.logo.view];
//初始化timmer
NSTimer*timer = [NSTimerscheduledTimerWithTimeInterval: 1.5target: selfselector: @selector(logo:) userInfo: nilrepeats: YES];
注意,初始化的代码中有这么一段:@selector(logo:),其中的方法就是当这个1.5秒时间过去之后自动调用的方法。

-(void) logo:(NSTimer*)timer{
[logo.view removeFromSuperview];
 [timer invalidate];//这句代码用来终止timmer,否则,每过1.5秒,就会执行该方法一次,我们是要在开始的时候执行一次就够了。
 }

线程(重要基础知识)
 1. 创建一个新的线程:

[NSThread detachNewThreadSelector:@selector(myMethod) 
 toTarget:self 
 withObject:nil];


  2. 创建线程所调用的方法:

-(void)myMethod {
 NSAutoreleasePool *pool =[[NSAutoreleasePool alloc] init];

***code that should be run in the newthread goes here ***[pool release];
 }



  假如我们需要在线程里面调用主线程的方法函数,就可以用performSelectorOnMainThread来实现:

[self performSelectorOnMainThread:@selector(myMethod) 
 withObject:nil 
 waitUntilDone:false];



[super viewDidLoad];是什么意思?有什么作用?
-(void)viewDidLoad函数里边 [super viewdidload] 是必须的嘛?
首先,viewDidLoad是视图控制器类用于加载视图的方法。其次,super就是调用父类中的方法。
[super viewDidLoad]就是调用父类中的viewDidLoad方法。


父类中的viewDidLoad会帮助你做一些初始化的工作,比如A是基类,B从A继承,B在viewDidLoad方法中创建和初始化了一些成员,
C继承B,如果C在调用viewDidLoad的时候没有调用super的viewDidLoad方法,那么就会有一些成员没有被初始化,可能就会产生问题。


为何需要调用“super viewDidLoad”?

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

在上面的代码中,什么需要调用父类相应的方法呢?
以viewDidLoad为例,父类(super)中的viewDidLoad会帮助你做一些初始化的工作,比如A是父类,B继承A,B在viewDidLoad方法中创建和初始化了一些成员;
C又继承B,此时,如果C在调用viewDidLoad的时候没有调用super的viewDidLoad方法,那么就会有一些成员没有被初始化,可能就会产生问题。


initWithFrame: 和 initWithCoder: 区别

1.initWithCoder: 对于.xib,视图加载时默认调用的是该方法;
2.initWithFrame: 非.xib的手动编码,视图加载时默认调用的是该方法。
所有初始化的代码都放到上面方法内部调用。另,对于.xib,也可以在awakeFromNib方法里面放额外的初始化动作。


Objective-C利用协议实现回调函数(类似java的回调函数)
在编写iphone开发时,最常用的就是回调函数。自己编写回调函数,实现动态加载数据,加载完数据之后就利用回调函数通知给前台页面,显示相应数据的界面。在iphone中利用协议可以很容易的实现回调函数,后台加载数据,然后显示在前台页面。



- (id)init {
// 先讓父類別進行初始化
if (self = [super init]) {
// do something
}
return self;
}


if(self=[super init]) 首先的是[super init],使超类完成自己的初始化工作。
if(self=[superinit])这条语句的意思,[super init]是初始化父类中的变量方法,self=[superinit]就相当于子类也初始化了这些变量和方法,而用if判断下,是为了防止self为空的情况,即创建失败的情况。
self被指定为返回值,这个返回值通过self =[superinit]中发送给super对象的init消息得来。它只意味着在Object-C中我们必须手工调用父类得init方法。没有对父类的自动调用。我们必须指定self为[superinit]的返回值,因为它可能会返回nil。(非常重要的语法知识)
Objective-C创建对象需通过两个消息:alloc以及init。alloc的作用是分派存储器空间,init则是对对象做初始化。init与alloc都是定义在NSObject里的类方法,当对象收到这两个消息并做出正确回应后,新实体才算准备妥当。

- (id) init {
if (self  = [superinit]){
}
return (self);
}



父类进行初始化时,用的是子类对象指针self,父类的init方法有可能对这个指针指向的内存区作了大的变更(有可能把这个指针所指的内存释放了,
重新分配了另一块内存区域返回来,这时这个返回的指针与原来的指针是指向不同地址的),所以父类初始化后要重新返回指针。
父类返回的和子类的self的类型都为id类型(通用类型)。父类的init方法若返回的指针与self不一样,
在父类的init方法中已作了release和新的内存分配,不需要自己再去release sef,直接用父类init方法返回的指针就可以了。


if(self = [super init]) {} 若要超类可以完成所需得一次性初始化
需要调用[super init]init 方法返回得值(id型数据 即泛型指针)
描述被初始化对象。


printf("%d",max(a,b)); max(a,b)作为printf函数的一个参数。



类方法是通过给类而不是对象发送消息来调用的下面是一例子:

NSCalendarDate *now; 
 now=[NSCalendarDate calendarDate]; 
 +(id)dateWithYear:(int)year 
 mouth:(unsigned) month 
 day: (unsigned) day 
 hour:(unsigned) minute 
 second:(unsigned)second 
 timeZone:(NSTimeZone *)aTimeZone

类方法返回一个自动释放的对象。特别的是,这个类方法使用的参数所指定
的值来创建并初始一个日历数据。NSCalendarDate这个类,在MAC开发中很常
用。


objective-c中的方法有两种:类方法和实例方法



Objective-C利用协议实现回调函数(类似java的回调函数)
在编写iphone开发时,最常用的就是回调函数。自己编写回调函数,实现动态加载数据,加载完数据之后就利用回调函数通知给前台页面,显示相应数据的界面。在iphone中利用协议可以很容易的实现回调函数,后台加载数据,然后显示在前台页面。[font=宋体 ] 网络的回调函数, 如果你指的是- (void)connectionDidFinishLoading:(NSURLConnection *)connection;
那么只有在全部数据接收完后才会被系统调用
如果你想收到一点就处理一点的话
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data;
这个回调能满足你的要求
总之, 你先弄明白什么叫回调函数吧。才能学会调接口,从服务器上取数据,显示到手机界面上。(非常重要的基础语法知识) 所谓回调函数,是指callback,请先理解。
回调函数的理解
所谓回调,就是客户程序C调用服务程序S中的某个函数A,然后S又在某个时候反过来调用C中的某个函数B,对于C来说,这个B便叫做回调函数。
例如Win32下的窗口过程函数就是一个典型的回调函数。一般说来,C不会自己调用B,C提供B的目的就是让S来调用它,而且是C不得不提供。
由于S并不知道C提供的B姓甚名谁,所以S会约定B的接口规范(函数原型),然后由C提前通过S的一个函数R告诉S自己将要使用B函数,
这个过程称为回调函数的注册,R称为注册函数。WebService以及Java的RMI都用到回调机制,可以访问远程服务器程序。
其实回调函数并不神秘
对于很多初学者来说,往往觉得回调函数很神秘,很想知道回调函数的工作原理。
C语言回调函数
对指针的应用是C语言编程的精髓所在,而回调函数就是C语言里面对函数指针的高级应用。简而言之,回调函数是一个通过函数指针调用的函数。
如果你把函数指针(函数的入口地址)传递给另一个函数,当这个函数指针被用来调用它所指向的函数时,我们就说这个函数是回调函数。
什么是回调函数?
简而言之,回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数。

[font=宋体 ]




iphone--UIViewController与UIView的关系
UIViewController和Uiview是两个不同的类
UIViewController是视图控制器
而UIView是视图
也就是说,UIViewController是控制UIView的。
你也可以认为UIViewController就是一个相框
而UIView就是一个相片
相框可以随时随地的拿走这个相片而换另外一张相片
或者在这张相片上加一个新的相片。而相片
却不能操纵相框的。


UIView工作在第一线,向用户展示表现的内容,并接受用户的交互。UIViewController相当于导演,按照计划编排属下的UIView以何种形式展现,其中包含一些花哨的技巧,如翻转、淡入淡出等。
UIVewController的另一个功能是处理用户交互操作,注意这里我说的是"处理",当然UIViewController本身是不知道用户交互的,这就需要UIView将用户的交互操作(例如:touchesBegintouchesMoved)传递上来。一般常用的两种方法完成这种传递:
1、[self nextResponder] touchesBegin:touches...
2、使用Notification

不管以何种方式,如果UIViewController得到了用户的输入,那么它应该对UIView做些改变以响应用户的输入,这里要注意UIViewController应该只改变UIView的表现,而不应该处理其它事情,
更多的操作通过Delegate来进行,关于Delegate的应用场合下次讲解消息的传递方式中一起阐述。

UIView是一个视图,UIViewController是一个控制器,每一个viewController管理着一个view



特别注意:在Objective-c中,这句话中,if(self=[super init])为什么不用“==”而用"="
这里不是判断self与[super init]是否相等,而是判断是否可以成功初始化。
[super init]:父类初始化成功的话,通过=给self,这样self成为一个非空对象,整个来说即非false(非NO)。
于是也就变成了:

if ( !false )
 {
 //成功初始化后执行的代码
 }


如果init失败 self则为空 if条件为假,于是if段内语句不执行

非常重要的基础语法知识



在objective-C中#pragma mark是什么意思?



经常在 Xcode IDE 里面的代码中看到以下代码指令:

#pragma mark -
 #pragma mark Initialization

#pragma 是什么

从技术上讲,以 #pragma 开头的代码是一条编译器指令,是一个特定于程序或编译器的指令。它们不一定适用于其它编译器或其它环境。如果编译器不能识别该指令,则会将其忽略。

作用

它们告诉Xcode编译器,要在编辑器窗格顶部的方法和函数弹出菜单中将代码分隔开,如下图所示:

iOS 自定义函数名字 iphone自定义命令_timer


一些类(尤其是一些控制器类)可能很长,方法和函数弹出菜单可以便于代码导航。此时加入#pragma 指令对代码进行逻辑组织很有效果。

注意

  1. #pragma mark – 的“-”后面不能有空格。
  2. 如果你的标志没有出现在弹出菜单中,比如没有分隔线出现,请在Xcode菜单 “Preferences..”中的 “Code Sense”选项取消选中”Sort list alphabetically”即可。






在Objective-C中何时用self.何时不用?(非常重要的基础语法知识)

今天在看《iPhone开发基础教程》第七章的时候,代码比着书上的写,但是出错了。排了下错发现是在数据源的一个方法中pickerData已经变成了空,没法用了,这个本来不应该是空值的。仔细比较了下我写的代码和书上的代码,发现是SingleComponentPickerViewController.m中的viewDidLoad中的self.pickerData = array;写成了pickerData = array; 少了个self. 。为什么少写了self.就出错了呢?加个self.有什么作用吗?


还记得在对应的头文件中这样写的吧:@property (nonatomic, retain) NSArray * pickerData; ? 关键是retian,如果不明白这里为什么要用retain,请看《Objective-C基础教程》第134页讲解内存管理的地方。然后到这里如果还不明白,就需要看《Objective-C基础教程》第167页“如果点表达式出现在等号(=)左边,该属性名称的setter方法(-setRainHandling:和-setSnowHandling:)将被调用。如果点表达式出现在对象变量右边,则该属性名称的getter(-rainHandling和-snowHandling)将被调用”。还有第172页中间有一段说“如果只使用裸名name,编译器将假设我们直接修改了实例变量。

要使用访问器方法,我们可以写[self setName:@"Car"]”。


这里就是说,加个self.是为了调用对应的set方法,如果不加,就不调用,不掉用就会造成pickerData的retainCount不加一,不加一就会被直接释放,结果就是在数据源那个方法中得到空值,没法使用,程序崩溃。


所以需要调用对应的方法就加上self. ,不需要就不加。


附:viewDidLoad的代码:


- (void)viewDidLoad 

 { 

 [super viewDidLoad]; 

  

 NSArray * array = [[NSArray alloc] initWithObjects:@"Luke", @"Leia", @"Han", @"Chewbacca", @"Artoo", @"Threepio", @"Lando", nil]; 

 self.pickerData= array; 

  
[array release]; //如果不加self.就会在这里把array直接完全释放,结果array就没法用了。 

 }




switch实例

switch(表达式)
{
case 常量或常量表达式1:
语句1;
break;
case 常量或常量表达式2:
语句1;
break;
.....
case 常量或常量表达式n:
语句n;
break;
default :
语句n+1;
}


计算表达式的值,并逐个与其后面的常量或常量表达式值相比较,当switch上的表达式的值与某个case下的常量表达式的值相等时,即执行其后的语句。如:switch表达式的值与所有case后面的常量表达式均不相同时,则执行default后的语句。
另外须特别注意的是,如果你忘了写break语句的话,当switch表达式的值与某个case常量表达式的值相等时,系统执行所有case后的语句。
例题: int i=4;

switch (i){
case 1:
NSLog(@"我是1");
break;
case 2:
NSLog(@"我是2");
break;
case 3:
NSLog(@"我是3");
break;
default:
NSLog(@"我不是1,2,3");
break;
}


程序结果:我不是1,2,3
程序详解:当程序执行switch语句的时候,发现i的值是4,于是将其和每个case后面的数字进行比较。发现不等于的时候跳到后面的case语句再次进行类似的比较,直到比较结束,发现都不符合条件,于是执行default中的语句,将"我不是1,2,3"打印到控制台上,然后通过break语句结束整个switch语句。

-(IBAction)changeColor:(id)sender//更改颜色
 {
 UISegmentedControl *control = sender;
 NSInteger index = [control selectedSegmentIndex];//得到第几个分段

 QuartzView *quantzView = (QuartzView *)self.view;//把当前的视图转换为QuartzView视图

 switch (index)//根据选择设置颜色
 {
 case kRedColorTab:
 quantzView.currentColor = [UIColor redColor]; //currentColor当前颜色
 quantzView.useRandomColor = NO; //Random随机色
 break;
 case kBlueColorTab:
 quantzView.currentColor = [UIColor blueColor];
 quantzView.useRandomColor = NO;
 break;
 case kYellowColorTab:
 quantzView.currentColor = [UIColor yellowColor];
 quantzView.useRandomColor = NO;
 break;
 case kGreenColorTab:
 quantzView.currentColor = [UIColor greenColor];
 quantzView.useRandomColor = NO;
 break;
 case kRandomColorTab:
 quantzView.useRandomColor = YES;
 break;
 default:
 break;
 }
 }




if 语句与布尔值
if 语句是 C++/C 语言中最简单、最常用的语句,然而很多程序员用隐含错误的方式
写 if 语句。
假设布尔变量名字为 flag,它与零值比较的标准 if 语句如下:
if (flag) // 表示 flag 为真
if (!flag) // 表示 flag 为假
其它的用法都属于不良风格,例如:
if (flag == TRUE)
if (flag == 1 )
if (flag == FALSE)
if (flag == 0)



Objective-C只支持单继承,但可以实现多个协议(接口)。
@protocol 定义一个协议,我跟喜欢把它理解成一个接口,相当于Java中的interface。

obj-c有多重继承么?不是的话有什么替代方法? 由于Object-C不支持多重继承,有一些逻辑类的封装可能无法方便地使用,因此Object-C中提供了协议的机制,
一个类可以实现若干的协议,从这个角度实现了类的多重继承
Objective-C 也使用了类似的机制,成为协议 protocol。在 C++ 中,这种概念是使用抽象类。协议并不是真正的类:它只能声明方法,不能添加数据。有两种类型的协议:正式的 formal 和非正式的 informal。
Objective-C 也有同样的机制,这就是协议 protocol categories。 要注意的是Objective-c只支持单继承,如果要实现多继承的话,可以通过类别和协议的方式来实现。



线程同步和线程异步有什么区别?(重要基础知识)打个比方,如果你在等一个人,
同步的时候,你会一直等到她来了之后才做其他事情,这个过程除了等待你啥都不会做,
异步的时候,你一边在等,可能一边玩游戏或者是看报纸什么的,一直到她到来,你的等待状态才会结束
在实现上,同步的过程会阻塞进程的所有其他操作,将同步转换为异步的最常见方法则是
将会阻塞进程的等待操作放入到一个新的进程中,同时为该等待操作添加一个监视器,在检测到等待操作完成的时候结束等待的进程。