Objective-C一瞥

Objective-C一瞥,第1张

概述转载自:http://www.cnblogs.com/hucn/archive/2011/12/10/2283646.html 学习Objective-C有段时间了, 写些心得和大家分享讨论. 我的"母语"是C++, 所以会通过和C++比较来加深理解. 文章主要介绍Objective-C的基础知识, 适合Objective-C新手, 熟悉Objective-C的朋友可以不看了, 或是帮忙挑挑错~

转载自:http://www.cnblogs.com/hucn/archive/2011/12/10/2283646.html

学习Objective-C有段时间了,写些心得和大家分享讨论. 我的"母语"是C++,所以会通过和C++比较来加深理解. 文章主要介绍Objective-C的基础知识,适合Objective-C新手,熟悉Objective-C的朋友可以不看了,或是帮忙挑挑错~

 

1. C和Objective-C

Objective-C是C的超集,即支持所有C的特性,包括符号重定义typedef,类型转换,宏. 增加了面向对象,异常处理,Block,CatgorIEs等功能, 因此熟悉C的朋友学习Objective-C也会很容易.

2. OO特性

Objective-C是一门面向对象的语言,具有纯正的OO的设计思想. 支持单一继承,数据封装@private和@protected,支持运行时多态.

和C++相比,Objective-C在语言层面引导我们使用OOP设计. 用@interfaced定义类类型,@protocol定义接口,将实现继承和接口继承分开,支持一个实现继承和多个接口继承.

细节

在Cocoa下Objective-C的对象都继承与NSObject(NS是NeXTSTEP的缩写),这个类提供了基本的OO的支持. 包括运行时的动态类型,判断对象是否支持某接口,判断是否实现了某函数.

Cocoa采用依赖倒置的设计,使得我们必须采用面向对象的思想进行设计. 这和C++或其他一些语言的开发不大一样,在C++中,我们来控制程序的主要逻辑,我们使用库是为了实现某个功能. 一个好的设计师,可能会把具体的实现抽离出一层,在抽象的接口中处理主要的逻辑,在具体的实现中对抽象进行具现化处理,这样使多个实现低耦合. 这其实就是DIP(Dependency-Inversion Principles)的思想. 而Cocoa库把这些都做好了,我们使用Cocoa库时不关心程序的主要逻辑,只是在处理某个具体的功能. 和以前的思路刚好相反,具体见库和设计支持部分.

3. 内存管理

对与每个C++程序员,内存管理是让头疼的事情,因此在STL和Boost中都提供了智能指针帮助内存管理. Java则通过JVM提供内存的检查和自动回收,我们不需要也不能手动释放内存. Objective-C则做出了折中的方案,提供三个内存管理方式:

1. 每个Objective-C对象内置引用计数管理,当引用计数为0时自动释放;

2. 提供以一次函数调用为生存期的系统管理的对象,在函数中申请,函数出栈时释放. 和C++中用局部对象的构造和析构控制资源很像.

3. 提供系统管理的内存池NSautoRealeasePool,可以通过创建和释放内存池控制内存申请和回收的时机. 

 

细节:

所有NSObject的子类都可以使用内置的引用计数. 通过retain增加引用计数,release减小计数,当引用计数为0时会自动调用realloc函数进行析构.

通常引用计数和Objective-C的存取器功能配合使用,存取器和Java的setter和getter功能很像,只是额外提供了对线程安全和引用计数的支持. 存取器通过retain assign copy控制引用计数. retain即引用计数加一,即对某对象强引用; assign不影响对象的引用计数,对其弱引用; copy是将对象浅拷贝一份,使其具有独立的生存期.

此外,容器也会影响对象的生存期,在容器中总结. XCode中提供的引用分析工具Analyze和内存泄漏检查工具,更提供了强大的编译期和运行期的内存检测,在工具中总结.

Tips:

1 通过Objective-C控制内存比较容易,首先需要根据期望对象的生存期选择合适的管理方式.

第1种方式是通过alloc – initial方式创建的,创建后引用计数+1,此后每retain一次引用计数+1,那么在程序中做相应次数的release就好了.

第2种方式一般是由类的静态方法创建的,函数名中不会出现alloc或init字样,如[Nsstring string]和[NSArray arrayWithObject:],创建后引用计数+0,在函数出栈后释放,即相当于一个栈上的局部变量. 当然也可以通过retain延长对象的生存期.

