[非凡程序員] 楊茹

IOS的內存管理數組

1.IOS中對於每個對象都會有一個對象計數器性能


2.IOS內存管理分爲三種(MRC:手動釋放內存  autorelaese:自動釋放內存 ARC:自動引用計數)編碼

(1)MRC 黃金法則: 一旦對象被建立(new alloc init copy retain,那麼就由建立者釋放。總結:誰建立,誰釋放,誰retain,誰release。其中 retain 計數器加一  release 計數器減一。atom

使用方式:Target-> 搜索auto -> 找到Automatic Reference Counting 將其修改爲NOspa


如狀況一.net


 //實例化Person對象 此時計數器爲 13d

    Person *person1 = [[Person alloc]init];指針

    //計數器加一rest

    [person1 retain];code

    //計數器減一

    [person1 release];

    //打印當前計數器的值

    NSLog(@"%li",[person1 retainCount]);


如狀況二


 //若只是建立一個person的指針 則計數器爲 0

    Person *person;

     // 由於計數器的release是針對於對象計數器而言的,此時沒有對象,因此即便[person retain] 打印出的計數器的值永遠爲0

    


如狀況三


 //建立了一個Dog對象

    Dog *dog = [[Dog alloc]init];


 //給人設置狗對象後,狗被引用一次 , 此時dogretainCount2

    [person1 setDog:dog];


//類的類屬性,設置和獲取,setget,如今能夠簡便化:

    //@property \ @synthesize

    //noatomic 高性能  atomic 低性能

    //retain 表明針對於這個對象計數器+1

    //readonly  表明對象只讀

    //setter getter 更改這個方法的名字

    //assign 賦值經過針對於簡單的數據類型



 //3.釋放內存用dealloc,通常在.m文件中實現 [super dealloc],只要調用對象的release方法,就會進入dealloc;

    

//4.類的類屬性,setget,如今能夠簡化爲:@property @synthesize

    //noatomic 高性能  atomic 低性能 readonly  表明對象只讀

    //setter getter 更改這個方法的名字

   

//5.有內存管理,用retain  OC語言的數據類型可內存管理

   // @property( nonatomic , retain ) Dog *dog;

    

  無內存管理 assign  c語言的基礎數據類型無內存管理

  // @property( nonatomic , assign ) int age;



3.關於retainCount1,-10,無窮大的條件

(1)1 是對象計數 當建立對象時或者對象即將釋放時爲1,即對象計數器最小爲1.

(2)0 當一個指針的值爲空時。

(3)爲-1或無窮大時 當一個數據類型被賦值時。

不可變對象一般被稱爲靜態常量,這類對象通常不能用於計數,而可變的對象是能夠用來計數的



.淺拷貝和深拷貝

1.淺拷貝 copy 一般指針對於指針進行拷貝,特色爲:經過多個指針指向同一片內存地址。

 NSString *string = @"123";

    NSString *stringI = [string copy];

這時stringstringI輸出的內存地址相同

2.深拷貝 mutableCopy 指的是賦值內容而且從新建立一塊內存地址

 NSString *stringII = [string mutableCopy];

這時stringstringII輸出的內存地址不相同


.自動釋放池(autorelease)

1.autorelease一般有做用域,當在做用域範圍內的建立特定的對象時,出去做用域計數器就會-1

@autorelease{

    Person *personP = [[Person alloc]autorelease];

//特定的autorelease建立的對象纔在出去做用域的時候release 計數器 -1

此時也能夠在做用域裏面對person retainrelease,可是無論怎樣,出做用域時計數器只會減一

}


.ARC(自動引用計數)

1.ARC會追蹤你的對象並決定哪個仍會使用而哪個不 會再用到  

若是啓用了ARC,編譯器會自動插入retainrelease 語句  

經過Xcode啓用或禁用可

2.ARC的特色

(1)不容許調用release,retain,retainCount    

(2)容許重寫dealloc,可是不容許調用[super dealloc]  

(3)@property的參數:  

  • strong:至關於原來的retain(適用於OC對象),成員變量是強指針  

  • weak:至關於原來的assign,(適用於OC對象類型),成員變量是弱指針  

  • assign:適用於非OC對象類型(基礎類型)

相互引用時注意的問題:

1.在一方的.h文件中要導入另外一方的頭文件,另外一方的.h文件要引用@class name

 #import <Foundation/Foundation.h>

   #import "MicroBlog.h"

   @interface Person : NSObject

   #import <Foundation/Foundation.h>

   @class Person;

   @interface MicroBlog : NSObject

2.一方使用強指針,另外一方使用弱指針

3.引用@class的一方若要在.m文件中實現相應的方法,要在.m文件中再次導入另外一方的頭文件

 #import "MicroBlog.h"

   #import "Person.h"

   @implementation MicroBlog


ARC實例:

person.h


#import <Foundation/Foundation.h>

#import "MicroBlog.h"


@interface Person : NSObject

@property (nonatomic ,strong)MicroBlog *microBlog;

@property (nonatomic,strong) NSString *name;

@property (nonatomic,weak) NSString *comment;

-(void)printf;

@end



person.m

#import "Person.h"


@implementation Person

-(void)printf

{

    NSLog(@"%@%@發佈了第%i條微博,內容是:%@",_name, [_microBlog time],[_microBlog second],[_microBlog content]);

}

@end


microBlog.h


#import <Foundation/Foundation.h>

@class Person;


@interface MicroBlog : NSObject

@property(nonatomic,weak) Person *person;

@property(nonatomic,weak) Person *commentPerson;

@property(nonatomic,weak) NSString *content;

@property(nonatomic,weak) NSString *time;

@property(nonatomic,assign) int second;


-(void)printComment;

@end


microBlog.m


#import "MicroBlog.h"

#import "Person.h"


@implementation MicroBlog

-(void)printComment

{

    NSLog(@"%@評論了你的微博:%@",[_commentPerson name],[_commentPerson comment]);

}

@end



main.m


#import <Foundation/Foundation.h>

#import "MicroBlog.h"

#import "Person.h"


int main(int argc, const char * argv[]) {

    

    Person *person = [[Person alloc]init];

    person.name = @"小明";

    Person *personI = [[Person alloc]init];

    personI.name = @"小花";

    personI.comment = @"👍";

    

    MicroBlog *microBlog = [[MicroBlog alloc]init];

    

    microBlog.content = @"暑假去旅遊";

    

    microBlog.second = 2;

    

    NSDate *date = [NSDate date];

    NSDateFormatter *dateformatter = [[NSDateFormatter alloc]init];

    [dateformatter setDateFormat:@"yyyy-MM-dd HH-mm-ss"];

    NSString *nowTime = [dateformatter stringFromDate:date];

    microBlog.time = nowTime;

    

    microBlog.commentPerson = personI;


   //這是容易忘記的一步,要給person對象設置microBlog

    person.microBlog = microBlog;

    

    [person printf];

    [microBlog printComment];

    

 return 0;

}




  KVC: key value coding 鍵值編碼。


能夠將對象屬性變爲一個鍵從而去設置屬性的值
.KVC的四種方法

1.setValue:forKey: 設置類屬性的值
: [hunter setValue:"光頭強" forKey:"name"];

2.valueForKey: 取相對應的屬性的值
: [person valueForKey:@"name"]

3.setValue:forKeyPath: 根據鍵路徑設置類屬性的值

4.valueForKeyPath: 根據鍵路徑取相對應的屬性的值(對象屬性是另外一個的類屬性)
: [person valueForKeyPath:@"hunterPig.weight"]

.KVC中經常使用的幾種計算方式
:
//建立森林對象
Forest *forest = [[Forest alloc]init];
//把三隻豬放到同一個數組中
NSArray *array = [boarI,boarIII,boarII,boarII];

//將存放豬的數組放入到森林數組(是森裏類的一個屬性) 即完成了

[forest setValue:array forKey:"forestArray"];

1.count: 計算數量

//求豬的個數

NSLog("豬的個數是:%",[forest valueForKeyPath:"forestArray.@count"])

2.max: 計算最大值

//求豬重量的最大值

NSLog("豬的重量的最大值是:%",[forest valueForKeyPath:"forestArray.@max.weight"]);

3.min: 計算最小值

//求豬重量的最小值

NSLog("豬的重量的最小值是:%",[forest valueForKeyPath:"forestArray.@min.weight"]);

4.sum: 計算總和

//求豬重量的總和

NSLog("豬的重量的總值是:%",[forest valueForKeyPath:"forestArray.@sum.weight"]);

5.avg: 計算平均值

//求豬重量的平均值

NSLog("豬的重量的平均值是:%",[forest valueForKeyPath:"forestArray.@avg.weight"]);

.針對數組
1.
自動去除數組重複的元素  distinctUnionOfObjects

NSArray *arr = [1,@2,@3,@2];

NSLog("數組裏的元素有%@",[arr valueForKeyPath:"@distinctUnionOfObjects.self"]);

2. 不會自動去除數組多餘的元素 @unionOfObjects

  NSLog(@"數組裏的元素有%@",[arrvalueForKeyPath:@"@unionOfObjects.self"]);



KVO: key value observing 當類屬性的值發生改變時,會自動調用監聽回調方法進行提醒


:KVO中必有的三種方法
1.給對象添加監聽者 
[被監聽者 addObserver:監聽者 forKeyPath:@「類屬性」 options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
注意:被監聽者和監聽者能夠是同一類實例化出的兩個相同或不一樣的對象,也能夠是不一樣類分別實例化出的對象
類屬性能夠是本身類的屬性,也能夠是對象類屬性裏面的屬性

2.給對象移除監聽者 
[被監聽者 removeObserver:監聽者 forKeyPath:@"類屬性"];

3.一旦類屬性的值發生改變,監聽回調如下方法
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
其中的四個屬性:
keyPath :監聽的key
object: 監聽的對象 
change: 返回新值和舊值(在添加監聽者時須要設置)
context:上下文內容

它們的輸出方式爲:
NSLog("keyPath :%",keyPath);
NSLog("object :%",[object valueForKey:類屬性」]);

NSLog("change :%",change);

取出舊值:[change valueForKey:「old」];
取出新值:[change valueForKey:@「new」];

類屬性值發生改變時是發生在添加和移除監聽者之間的


舉例說明KVO

人監聽帳戶裏的帳戶名和帳戶餘額屬性

main.m


#import <Foundation/Foundation.h>

#import "Person.h"

#import "Account.h"


int main(int argc, const char * argv[]) {

    

    //實例化person對象

    Person *person = [[Person alloc]init];

    

    //實例化一個帳戶

    Account *account = [[Account alloc]init];

    

    //給帳戶設置餘額和帳戶名

    [account setValue:@"200" forKey:@"money"];

    [account setValue:@"123456" forKey:@"name"];

    

    //給帳戶添加監聽者來監聽它的餘額

    [account addObserver:person forKeyPath:@"money" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];

    

    //給帳戶添加監聽者來監聽它的zhanghum

    [account addObserver:person forKeyPath:@"name" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];


    

    //給帳戶從新設置餘額和帳戶名

    [account setValue:@"500" forKey:@"money"];

    [account setValue:@"678954" forKey:@"name"];


    //移除監聽者

    [account removeObserver:person forKeyPath:@"money"];

    [account removeObserver:person forKeyPath:@"name"];


    return 0;

}


person.m


#import "Person.h"


@implementation Person

//一旦被監聽者的屬性值發生改變,當即進入此方法

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context

{

//    NSLog(@"keyPath :%@",keyPath);

//    NSLog(@"object :%@",[object valueForKey:@"money"]);

//    NSLog(@"change :%@",change);

    

    //當同時監聽對象的多個屬性時,輸出改變值時須要進行判斷

    if ([keyPath isEqualToString:@"money"]) {

        

        NSLog(@"您的帳戶餘額發生改變,當前金額爲%@",[object valueForKey:keyPath]);

        

      NSLog(@"您當前餘額總共有%i",[[change valueForKey:@"old"]intValue] + [[change valueForKey:@"new"]intValue]);

    }

    else

        if ([keyPath isEqualToString:@"name"]) {

            NSLog(@"您的帳戶名發生改變,當前帳戶名爲:%@",[object valueForKey:keyPath]);

        }

     

}


@end

相關文章
相關標籤/搜索