iphone学习整理.docx

上传人:b****6 文档编号:7348687 上传时间:2023-01-23 格式:DOCX 页数:16 大小:38.22KB
下载 相关 举报
iphone学习整理.docx_第1页
第1页 / 共16页
iphone学习整理.docx_第2页
第2页 / 共16页
iphone学习整理.docx_第3页
第3页 / 共16页
iphone学习整理.docx_第4页
第4页 / 共16页
iphone学习整理.docx_第5页
第5页 / 共16页
点击查看更多>>
下载资源
资源描述

iphone学习整理.docx

《iphone学习整理.docx》由会员分享,可在线阅读,更多相关《iphone学习整理.docx(16页珍藏版)》请在冰豆网上搜索。

iphone学习整理.docx

iphone学习整理

第一回

这是我在csdn的第一篇blog,想和大家分享我学习iphone开发的经验。

也希望借着写Blog来督促自己学习。

iphone使用objectivec作为其开发语言(apple真是屌啊,就他们家用objectivec吧。

),在学习iphonesdk之前,我们先看看objectivec的基本特点吧。

objectivec是一种c语言的变种,所以有时候在objectivec中能看到写c语言的影子。

objectivec和c的不同之处

1.objectivec使用nil来表示NULL2.objectivec用YESNO来表示truefalse3.objectivec用#import而不是#include来包含头文件4.在objectivec中,我们称类的方法(method)为消息(message)。

在C++中,我们这样来调用方法:

aClass->function(var);但是在objectivec中,我们使用[aClassfunction:

var]objectivec中的消息(message)比较有意思的特点是:

1)调用消息的类可以不知道如何响应这个消息。

如果它不知道如何处理这个消息,它会自动的将这个消息转给其他的类,比如它的父类;2)调用消息的类可以是nil。

在C++中,在使用类方法之前,我们都需要检查对象是否为空,所以在实现析构函数的时候,常会有如下的代码,如if(var){deletevar;}但是在objectivec中,我们就可以直接写[varrelease];即使var==nil,也不会有问题。

照着老规矩,先写个helloworld#importintmain(intargc,char*argv[]){printf("helloworld\n");return1;}确实跟C很像吧。

但是也不其然,objectivec是一个很好的面向对象的语言。

跟C还是有挺多不同之处。

我们先实现一个简单的类。

//Sample.h#import@interfaceSample:

NSObject{inta;}-(void)print;-(void)setA:

(int)a;@end咱们一句一句来看。

#import在objectivec中,所有的类都必须继承NSObject,这个概念很想Java里面的Object。

objectivec声明类的格式如下:

@interfaceclassName:

baseClassName{membervariables;}memberfunctions@end大家可能注意到objectivec中函数的声明挺有特点的,我们现在来解释:

objectivec的函数声明的基本格式如下-/+(returntype)function_name;-/+(returntype)function_name:

(parametertype)parameter;-/+(returntype)function_name:

(parametertype)parameter1otherParameter:

(parameter_type)parameter2;1)-/+:

这个称做scope,如果在函数前面是-,那么理解为一般的函数;如果是+,可以理解为c++中的static函数2)函数的参数声明:

objectivec和c++,java都很不一样。

如果没有参数的话,在函数名后面,可以什么都不写;如果只有一个参数,在:

后面声明参数的类型和名称;如果有多个参数的话,每个参数前面都要有一个:

,然后接着是参数类型和参数名称。

可是大家可能还是觉得很奇怪。

比如上面这个例子中,otherParameter这个东西是干什么的呢?

在objectivec中,对于有多个参数的函数,我们可以理解为将函数的名称拆成了几个部分,每个部分都是对紧接着的参数的一个解释。

比如在C++中:

voidinitializeRectangle(intx1,inty1,intx2,inty2),但是我们并不知道这些参数都是什么意思;但是在objectivec中,我们可以这样声明:

voidinitializeRectangeWithLeftTopX:

(int)x1LeftTopY:

(int)y1RightBottomX:

(int)x2RightBottomY:

(int)y2;怎么样?

有感觉了吧。

