OC學習六

OC的集合是不允許存入基本類型的,所以NSNumber類就是講基本類型封裝一下,然後存進去,這個類似於Java中的自動裝箱0和自動拆箱,Java中的集合其實也不允許存入基本數據類型,但是我們仍然可以操作,是因爲有自動裝箱和拆箱。
爲什麼基本類型不能存入到集合中?
是因爲在操作集合的時候會操作集合元素中的方法,但是基本數據類型是沒有方法的。

KVC和KVO

OC中的KVC操作和Java中使用反射機制去訪問類的private權限變量一樣。這樣會破壞類的封裝性,類中private關鍵字標記的屬性或者方法就不希望外界去訪問,但是有的時候真的需要這樣做。下面就舉個例子:|
一個Person類中定義兩個屬性 name和dog都是private的。

//Person的.h文件 NSDog是一個沒有參數沒有方法的類 _name和_dog是沒有set和get方法的
@interface Person:NSObject{
    @private
        NSString *_name;
        NSDog *_dog;

        NSInteger *_age;
}
@end

//--------測試代碼---------
//KVC設置值時,如果屬性有set方法,則優先調用set方法,如果沒有則直接設置上去,get方法類似
Person *P = [[Person alloc] init];
[p setValue:@"zhangsan" forKey:@"name"];

Dog *dog = [[Dog alloc] init];
[p setValue:dog forKey:@"dog"];

//-----------讀取--------
NSString *name = [p valueForKey:@"name"];
//如果設置基本數據類型,需要將基本數據類型轉化爲NSNumber,在設置值的時候,會有自動解包的過程
[p setValue:@22 forKey:@"age"];

KVO 添加監聽對象
第一個參數:addObserver:self 監聽者
第二個參數:forKeyPath:@"hapyValue" 監聽對象的屬性名
第三個參數:options  監聽這個屬性的狀態,這裏可以用 | 進行多種組合操作,屬性的新值和舊值
第四個參數:Context:@"context" 傳遞內容給監聽方法

[_children addObserver:self forKeyPath:@"hapyValue" options:NSKeyValueObservingOptionNew |NSKeyVauleObservingOptionOld Context:@"context"];

 監聽方法
第一個參數:(NSString *)keyPath 鍵值路徑
第二個參數:ofObject:(id)object 監聽對象
第三個參數:change:(NSDictionary *)change 變化的值
第四個參數:context:(void *)context 傳遞的內容

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
    if([keypath isEqualToString:@"hapyValue"]){
        NSNumber *hapyValue = [change objectForKey:@"new"];
        NSInteger *value = [hapyValue integerValue];
        if(value <90){
            //do somthing...
        }
    }
}

銷燬方法:

-(void)dealloc{
    [_children removeObserver:self forKeyPath:@"hapyValue"];
}

 

NSNotificationCenter 通知

KVO只用來監聽屬性值的變化,這個發送監聽的操作是系統控制的,我們只能控制監聽操作,類似於Android中系統發送的廣播,我們只能接收。通知就不一樣,他的監聽發送也是我們控制的,我們可以在任何地方任何時機發送一個通知,類似於Android中開發者自己發送廣播。

定義了一個定時器,在timerAction方法中發送通知
第一個參數:postNotificationname:@"XXX" 通知的名字,這個名稱必須和後面接受通知的名稱一致
第二個參數:object:self 可以傳遞的一個參數對象

@implementation Children

-(id) init{
    self = [super init];
    if(self !=nil){
        [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
        self.hapyValue = 100;
    }
    return self;
}

-(void) timerAction:(NSTimer *) timer{
    _hapyValue--;
    if(_hapyValue < 80){//發送通知
    [[NSNotificationCenter defaultCenter] postNotificationName:@"hapyValueNotification" object:self];
    }
}
@end

監聽通知
第一個參數:addObserver:self 監聽者對象
第二個參數:selector:@selector(notificationAction) 監聽處理通知的方法
第三個參數:name:@"XXX" 通知單額名稱
第四個參數:object:nil 通知發送時候傳遞的參數對象

@implementation Nure

-(id) init{
    self = [super init];
    if(self !=nil){//監聽通知
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notificationAction) name:@"hapyValueNotification" object:nil];
    }
return self;
}

//處理通知的方法
-(void) notificationAction:(NSNotification *)notification{
    Children *children = notification.object;
}

-(void) dealloc{
    [[NSNotificationCenter defaultCenter] removeObserver:self name:@"happyValueNotification" object:nil];
    //一個類中可以添加多個通知,這個方法可以移除所有的通知
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

@end

謂詞 NSPredicate 

謂詞就像sql語句一樣有自己的規則,這就不說了,比較容易理解

 

@property關鍵字定義屬性會自動有set/get方法

@Property NSString *userName;

@Property(atomic,retain,readwrite) Dog *dog;

第一個位置:atomic---線程保護的,默認       nonatomic---線程不保護的
第二個位置:assign---直接賦值,默認           retain---保留對象,內部會自動調用retain方法引用次數 +1        copy---拷貝對象
第三個位置:readwrite---生成set/get方法,默認  readonly---只生成get方法

如果我們相信修改這個屬性名稱,可以用@synthesize關鍵字進行修改

拷貝
copy方法和mutableCopy方法的區別
區別只在於那些有可變對象和不可變對象之分的對象上,對於沒有這種區分的對象來說,這兩個方法的效果是一樣的。
【不可變對象 copy】是假拷貝,等價於 【不可變對象 retain】
【不可變對象 mutableCopy】是真拷貝
深拷貝:拷貝屬性對象的內容
淺拷貝:只拷貝所有屬性對象的指針

iOS中如果定義一個類型是NS開頭的,一般都是指針類型,比如NSString *str;結構體類型的CGRect rect;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章