第3种方式是由autorelease加入系统内存池,内存池是可以嵌套的,每个内存池都需要有一个创建释放对,就像main函数中写的一样. 使用也很简单,比如[[[Nsstring alloc]initialWithFormat:@”hey you!”] autorelease],即将一个Nsstring对象加入到最内层的系统内存池,当我们释放这个内存池时,其中的对象都会被释放.

2 和C++的smart pointer——shared_ptr<>一样,多个对象不能循环强引用,否则会泄漏. 比如,UIVIEwController对象强引用UIVIEw,@property UIVIEw *vIEw(retain); 则UIVIEw中若要引用UIVIEwController需要弱引用,即@property UIVIEwController *controller(assign);

  4. 动态特性

Objective-C是一个动态语言,具有在三个层次的动态支持.

1 动态类型 dynamic tyPing

ID类型是Objective-C提出的类型,是一个指向Object的指针,编译器对所有ID类型的对象不会进行编译期型别检查,这些工作可能会延迟到运行时我们自己做,或者不做.

ID是强大的工具,举例来说一个NSArray,一个Objective-C的顺序容器,可以用这个特性存储不同型别的对象,他们的类型都是ID. dynamic tyPing是后面两个动态特性的基础.

2 动态绑定 dynamic binding

C++的多态是由虚函数表vptr实现的,简单说来虚函数表就是一个间接层,将虚函数的具体实现和对象的类型剥离. 运行时根据虚函数表而不是变量的类型去执行函数,这其实就是动态绑定的概念.

细节:

NSObject中维护一个叫做指针isa,指向一个Class类型的结构体,  结构体中维护了父类的Class结构体指针以及成员函数指针表dispatch table,其中每个表项存储了SEL和IMP的对应关系. 简单说,SEL就是一个成员函数,IMP就是一个C的函数实现. 每次调用一个Object的成员函数SEL时,会索引到这个isa,然后查询dispatch table对应的表项,找到对应的实现. 并且dispatch table可以在运行时查询,修改,添加. 这样我们就可以通过维护类的dispatch table动态查询,修改对象的表现. 比如,通过responsToSelector:(SEL)selector,可以查询到table中SEL函数对于的IMP是否有效.

 

3 动态加载 dynamic loading

动态加载是同过Bundles实现的,XCode将程序中需要的Code,Nib,picture等资源打包成bundles. 由系统控制资源的加载,在内存受限的移动设备中,动态加载是很强大的功能.我们还可以通过NSBundle在运行期控制资源加载.

5. 容器

Cocoa提供几种主要的容器:

顺序容器 NSArray

集合容器 NSSet

字符串 Nsstring

Map NSDictionary

每种都提供了同STL一样强大的 *** 作. 另外上面的所有容器都是初始化后不能修改的,每种有对应的可修改版本,如NSMutableArray. 可见Cocoa对只读的容器和可写容器进行了不同的优化策略.

6. 库与设计支持

1 MVC和UIKit

MVC即Model VIEw Control,Model代表数据,VIEw代表显示,Control代表Model和VIEw之间的控制. MVC是一种复合的设计模式,将数据、显示和逻辑解耦,为了方便的修改数据而不影响显示部分,或是修改显示而不需要调整数据.

Cocoa的UIKit是iOS的界面设计库,UIKit是按照MVC模式设计的,它使得iOS的UI开发快捷并灵活. VIEw对应UIVIEw,Control对应UIVIEwController.

UIVIEw负责屏幕上一个矩形区域的显示和用户交互,通过继承UIVIEw可以定制具体的渲染行为和交互行为.

UIVIEwController负责组织一组UIVIEw, 响应Model的变化,处理设备方向响应,组织特殊的UIVIEw,如UITabbarController组织屏幕下方的一组Tab bar,UINavigationController组织屏幕上方的导航栏.

细节

我们在界面上看到的多数元素都是UIVIEw的特化,比如按钮UIbutton、标签UILabel、输入框UITextVIEw都UIVIEw的子类. 它们由一个树来组织,每个UIVIEw实例有一个super vIEw,UIVIEw *superVIEw,和若干subVIEw NSSet *subVIEws. 每个UIVIEw有一个tag,默认为0,通过tag可以方便对UIVIEw访问.

这样一棵树由一个UIVIEwController实例所管理,UIVIEwController的vIEw成员指向树的根节点. VIEwController除了管理这些VIEw还处于responder chain中,若所有的UIVIEw都没有处理一个交互,UIVIEwController可以处理,否则交给vIEw的super vIEw处理. 这个super vIEw也会在另一颗树中,并由另一个UIVIEwController实例管理着.