下面来实现这个简单的Sample类//sample.m#import#import"Sample.h"@implementationSample-(void)print{printf("%d\n",a);}-(void)setA:

(int)aa{a=aa;}@end使用这个类#import"Sample.h"intmain(intargc,char*argv[]){Sample*smp=[[Samplealloc]init];[smpsetA:

1];[smpprint];[smprelease];}在objectivec中,每一个类的对象都是一个指针,这和Java差不多(每个类的对象都用new声明)。

alloc类似于C中的malloc,init是NSObject中的方法,用于初始化这个对象。

如果我们实现了自己的初始化方法,也可以调用自己的初始化方法。

使用完毕后,需要调用release释放空间。

在iPhone开发中,需要特别注意内存的管理。

今后还会仔细些这部分的内容。

今天先写这么多。

未完待续:

第二回:

上次说了ObjectiveC是一种挺好的面向对象的语言。

那么我们今天就来看看ObjectiveC中的一些面向对象的特性吧。

构造函数(constructor)

其实我觉得在ObjectiveC中,这个名字并不算很恰当,可能叫做“初始化函数”比较合适一些吧。

因为这个函数其实就是一个普通的函数,和C++与Java中对构造函数的特殊待遇不同。

举个例子:

@interfaceSample:

NSObject{inta;}-(Sample*)initWithIntValue:

(int)aa;-(void)setA:

(int)aa;-(void)print;@end@implementationSample-(Sample*)initWithIntValue:

(int)aa{if(self=[superinit]){[selfsetA:

aa];}returnself;}//setA和print的实现参见上一篇@end其实,initWithIntValue就是所谓的“构造函数”。

我们在使用的时候,还是需要先调用父类NSObject中的alloc方法(注:

alloc方法是一个static的方法,它是被“+”修饰的,参见上篇关于函数声明的介绍):

Sample*smp=[[Samplealloc]initWithIntValue:

1];对构造函数的几个说明:

1)返回值一定要是类的指针2)一定要先调用父类NSObject的init函数,因为在ObjectiveC中所有的类都是从NSObject继承来的3)检查init返回的值是否有效4)self:

这是ObjectiveC的一个关键字,概念上和C++与Java中的this一样

访问限制

在面向对象程序设计中,大家一定很熟悉访问限制的概念,也就是C++和Java中的public,protected,private,在ObjectiveC中也有类似的东西#import@interfaceAccessExample:

NSObject{@publicintpublicVar;@protectedintprotectedVar;@privateintprivateVar;}@end没错,就是挺简单的。

还记得之前说的ObjectiveC中的静态方法么(staticmessages)?

下面我们来看一个例子:

//ClassA.h#importstaticintcount;@interfaceClassA:

NSObject+(int)getCount;+(void)initialize;@end//Implementation@implementationClassA-(id)init{self=[superinit];count++;returnself;}+(int)getCount{returncount;}+(void)initialize{count=0;}@endstaticintcount;在C++中,还记得怎么声明静态变量么?

viewplaincopytoclipboardprint?

classA{public:

A();~A();protected:

staticinta;}staticintA:

:

a=0;classA{public:

A();~A();protected:

staticinta;}staticintA:

:

a=0;但是在ObjectiveC中,所谓类的静态变量其实可以理解为一个全局的静态变量,因为它并没有被放在@interface的定义里面。

接下来,getCount和initialize是两个静态方法。

getCount用于返回当前对象的个数,而initialize用于清空对象的计数。

但是在Implementation中,为什么会有init这个方法呢?

是的,这里可以理解为,我们重载了NSObject中的init方法:

仅增加了一个功能,就是计数。

我们不需要在头文件中声明init,因为我们继承了NSObject。

如何使用这个类呢:

intmain(intargc,char*argv[]){[ClassAinitialize];ClassA*c1=[[ClassAalloc]init];ClassA*c2=[[ClassAalloc]init];printf("ClassAcount:

%i\n",[ClassAgetCount]);......}读者自己试一试实现自己的release方法吧:

)未完待续~~

第三回

继承

我们接着来看objectivec中面向对象的特性。

要谈到面向对象,就不可能不说继承和多态。

其实,我们之前就已经谈到了继承,因为在objectivec中,所有类都是从NSObject继承而来的。

继承,可以理解为“is-a”的关系,这个概念相信对大部分人来说都在熟悉不过了,关于C++和Java的任何一本书都会详细介绍这个概念,这里我不再赘述,直接上例子。

//Rectangle.h#import@interfaceRectangle:

NSObject{intwidth,height;}-(Rectangle*)initWithWidth:

(int)wandHeight:

(int)h;-(void)setWidth:

(int)w;-(void)setHeight:

(int)h;-(void)setWidth:

(int)wandHeight:

(int)h;-(int)width;-(int)height;-(void)print;//printf("widthis%i,heightis%i\n",[selfwidth],[selfheight]);@end-(Rectangle*)initWithWidth:

(int)wandHeight:

(int)h和-(void)setWidth:

(int)wandHeight:

(int)h都是带多个参数的函数声明(参见第一篇)。

我们再实现一个正方形的类,继承矩形。

//Square.h#import"Rectangle.h"@interfaceSquare:

Rectangle{}-(Square*)initWithSize:

(int)s;-(void)setSize:

(int)s;-(int)size;@end//Square.m@implementationSquare-(Square*)initWithSize:

(int)s{if(self=[superinit]){[selfsetSize:

s];}returnself;}-(void)setSize:

(int)s{width=s;height=s;}-(int)size{returnwidth;}-(void)setWidth:

(int)w{[selfsetSize:

w];}-(void)setHeight:

(int)h{[selfsetSize:

h];}-(void)print{printf("thesizeis%i\n",[selfsize]);}@end上面这个正方形类,继承了矩形类的成员变量。

但是由于正方形的几何特殊性(长=宽),所以在正方形类中添加了三个方法。

分别是initWithSize,setSize,size。

另外,我们重载了矩形类中的setWidth和setHeight方法,因为正方形不允许分别设置长和宽。

如何使用:

intmain(intargc,char*argv[]){Rectangle*rect=[[Rectanglealloc]initWithWidth:

10andHeight:

5];Square*sq=[[Squarealloc]initWithSize:

10];[rectprint];[sqprint];[rectrelease];[sqrelease];}

虚函数

有了继承,我们就来说一说多态性。

C++中虚函数的概念相信大家都不陌生,它通过一个虚拟表(virtualtable)实现了动态绑定(dynamicbinding)。

在objectivec中也有类似的概念。

我们就以上面两个类为例子:

intmain(intargc,char*argv[]){Rectangle*rect=[[Rectanglealloc]initWithWidth:

10andHeight:

5];Square*sq=[[Squarealloc]initWithSize:

5];idshape;shape=rect;[shapeprint];//calltheRectangle'sprintshape=sq;[shapeprint];//calltheSquare'sprint......}这里,引入了objectivec的一个很重要的关键词id。

我们可以将id理解为C++中的void*,所以我们能将rect和sq都赋值给shape。

那么shape是怎么知道调用哪个版本的print的呢?

还记得第一篇中我们提到的message的概念么?

虽然id不知道如何响应print,但是它可以把这个消息传递给rect或者sq。

run-time的类类型检查

和c++与Java一样,objectivec也支持run-time的类类型检查-(BOOL)isKindOfClass:

classObj用于判断该对象是否属于某个类或者它的子类。

如:

if([sqisKindOfClass:

[Rectangleclass]]==YES){}-(BOOL)isMemberOfClass:

classObj用于判断该对象是否属于某个类(这里不包括子类)如:

if([sqisMemberOfClass:

[Rectangleclass]]==NO){}-(BOOL)respondsToSelector:

selector用于判断该对象是否能响应某个消息。

这里,我们可以将@selector后面带的参数理解为C++中的函数指针。

注意:

1)不要忘了@2)@selector后面用的是(),而不是[]。

3)要在消息名称后面跟:

,无论这个消息是否带参数。

如:

if([sqrespondsToSelector:

@selector(setSize:

)]==YES){}+(BOOL)instancesRespondToSelector:

selector用于判断该类是否能响应某个消息。

这是一个静态函数。

如:

if([SquareinstancesRespondToSelector:

@selector(setSize:

)]==YES){}我们之前说到Objective-C是一种很好的面向对象的语言,和C++和Java相比,Objective-C有一些自己独特的东西,下面我们来简单的介绍一下。

1)Category

回想一下,在C++中,如果我们想继承一个类,给它添加一些新的功能,我们需要什么?

当然是我们需要得到这个类的源代码。

但是在Objective-C中,由于有了这个Category的概念,我们可以在没有源代码的情况下,为一个已经存在的类添加一些新的功能,比如:

//DisplayMath.h@interfaceRectangle(Math)-(int)calculateArea;-(int)calculatePerimeter;@end//DisplayMath.m@implementationRectangle(Math)-(int)calculateArea{returnwidth*height;}-(int)calculatePerimeter{return2*(width+height)}@end这里,使用了之前定义的Rectangle类,我们想为它添加两个功能:

计算面积和周长。

即使没有Rectangle类的源代码,我们也可以通过Category创建Rectangle的子类。

使用Category的时候,需要注意两个地方:

1)只能添加新的方法,不能添加新的数据成员2)Category的名字必须是唯一的,比如这里,就不允许有第二个Math存在。

如何使用:

intmain(intargc,char*argv[]){Rectangle*rect=[[Rectanglealloc]initWithWidth:

5andHeight:

10];[rectcalculateArea];[rectrelease];}

2)如何创建私有方法

我们知道可以使用@private来声明私有变量,但是如何声明私有方法呢?

Objective-C中并没有什么关键词来修饰方法,如果我们想让某个方法不被其他的类所见,唯一的方法就是不让这个方法出现在头文件中。

比如:

//MyClass.h#import@implementationMyClass-(void)sayHello;@end//MyClass.m#import"MyClass.h"@implementationMyClass-(void)sayHello{NSLog(@"Hello");}@end@interfaceMyClass(Private)-(void)kissGoodbye;@end@implementationMyClass(Private)-(void)kissGoodbye{NSLog(@"kissgoodbye");}@end怎么样,看到了Category的应用么?

是的,利用Category可以方便的实现“私有”方法。

3)Protocol

在Objective-C中,Protocol的概念很象Java中的interface或者C++中的virtualclass。

来看下面这个例子:

@protocolPrinting-(void)print;@end//MyDate.h@interfaceMyDate:

NSObject{intyear,month,day;}-(void)setDateWithYear:

(int)yandMonth:

(int)mandDay:

(int)d;@end//MyDate.m#import#import"MyDate.h"@implementationMyDate-(void)setDateWithYear:

(int)yandMonth:

(int)mandDay:

(int)d{year=y;month=m;day=d;}-(void)print{printf("%4d-%2d-%2d",year,month,day);}@end我们首先声明了Printing协议,任何遵守这个协议的类,都必须实现print方法。

在ObjectiveC中,我们通过<>来表示遵守某个协议。

当某个类声明要遵守某个协议之后,它就必须在.m文件中实现这个协议中的所有方法。

如何使用:

intmain(intargc,char*argv[]){MyDate*dat=[[MyDatealloc]init];[datinitDateWithYear:

1998andMonth:

09andDay:

01];idvar=dat;[varprint];if([datconformsToProtocol:

@protocol(Printing)]==YES){}//true[datrelease];}注意两个地方:

1)使用id作为类型,而不是象C++中,使用Printing*var;2)conformsToProtocol类似于之前所说的respondsToSelector,用于动态检查某个对象是否遵守某个协议。

iPhone程序开发时内存的管理

在开发iPhone程序时,一定要特别小心内存的管理。

其实基本的道理很简单,就像我们以前写C++程序一样,new和delete要成对出现。

问题是在某些时候,我们没有意识到自己使用了new。

Objective-C中对内存的管理采用引用计数的技术。

简单说就是,当我们拥有一个变量的时候,这个变量的计数就加1,当我们释放这个变量的时候,这个变量的计数就减1。

当计数为0时,这个变量就可以合法的被删除了。

1)alloc很明显,这个函数调用之后,变量的计数加1。

所以在调用alloc之后,一定要

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 小学教育 > 语文

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1