一璃诀、類別
類別就是類的擴展月培,在不改變類的結構的同時,可以像類中添加方法(不能添加成 員變量)
二夫椭、類別作用
- 可以將類的實現分散到多個不同文件或多個不同框架中步咪,方便代碼管理。也可以對框架提供類的擴展
- 使用匿名類別模擬私有方法
- 類別可以實現非正式協(xié)議
- 創(chuàng)建對私有方法的前向引用
其中對第四點進行解釋:
創(chuàng)建一個Student類益楼,有一個私有方法
<pre>
import <Foundation/Foundation.h>
@interface Student : NSObject
@end
</pre>
<pre>
import "Student.h"
@interface Student()
{
// 匿名類別中的成員變量猾漫,相當于全局變量來使用。
int a ;
}
-(void)privateMethod;
@implementation Student
// 實現的私有方法感凤,不能在本類以外的任何地方調用悯周。
-(void)privateMethod
{
NSLog(@"private mythod");
}
@end
</pre>
創(chuàng)建一個Student類的類別,.h文件聲明了一個privateMethod陪竿,但是在.m中沒有實現方法
<pre>
@interface Student (HavePrivateMethod)
-(void)privateMethod;
@end
</pre>
在 main.m中調用禽翼,記住import這個類別
<pre>
import <Foundation/Foundation.h>
import "Student.h"
import "Student+ HavePrivateMethod.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
Student *s1 = [[Student alloc] init];
[s privateMethod];
}
return 0;
}
</pre>
三屠橄、類別注意
- 通過繼承關系,父類中的類別的方法闰挡,可以繼承給子類锐墙。(想調用類別中的方法,就要引用頭文件)长酗。
- 類別中聲明的方法可以不實現 (但是擴展不可以)
- 如果分類和原來類出現同名的方法溪北,優(yōu)先調用分類中的方法, 原來類中的方法會被忽略
四、給類別添加屬性的方法
首先我們看下以下代碼
<pre>
@interface UIView (nl_Frame)
@property (nonatomic, assign) CGFloat nl_width;
@end
</pre>
<pre>
@implementation UIView (nl_Frame)
(void)setNl_width:(CGFloat)nl_width {
CGRect frame = self.frame;
frame.size.width = nl_width;
self.frame = frame;
}(CGFloat)nl_width {
return CGRectGetWidth(self.frame);
}
@end
</pre>
在這里給 UIView增加了一個寬度屬性:nl_width夺脾,而且為其實現了相應的 getter和 setter方法(nl_width之拨、setNl_width:)。這兩個方法實際上訪問的 frame屬性咧叭,如果你有注意過的話蚀乔,你會發(fā)現frame也是定義在分類里邊的:
<pre>
@interface UIView(UIViewGeometry)
@property(nonatomic) CGRect frame;
//...
@end
</pre>
可以看到,這種定義在分類里的屬性菲茬,實際上是實現了相應的方法吉挣,并在方法里邊通過訪問其它屬性來達到目的。這通常用來簡化某些操作婉弹,比如定義咱們這個分類后听想,獲取視圖的寬度只要view.nl_width就可以了,再不用CGRectGetWidth(view.frame)來得到寬度马胧,而且可讀性也增強了很多汉买。
當然還有另一種方法來實現類別屬性
首先得先引入頭文件:
<pre>
import <objc/runtime.h>
</pre>
可以在該頭文件中找到三個允許你將任何鍵值在運行時關聯(lián)到對象上的函數
<pre>
objc_setAssociatedObject // 設置關聯(lián)對象
objc_getAssociatedObject // 獲取關聯(lián)對象
objc_removeAssociatedObjects // 移除關聯(lián)對象
</pre>
知道這個之后我們來實踐下添加屬性
<pre>
@interface Person (Sport)
@property (nonatomic, assign) NSUInteger age;
@end
</pre>
<pre>
@implementation Person (Sport)
static void * age_key = & age_key;
(void) setAge:(NSUInteger)age {
objc_setAssociatedObject(self, age_key , @(age), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}(NSUInteger)age {
return [objc_getAssociatedObject(self, age_key) unsignedLongValue];
}
@end
</pre>
關聯(lián)對象在使用時,需要咱們提供一個指針佩脊,即key蛙粘,用來識別被關聯(lián)的對象。咱們這里的key就是一個空指針:nl_sqlite_rowid_key威彰。當然出牧,你也可以@selector(rowid)來作為 key(常用)。
于是歇盼,就可以這么來用了:
<pre>
Person *person = [Person new];
person.age = 1;
</pre>
注意咯:
<pre>
關聯(lián)類型 等效的@property屬性
OBJC_ASSOCIATION_ASSIGN assign
OBJC_ASSOCIATION_RETAIN_NONATOMIC nonatomic, retain
OBJC_ASSOCIATION_COPY_NONATOMIC nonatomic, copy
OBJC_ASSOCIATION_RETAIN retain
OBJC_ASSOCIATION_COPY copy
</pre>