2 delegation、依赖倒置和target-action mechanism

UIKit中到处都是delegation的影子,每个UIVIEw或是UIVIEwController或UIApplicationDelegate都处理大量的delegation. 这样带来的好处是我们不用关心应用程序是怎么执行起来的,只要处理我们感兴趣的delegation就好了. 比如我们想做一个触碰屏幕的相应,就在UIVIEw的具现化中实现touchBegan:这样一个函数就好了,或者我们想在某个VIEw出现的时候初始化些东西,只需在UIVIEw中实现VIEwDIDLoad就好了. 其他的事情都交给UIKit处理,这也是为什么main函数如此简单.

这样我们就"被迫"用依赖倒置原则设计程序,因为抽象的逻辑已经写好了,我们就根据他们写写细节吧.

target-action mechanism是UIKit处理事件Event的方法. 做过UI程序的人都知道,UI最烦的就是处理各种事件了,事件多起来逻辑可能很复杂. 这个机制尽可能的减少事件的触发和处理的耦合关系.

通过对一个vIEw调用-(voID)addTarget:(ID)target: (SEL)action: forControlEvents:(UIControlEvents)controlEvents; 函数设定当这个VIEw的某个cotrolEvent发生时调用target的action函数. 本质上还是delegation,但是这里的方便之处在于可以多次调用函数为一个Event添加多个响应,也可以通过将target参数设为nil将事件传递到responder chain上. 这样我们可以在运行时设定事件的处理方法,而不需改变处理方的实现.

3 观察者模式NSNotificationCenter

在Cocoa中提供了观察者模式的支持,用NSNotificationCenter的全局实例,可以方便的添加观察者和对观察者发出Notification.

主要的函数有,

// 返回一个NSNotificationCenter全局实例,类似于单件Singleton.

+ (ID)defaultCenter;

// 为anObject添加一个观察者observer,observer的aSelector用于接收Notification,Notification的名字是aname.

- (voID)addobserver:(ID)observer selector:(SEL)aSelector name:(Nsstring *)aname object:(ID)anObject;

// 发送所有anObject的以aname为名的Notification

- (voID)postNotification:(Nsstring *)aname object:(ID)anObject;

Tips:

Notification与delegation

两者都是解耦事件的触发和响应的,delegation更适用于一个触发一个响应的情况,并且响应函数的参数为发出delegation的对象,无法区分是这个对象的哪个Event. 而Notifaction则更是用一个触发响应多个响应情况,当Notificationtable庞大时可能会影响效率.

7. 安全性

C++中对空指针是很危险的,对空指针进行寻址会抛出异常,若不进行处理会导致程序崩溃. 因此会提倡RAII.

而Objective-C中对null的寻址可以正常进行,只是什么都没做. 这样很大程度上减少了这类异常,增强了程序的健壮性,但也为调试程序增加了一些困难.

  8. 工具

XCode集成了很多优秀的编译器,调试器,以及分析工具. 这里挑我熟悉的几点说明.

XCode有方便的编辑提示,快速的代码补全.

XCode在代码编辑期就对代码进行实时编译并给出提示,越早的发现错误,修改的代价就越低.

XCode提供可视化界面编辑工具,IB Interface Builder

XCode提供强大的Analyze功能,方便的进行引用计数分析,指出可能的内存泄漏或是提前释放,不仅能够找到可能的位置,还能找到泄漏或释放的原因,并用可视化界面帮助程序要分析.

XCode提供NSZombIE和Instruments方便的追宗、分析并解决程序崩溃的难题.

 

9. 其他特性

和C++相比Objective有一些其他特性,包括支持的和不支持的:

不支持运算符重载

不支持模板

支持CategorIEs 我理解CategorIEs就是开放了类的定义,可以方便的对已有类进行扩展. 就像C++中namespace是开放的,可扩展的一样.

Block Block就像是C++0x中的lambda表达式功能,可以定义匿名函数作为简单调用或参数传递. 和lambda不同的是,Block可以 *** 作local变量,这使得Block的用途更为广泛.

@H_563_419@ 总结

以上是内存溢出为你收集整理的Objective-C一瞥全部内容,希望文章能够帮你解决Objective-C一瞥所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/1056412.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-25
下一篇2022-05-25

发表评论

登录后才能评论

评论列表(0条)

    保存