ios-基础之【11】-类的category
2016-03-27 10:37
344 查看
原文链接:http://www.jianshu.com/p/535d1574cb86
参考文:http://www.cnblogs.com/crazypebble/p/3439261.html
类别的简介
在开发中有时会用到Category,类别有三个作用:(1)可以将类的实现分散到多个不同文件或多个不同框架中,方便代码管理。也可以对框架提供类的扩展(因为框架类没有源码,不能修改)。 (2)创建对私有方法的前向引用:如果其他类中的方法未实现,在你访问其他类的私有方法时编译器报错这时使用类别,在类别中声明这些方法(不必提供方法实现),编译器就不会再产生警告 (3)向对象添加非正式协议:创建一个NSObject的类别称为“创建一个非正式协议”,因为可以作为任何类的委托对象使用。有两个方面的局限性: (1)无法向类中添加新的
但是却又经常听说Category只能添加方法不能添加属性,额。。。看这里:
屏幕快照 2016-03-15 21.50.22.png
哦呦,属性哎!!!!什么鬼?不是不能添加属性吗????这个问题真心烦人啊,怎么回事儿呢?以前看的他们说的Category不能添加属性难道不对吗?(⊙o⊙)…相信很多童鞋会有和我一样的疑问。。。
首先解释一下属性和成员变量的区别吧:
属性和成员变量的区别
我们声明了一个属性,因为现在我们用的编译器已经是LLVM了,所以不再需要为属性声明实例变量了。如果LLVM发现一个没有匹配实例变量的属性,它将为你生成以下划线开头的实例变量_myButton,不需要自己手动再去写实例变量。而且也不需要在.m文件中写
注意:
假如在Objective-C中我们
.m文件中,self.name 这样的表达式是错误的。xcode会提示你使用->,改成self->name就可以了。因为oc中点表达式是表示调用方法,而上面的代码中没有name这个方法。
Objective-C中的点语法说明:
如果点表达式出现在 "=" 左边,该属性名称的setter方法将被调用。如果点表达式出现在右边,该属性名称的getter方法将被调用。所以在oc中点表达式其实就是调用对象的setter和getter方法的一种快捷方式。
@synthesize 还有一个作用,可以指定与属性对应的实例变量,例如
在实际项目中,我们一般在.m中这样写:
如果.m文件中写了
Category中属性Property
类别中只能添加方法,不能添加实例变量。我们经常看见在类别中这样写:
在这种情况下是不会自动生成实例变量的。这里添加的属性,其实是添加的setter和getter方法。
屏幕快照 2016-03-15 21.21.14.png
那为什么Objective-C类别中可以添加方法和属性但是不能添加实例变量呢?
在Objective-C提供的runtime函数中,确实有一个class_addIvar()函数用于给类添加成员变量,但是文档中特别说明:
意思是说,这个函数只能在“构建一个类的过程中”调用。一旦完成类定义,就不能再添加成员变量了。经过编译的类在程序启动后就
因为方法和属性并不“属于”类实例,而成员变量“属于”类实例。我们所说的“类实例”概念,指的是一块内存区域,包含了isa指针和所有的成员变量。所以假如允许动态修改类成员变量布局,已经创建出的类实例就不符合类定义了,变成了无效对象。但方法定义是在objc_class中管理的,不管如何增删类方法,都不影响类实例的内存布局,已经创建出的类实例仍然可正常使用。
参考文:http://www.cnblogs.com/crazypebble/p/3439261.html
类别的简介
在开发中有时会用到Category,类别有三个作用:(1)可以将类的实现分散到多个不同文件或多个不同框架中,方便代码管理。也可以对框架提供类的扩展(因为框架类没有源码,不能修改)。 (2)创建对私有方法的前向引用:如果其他类中的方法未实现,在你访问其他类的私有方法时编译器报错这时使用类别,在类别中声明这些方法(不必提供方法实现),编译器就不会再产生警告 (3)向对象添加非正式协议:创建一个NSObject的类别称为“创建一个非正式协议”,因为可以作为任何类的委托对象使用。有两个方面的局限性: (1)无法向类中添加新的
实例变量,类别没有位置容纳实例变量。(2)名称冲突,即当类别中的方法与原始类方法名称冲突时,类别具有更高的优先级。类别方法将完全取代初始方法从而无法再使用初始方法。这个类似于方法的重载,但是这里是直接覆盖了原方法。
但是却又经常听说Category只能添加方法不能添加属性,额。。。看这里:
屏幕快照 2016-03-15 21.50.22.png
哦呦,属性哎!!!!什么鬼?不是不能添加属性吗????这个问题真心烦人啊,怎么回事儿呢?以前看的他们说的Category不能添加属性难道不对吗?(⊙o⊙)…相信很多童鞋会有和我一样的疑问。。。
首先解释一下属性和成员变量的区别吧:
属性和成员变量的区别
@property (nonatomic, strong) UIButton *myButton;
我们声明了一个属性,因为现在我们用的编译器已经是LLVM了,所以不再需要为属性声明实例变量了。如果LLVM发现一个没有匹配实例变量的属性,它将为你生成以下划线开头的实例变量_myButton,不需要自己手动再去写实例变量。而且也不需要在.m文件中写
@synthesize myButton;也会自动为你生成setter,getter方法。@synthesize的作用就是让编译器为你自动生成
setter与
getter方法。那么在
.m文件中可以直接的使用_myButton实例变量,也可以通过属性self.myButton.两者都是一样的。
注意:
这里的self.myButton其实是调用的myButton属性的getter/setter方法。
假如在Objective-C中我们
@interface MyViewController:UIViewController { NSString *name; } @end
.m文件中,self.name 这样的表达式是错误的。xcode会提示你使用->,改成self->name就可以了。因为oc中点表达式是表示调用方法,而上面的代码中没有name这个方法。
Objective-C中的点语法说明:
如果点表达式出现在 "=" 左边,该属性名称的setter方法将被调用。如果点表达式出现在右边,该属性名称的getter方法将被调用。所以在oc中点表达式其实就是调用对象的setter和getter方法的一种快捷方式。
@synthesize 还有一个作用,可以指定与属性对应的实例变量,例如
@synthesize myButton = xxxx;那么
self.myButton其实是操作的实例变量
xxxx,而不是
_myButton了。
在实际项目中,我们一般在.m中这样写:
@synthesize myButton;这样写了之后,那么编译器会自动生成
myButton的实例变量,以及相应的
getter和
setter方法。注意:
_myButton这个实例变量是不存在的,因为自动生成的实例变量为
myButton而不是
_myButton,所以现在
@synthesize的作用就相当于指定实例变量;
如果.m文件中写了
@synthesize myButton;那么生成的实例变量就是
myButton;如果没写
@synthesize myButton;那么生成的实例变量就是
_myButton。所以跟以前的用法还是有点细微的区别。
Category中属性Property
类别中只能添加方法,不能添加实例变量。我们经常看见在类别中这样写:
@property (nonatomic, assign) CGFloat x;
在这种情况下是不会自动生成实例变量的。这里添加的属性,其实是添加的setter和getter方法。
屏幕快照 2016-03-15 21.21.14.png
那为什么Objective-C类别中可以添加方法和属性但是不能添加实例变量呢?
在Objective-C提供的runtime函数中,确实有一个class_addIvar()函数用于给类添加成员变量,但是文档中特别说明:
This function may only be called after objc_allocateClassPair and before objc_registerClassPair. Adding an instance variable to an existing class is not supported.
意思是说,这个函数只能在“构建一个类的过程中”调用。一旦完成类定义,就不能再添加成员变量了。经过编译的类在程序启动后就
runtime加载,没有机会调用
addIvar。程序在运行时动态构建的类需要在调用
objc_registerClassPair之后才可以被使用,同样没有机会再添加成员变量。那为什么可以在类别中添加方法和属性呢?
因为方法和属性并不“属于”类实例,而成员变量“属于”类实例。我们所说的“类实例”概念,指的是一块内存区域,包含了isa指针和所有的成员变量。所以假如允许动态修改类成员变量布局,已经创建出的类实例就不符合类定义了,变成了无效对象。但方法定义是在objc_class中管理的,不管如何增删类方法,都不影响类实例的内存布局,已经创建出的类实例仍然可正常使用。
相关文章推荐
- ios-基础之【10】-NSTimer
- iOS 断言 NSAssert的使用 调试程序错误
- ios-其他之【1】-证书
- 玩转iOS开发 - 数据缓存
- iOS开发 ☞ 常用终端命令
- iOS中几种数据持久化方案-转自简书
- iOS 使用NSMutableAttributedString实现不同颜色尺寸文字 —— HERO博客
- OC阅读笔记三:动态绑定
- iOS BeizierPath 绘图
- iOS-消息转发机制
- IOS基础-事件机制
- IOS 杂笔-16 (-(void)scrollViewDidEndScrollingAnimation:方法使用注意)
- IOS 禁止横屏、键盘的隐藏、键盘出现时上移后面的视图
- 我的iOS开发入门自学路径
- ios 从url字符串中获取图片名字
- Html - 仿Ios assistiveTouch 悬浮辅助球工具
- iOS导航条颜色色差的问题
- iOS开发推荐DMG资源
- iOS动效学习-推荐资料(最全)
- iOS开发常用网址(最全)