`
cantellow
  • 浏览: 847232 次
  • 性别: Icon_minigender_1
  • 来自: 草帽海贼团
社区版块
存档分类
最新评论

Objective-C就是一个C、C++和Java的杂交体

 
阅读更多

 

1Cocoa是什么?Cocoa是使用OC语言编写的工具包,里面有大量的类库、结构体,说白了其实就相当于java中的标准APIC++中的标准库。OC中没有命名空间的概念,所以使用加前缀来防止命名冲突,因此你会看到大量的以NS 为前缀的类名、结构体、枚举等。

 

2Cocoa框架由Foundation KitApp Kit两部分组成,前者是基础工具库,后者主要是UI库、高级对象等。

 

3static 标识的类变量定义在接口的外面,类变量只能本类访问,除非提供类方法给外部访问这个类变量。

 

4@语法是OC特有的一种语法,C是没有的。

 

5OC中只有类的成员变量才有访问权限控制,@public、@protected、@private,默认是@protected,类变量、类方法、成员方法是没有访问修饰符的,所有的方法都是public的,所有的类变量都是私有的。

 

6OC中的类方法只能类调用,如果使用对象调用就会报错,而java这只是一个警告而已。

 

7OC中定义类的@interfacejava中的interface不是一回事,OC@protocoljava中的interface才是一码事。@interfacejavaC++ class关键字差不多,在OCC++中,都习惯将类定义写在头文件里,而java却根本没有头文件的概念,至于为什么有这样的差别,我想是为了OCC++编译器方便,大多数时候编译器只需要知道头文件类的定义就知道这个类有哪些属性和方法了。

 

8get为前缀的方法在OC中有特殊的意义,所以尽量使用成员变量名称来作为getter方法的函数名。

 

9OC是动态语言,所以即便是@interface中没有定义的方法在.m文件中实现了也是OK的,一般我们都是给别人提供头文件,这种情况就相当于把方法变相的私有化了,对于我这种喜欢在写代码过程中随时加方法但又不想动头文件的人来说还是比较爽的。

 

10、在OC中所有对象的存取都是用指针,C++中还有引用,OC中没有,我宁愿你强迫我使用一种方法,也不愿你提供给我两种方法我却不知道使用哪一种方法的好。

 

11OC的方法定义和调用算是一大“特色”:

方法的定义:-(返回类型) 方法名:(参数1类型)参数1变量 参数2标签:(参数2类型)参数2变量...

[类或者实例的指针 方法名: 参数1 标签2: 参数2… …]

为了好看,第一个参数一般不加标签名,当然,标签名都可以隐藏的,但不建议这样做,因为当你接手了一个离职的人程序,其中的JAVA 程序调用了一个有五个甚至更多的参数的方法,但是你手里没有这个方法的API,那么你很难猜得出来这五个参数到底都干什么用的,但是Objective-C调用的时候,每个参数前面都必须有方法的标签名,这样你便能很容易的从标签名看出这个参数是什么意思。

 

12、调用类方法:

[Fraction t];

[[Fraction class] t];

Class clazz=[Fraction class];[clazz t];

class 来自于NSObject,相当于JAVA 中的getClass()方法,也就是获取这个类的Class 对象,

clazz 前面没有*,这是因为Class 已经是一个指针。另外这种嵌套调用的方式,你也要习

惯,这就和JAVA 中的A.b().c()没有什么区别。

获取Class 有如下几种方法:

[类或者对象 class]

[类或者对象 superclasss]

NSClassFromString(类名的字符串形式)

你也可以通过如下的函数把Class 转换为字符串形式:

NSStringFromClass(Class)

 

13OC中自定义类最好显示继承NSObject,可以获得alloc、init、release等方法。

 

14OC中使用nil表示null,但跟java中的null还是有区别的,java中调用null的方法,会报臭名昭著的空指针异常,而OC不会,所以在OC你不必再为空指针而烦恼。

 

15Cocoa中提供的很多函数和java中的api有很大的不一样,java是纯面向对象的,所有的方法都必须在类中定义,但OC是兼容C语言的,所以C中的面向过程思想在OC中也是行得通的,因此Cocoa中很多东西都不是对象,而是C语言的函数、结构体,比如NSLog()

 

16、对象的初始化

前面我们看到实例化对象最多的方法是:Fraction *frac=[[Fraction alloc] init];

这跟java不一样,java对象创建只需要new一下,同时调用构造方法(实际上虚拟机层面分为两个步骤:new对象,执行<init>方法(包含构造方法)),但是OC中分为两步:分配内存(同时给变量赋初值)、初始化。

1)、alloc 是从NSObject 继承而来的类方法,用于给对象分配存储空间,所有的成员变量在此时对确定了自己的内存位置,并被赋初值,整数类型为0,浮点数为0.0,BOOL 为NO,对象类型为nil,alloc 方法返回对象的指针。

2)、init这个方法是从NSObject继承而来的,你可以覆盖它,当然init不是构造方法,只是一个普通方法而已,你甚至可以换成其他方法,只不过我们习惯在方法名前缀加上init

还记得java中的构造方法没有返回值吧,所以为了达到java这种效果:Test t = new Test(2);OC中需要你手动在普通方法(相当于构造方法)中return self

 

17NSObject中的description方法相当于javaObjecttoString方法,,用于获取对象的字符串表示。唯一不同的是OC中需要使用格式化字符串%@,才会触发description被调用:

Fraction *frac=[[Fraction alloc] init];

NSLog(@"%@",frac);

 

18、Objective-C 的异常都继承自NSException,当然NSException 本身也继承自NSObject。使用下面的语句块进行异常捕获:

@try {  

      <#statements#>  

  }  

  @catch (NSException *exception) {  

      <#handler#>  

  }  

  @finally {  

      <#statements#>  

  }  

总体来说,OC中的异常体系和java中的异常体系差不多,唯一的差别就是java中有业务异常,意思就是说你必须捕获他,如果不捕获就会出现编译错误,OC中的异常基本上都属于java中的运行时异常,如果你没有捕获,发生了异常程序就会崩溃,在一些循环批任务中尤其要注意。

 

18OC中还有一个特色那就是他的弱类型id,他可以表示任何对象,实际上应该是利用了指针地址的通用性,由于OC中操作对象都必须是指针,而指针本身又是一串地址,所以通过指针可以指向一切不同的对象。

 

19、继承(感觉和java差不多啊)

 

20、反射(这个和异常一样,感觉跟java也很像)

 

21、选择器(其实就是C中的函数指针,以及java中的Method类)

 

22、类别(Category),扩充类的功能,但不可以声明新的成员变量。

类别的应用比较广泛,譬如:第三方的Objective-C 库RegexKitLite 就是对NSString、NSMutableString 做的类别,为Objective-C 的字符类型增加了正则表达式的功能。

 

23协议@protocol,这个就是前面说的,相当于java中的interface,思想都是一种约定、规范,只是具体语法不一样罢了。

 

24、终于到了内存管理了,擦,没怎么看懂,要好好找个专题弄懂。

 

25、字符串

-(BOOL) isEqualToString: (NSString*) s

比较两个字符串是否相等,与JAVA 一致的地方是==比较指针,比较对象是否相同要用到equal 方法。

-(NSMutableString*) appendString: (NSString*) s

这与JAVA 的StringBuffer 的append 没什么区别。

 

26、数组

Cocoa 使用NSArray 表示数组,但是它不能存储基本数据类型、enum、struct、nil,只能存储Objective-C 的对象。

NSArray *array=[NSArray arrayWithObjects: @"One", @"Two", @"Three", nil];

从这个类方法arrayWithObjects 的定义可以看出,它使用nil 表示数组元素结束,这也是nil 不能存储在NSArray 中的原因。

NSMutableArray 为长度可变的数组,相当于JAVA 中的List

NSMutableArray *mArray=[NSMutableArray arrayWithCapacity: 10];

[mArray addObject: @"Apple"];//添加数组元素

NSEnumerator *e = [mArray objectEnumerator];//获取数组的迭代器,相当于JAVA 中的Iterator,reserveObjectEnumerator 用于获取反转之后的数组迭代器。与JAVA 一致的地方是你在使用迭代器时,不能对数组进行添加、删除操作。

for(NSString *ms in mArray){

NSLog(@"%@",ms);

}

//for-each 快速枚举为Objective-C 2.0 的新特性,Windows 上的GNUStep 并不支持。

 

27字典(哈希表)

NSDictionary 用于存储key-value 的数据结构,与JAVA 中的Map 类似。

NSDictionary *dic=[NSDictionary dictionaryWithObjectsAndKeys: @"Apple", @"A", @"Google",@"G", nil];//dictionaryWithObjectAndKeys 后的可变参数,每两个为一个value-key,以nil 表示结束。

NSLog(@"%@",[dic objectForKey: @"A"]);//按照指定的key 查询value

同样的有NSMutableDictionary 表示长度可变的字典。

NSMutableDictionary *mDic=[NSMutableDictionary dictionaryWithCapacity: 10];

[mDic setObject: @"Apple" forKey: @"A"];//添加value-key 对

for(id key in mDic){

NSLog(@"%@ : %@",key,[mDic objectForKey: key]);

}

//快速迭代的for-each 循环

 

28哈希Set

NSSet 表示以hash 方式计算存储位置的集合,与JAVA 中的HashSet 是一致的。在NSSet 中的每个对象都有一个唯一的hash 值,重复的对象将只能保留一个。因此,这引出了Objective-C中的对象比较问题,这需要你实现从NSObject 继承而来的如下两个方法:

- (BOOL) isEqual: (id) anObject;

- (NSUInteger) hash;

这与JAVA 的对象比较没有什么区别,两个相等的对象必须有相同的hashCode,所以这两个方法必须同时实现。

同样的,NSMutableSet 表示长度可变的哈希Set。

 

29封装类(相当于java的包装器)

前面的几个容器类的对象都不能存放基本数据结构、enum、struct、nil,怎么办呢?在JAVA中我们知道所有的基本数据类型都有对应的封装类,例如:int---Integer、boolean---Boolean,使用封装类可以把基本数据类型包装为对象,而封装类本身又有方法可以返回原来的基本数据类型。Cocoa 使用NSValue 作为封装类。

NSRect rect=NSMakeRect(1,2,30,50);//这个是在前面提到过的一个表示矩形的结构体

NSValue *v=[NSValue valueWithBytes: &rect objCType: @encode(NSRect)];

//valueWithBytes 要求传入包装数据的地址,也就是变量中存储的数据的首地址,我们依然使用C 语言的&作为地址运算符,计算指针存储的首地址。

//objCType 要求传入用于描述数据的类型、大小的字符串,使用@encode 指令包装数据所属的类型。

 

NSMutableArray *mArray=[NSMutableArray arrayWithCapacity: 3];

[mArray addObject: v];

NSRect rect2;

[[mArray objectAtIndex: 0] getValue: &rect2];

//NSValue 的-(void) getValue: (void*) value 方法可以将NSValue 中的数据内容取出,要求传入的参数是一个指针,也就是说getValue 方法将你传入的指针指向存储的数据。

//一般Cocoa 中的getXXX 方法都是这个作用,这也是为什么前面的getter 方法不要以get作为方法前缀的原因。

对于基本数据类型,你可以使用简便的NSNumber 来封装,它是NSValue 的子类。

如果你想存储空值到集合类,可以使用NSNull,它使用NSNull *n =[NSNull null];的方式创建。

 

30日期类型

Cocoa 中使用NSDate 类型表示日期。

 

31数据缓冲区(其实就是java中的字节数组)

Cocoa 中使用NSData 类型来实现缓冲区,用于存储二进制的数据类型,譬如:从网络下载回来的文件等。

NSData 是长度不可变的数据缓冲区,还有一个NSMutableData 用来存储长度可变的数据缓冲区。

 

32写入和读取属性(简直就是java序列化和反序列化的翻版)

在iPhone 的*.ipa 文件中,你经常可以看到*.plist 文件,它保存了程序的相关属性,叫做属性列表。其实它就是NSArray、NSDictionary、NSString、NSData 持久化之后的文件。

这几个类型都有一个成员方法writeToFile: (NSString*) file atomically: BOOL 用于将自己写入到一个文件。atomically 为YES 表示文件先存储到临时文件区,如果文件保存成功,再替换掉原始文件,这样的好处是可以防止在保存文件过程中出错,但是仅适用于小文件,因为你相当于是在临时文件存储区也放了一份,再加上原始文件,就是两份文件,如果文件比较大,将会占用较多的用户的磁盘空间。

如果你要持久化的类型不是上述的数组、字典、缓冲区,那该怎么办呢?Objective-C 中也有和JAVA 一样的序列化、反序列化支持,使用NSCoding 协议。NSCoding 协议定义了如下两个方法:

-(void) encodeWithCoder: (NSCoder*) coder;

-(id) initWithCoder: (NSCoder*) decoder;

第一个方法相当于编码对象,第二个方法是解码回对象,也就相当于给类型定义了一个新的init 方法而已。

 

33对象的复制

对象的复制就相当于JAVA 中的clone()方法,也就是对象的深度复制,所谓深度复制就是重新分配一个存储空间,并将原对象的内容都复制过来,从这些描述可以看出,复制也会分配空间,那就是你要对复制出来的对象release,就是前面所说的alloc、new、copy 操作创建的对象,要手工release。

Objective-C 中的一个对象是否可以被复制,要看它的类型是否遵循NSCopying 协议,这个协议中有个复制方法-(id) copyWithZone: (*NSZone) zone 需要我们去实现。

 

34多线程

Objective-C 的多线程编程与JAVA 语言极其类似分为原始的线程操作、线程池两种,后者其实就是使用队列等机制对前者的封装。JAVA 也一样,原始的线程操作使用Thread 类,线程池的操作使用java.util.concurrent.*中的类库。

Objective-C 中NSThread 类型表示线程NSCondition 用于执行同步操作,在功能和用法上相当于JAVA 中的java.util.concurrent.*包中的Lock 对象。

另外,Objective-C 也支持@synchronized 指令做代码同步,写法也和JAVA 中的很相似。

@synchronized(要加锁的对象){

//同步执行的代码

}

 

另外比较有趣的是,如果你想更新UI 上的某一个部件,就需要在发起的新线程里调用UI 所在的主线程上的一个方法,新线程不能直接访问主线程的方法,需要在run 方法中使用如下的方法:

- (void) performSelectorOnMainThread: (SEL) aSelector withObject: (id) arg waitUntilDone: (BOOL) wait

如果你对javaswing熟悉的话,你应该知道在UI界,大多数更新界面的都必须在一个单线程中执行,因为如果更新界面是多线程的话会很难处理的,java swing处理的方法是更新界面的代码放在专门更新UI的线程下执行,其实这里IOS也是这么一个思想。

 

Objective-C 使用NSOperation、NSOperationQueue 两个类型实现线程池的操作,NSOpertion就好比JAVA 中的Runnable,其中的main(名字有点儿奇怪)方法也就是你要执行的操作,NSOperationQueue 是一个线程池队列,你只需要把NSOperation 添加到NSOperationQueue,队列就会retain 你的NSOperation,然后执行其中的操作,直到执行完毕。队列中会有多个操作,队列会按照你添加的顺序逐个执行,也就说队列中的任务是串行的。

java一样,如果线程池可以满足你的业务需求,尽量使用线程池,而不是原始的NSThread,因为使用线程池屏蔽了许多线程自身需要处理的问题,代码也更加简洁。

 

35KVC 与KVO(这个话题真高级)

KVC 是NSKeyValueCoding 的缩写,它是Foundation Kit 中的一个NSObject 的Category,作用你可以类比JAVA 中的反射机制,就是动态访问一个对象中的属性。

KVC 在解析key 的字符串的时候,是会比你正常调用setter、getter 要慢的,而且编译器无法在编译器对你的方法调用做出检查(因为你的属性名都是字符串,只有运行时才会知道你有没有写错),出错的几率也会提高,所以请不要随意使用KVC,而省去setter、getter 方法。KVC 一般用于动态绑定,也就是运行时才能确定谁调用哪个方法,编译期并不确定。

KVO就是NSKeyValueObserving的缩写,它也是Foundation Kit中的一个NSObject的Category,KVO 基于KVC 实现,基于观察者设计模式(Observer Pattern)实现的一种通知机制,你可以类比JAVA 中的JMS,通过订阅的方式,实现了两个对象之间的解耦,但又可以让他们相互调用。(具体请查资料)

 

36谓词NSPredicate

Cocoa 提供了NSPredicate 用于指定过滤条件,谓词是指在计算机中表示计算真假值的函数,它使用起来有点儿像SQL 的查询条件,主要用于从集合中分拣出符合条件的对象,也可以用于字符串的正则匹配

2
0
分享到:
评论

相关推荐

    Objective-C与Objective-C++的混用代码示例

    Objective-C是基于C语言的,主要用于构建iOS和macOS应用程序,而Objective-C++则是Objective-C的一个扩展,它引入了C++的特性,使得开发者可以同时利用Objective-C的动态特性和C++的面向对象编程能力。 ### ...

    C语言主要知识点巩固(学习Objective-C 的前提)

    在掌握了这些C语言基础知识后,你将更好地理解和学习Objective-C,因为Objective-C是在C语言的基础上扩展的面向对象编程语言,它保留了C的大部分语法,并引入了类、消息传递等面向对象特性。因此,牢固的C语言基础...

    在Objective-C中使用C++

    需要使用`@interface`定义一个桥接接口,让C++类遵循Objective-C协议,或者使用Objective-C++(`.mm`文件)来处理转换。 4. **内存管理** Objective-C使用ARC(Automatic Reference Counting)自动管理内存,而C++...

    Objective-C基础教程(入门教程).pdf

    Objective-C是一种广泛用于苹果平台应用程序开发的编程语言,它是C语言的一个超集,并加入了Smalltalk风格的消息传递机制。本篇教程主要面向初学者,介绍了Objective-C的基础知识点和一些核心概念。 1. Objective-C...

    Objective-C语言入门教程&深入浅出,理论实践相结合.pdf

    Objective-C语言入门教程&深入浅出,理论实践相结合 Objective-C语言入门教程&深入浅出,理论实践相结合 Objective-C语言入门教程&深入浅出,理论实践相结合 Objective-C语言入门教程&深入浅出,理论实践相结合 ...

    Objective-c语言学习-快速入门完整版完整版

    "第八讲 内存管理"是Objective-C开发中非常重要的一个环节,讲解了自动引用计数(ARC)和手动内存管理(MRC)的原理,以及如何避免内存泄漏。 最后,"第九讲 Foundation框架"介绍了苹果的基础框架,它提供了一系列...

    Objective-C Runtime测试代码

    这意味着Objective-C语言不仅需要一个编译器,还需要一个运行时系统来执行编译的代码。Runtime系统是一种用于Objective-C语言的操作系统,它使OC语言工作起来。  Runtime的核心是在运行时动态操作类和消息分发给...

    Objective-C高级编程 iOS与OS X多线程和内存管理_Objective-C_ios_

    本书主要围绕Objective-C语言在iOS和OS X操作系统上的应用,特别是针对多线程和内存管理这两个核心主题进行深入讲解。 在iOS和OS X开发中,多线程技术是提升应用程序性能和用户体验的关键。Objective-C提供了多种...

    Objective-C语言教程

    希望这个简单的Objective-C语言教程能够为你提供一个入门的起点。Objective-C是一种面向对象的编程语言,广泛应用于Mac OS和iOS开发。通过学习Objective-C的基本语法、类和对象、控制流程和方法等内容,你将能够编写...

    Objective-C 2.0 运行时系统编程指南

    因此,Objective-C不仅依赖于编译器,还需要一个强大的运行时系统来执行已经编译好的代码。运行时系统在Objective-C中扮演着类似操作系统的角色,为Objective-C应用程序提供了基础支撑。 #### 文档结构与目的 本...

    从 C++ 到 Objective-C 快速精通

    《从 C++ 到 Objective-C 快速精通》是一本专为C++程序员设计的指南,旨在帮助他们迅速掌握Objective-C这门强大的编程语言。Objective-C是苹果平台上的主要开发语言,尤其在iOS和macOS应用程序开发中占据核心地位。...

    Objective-C编程全解最新版.pdf.zip

    14. **Delegation**:代理模式是Objective-C中常用的设计模式,一个对象可以作为另一个对象的代理,处理特定事件或行为。 15. **GCD(Grand Central Dispatch)**:GCD是Apple的并发编程技术,用于在多核处理器上管理...

    Objective-C的语法与Cocoa框架.pdf

    Objective-C语言是一种面向对象的编程语言,它是C语言的一个超集,专门为MacOSX和iOS平台的开发设计。作为苹果官方支持的语言,Objective-C拥有悠久的历史和深厚的技术底蕴。它从C语言发展而来,对C语言的结构和语法...

    From C++ to Objective-C

    尽管如此,Objective-C本身也可以不依赖于Cocoa框架运行,例如gcc编译器就是一个例子。在MacOSX平台上,Cocoa框架是实现大部分功能的关键组件,但开发者应该清楚区分开Objective-C语言本身和Cocoa框架。 对于C++...

    Object-C语言教程-提供了 Objective-C 的基本语法和一些示例,希望能够帮助你快速入门 Objective-C

    作为C语言的一个超集,Objective-C允许开发者直接使用C语言代码。此外,它还借鉴了C++的一些特性,尽管它并非C++的直接子集。 Objective-C由苹果公司在其操作系统macOS和iOS的开发中广泛使用,是这两个平台上应用...

    objective-c基础教程

    - **Xcode集成**: Xcode是苹果官方提供的集成开发环境(IDE),它集成了Objective-C的编辑器、编译器和调试器等功能,为开发者提供了一个高效便捷的开发平台。 #### 三、Objective-C语言特点 Objective-C继承了C语言...

    Objective-C程序设计 第6版 pdf

    Objective-C是一种强大的面向对象编程语言,它在Apple的Mac OS X和iOS操作系统中扮演着核心角色,用于构建高质量的应用程序。《Objective-C程序设计 第6版》是学习和深入理解这种语言的重要参考资料,旨在帮助开发者...

    Objective-C2.0程序设计第二版中文版及代码

    Objective-C 2.0是一种强大的面向对象的编程语言,它主要应用于Apple的iOS和macOS操作系统。本资源包含了《Objective-C 2.0程序设计》的第二版中文版及其源代码,以及《Effective Objective-C 2.0》的英文版电子书。...

Global site tag (gtag.js) - Google Analytics