麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 學院 > 開發設計 > 正文

objective-c語法快速過(6)內存管理原理

2019-11-14 19:30:22
字體:
來源:轉載
供稿:網友

內存管理基本原理(最重要)

  • 移動設備的內存極其有限(iphone 4內存512M),每個app所能占用的內存是有限制的(幾十兆而已)。
  • 當app所占用的內存較多時,系統會發出內存警告,這時得回收一些不需要再使用的內存空間。比如回收一些不需要使用的對象、變量等
  • 管理范圍:任何繼承了NSObject的對象,對其他基本數據類型(int、char、float、double、struct、enum等)無效,和 java 不一樣,oc 開始的時候沒有垃圾自動回收機制。

OC對象的基本結構

每個OC對象都有自己的引用計數器,是一個四字節的整數,表示“對象被引用的次數”,即有多少人正在使用這個OC對象

每個OC對象內部專門有4個字節的存儲空間來存儲引用計數器(面試題)

引用計數器的作用

當使用alloc、new或者copy創建一個新對象時,新對象的引用計數器默認就是1,當一個對象的引用計數器值為0時,對象占用的內存就會被系統回收。換句話說,如果對象的計數器不為0,那么在整個程序運行過程,它占用的內存就不可能被回收,除非整個程序已經退出。

引用計數器的操作

給對象發送一條retain消息(代表調用這個對象方法),可以使引用計數器值+1retain方法返回對象本身)

給對象發送一條release消息,可以使引用計數器值-1,沒有返回值

可以給對象發送retainCount消息獲得當前的引用計數器值

對象的銷毀(IOS6之前)

當一個對象的引用計數器值為0時,那么它將被銷毀,其占用的內存被系統回收,

  • 當一個對象被銷毀時,系統會自動向對象發送一條dealloc消息,
  • 一般會重寫dealloc方法,在這里釋放相關資源,dealloc就像對象的臨終遺言,

一旦重寫了dealloc方法,就必須調用[super dealloc],并且放在最后面調用(類似 c++的析構函數,析構函數的調用順序和構造函數的調用順序完全相反),

  • 不要直接調用dealloc方法,
  • 一旦對象被回收了,它占用的內存就不再可用,堅持使用會導致程序崩潰(野指針錯誤)

Xcode的設置,取消 ARC

 

要想手動調用retain、release等方法,在創建項目的時候不要勾選ARC(自動引用計數)

/* 文件名:Person.h */#import <Foundation/Foundation.h>@interface Person : NSObject@PRoperty int age;@end/* 文件名:Person.m */#import "Person.h"@implementation Person// 當一個Person對象被回收的時候,就會自動調用這個方法- (void)dealloc{    NSLog(@"Person對象被回收");    // super的dealloc一定要調用,而且放在最后面    [super dealloc];}@end//  main.m 1> retain :計數器+1,會返回對象本身 2> release :計數器-1,沒有返回值 3> retainCount :獲取當前的計數器 4> dealloc,當一個對象要被回收的時候,就會調用這個函數,一定要調用[super dealloc],且這句調用要放在最后面。  概念 1> 僵尸對象 :所占用內存已經被回收的對象,僵尸對象不能再使用 2> 野指針 :指向僵尸對象(不可用內存)的指針,給野指針發送消息會報錯(EXC_BAD_access3> 空指針 :沒有指向任何東西的指針(存儲的東西是nil、NULL、0),給空指針發送消息不會報錯 ,這是 oc 的語法,但是其他語言不一定。比如 java 就不行。
#import <Foundation/Foundation.h>#import "Person.h"int main(){ // 計數器=1 Person *p = [[Person alloc] init]; //NSUInteger c = [p retainCount];  //NSLog(@"計數器:%ld", c);  //這樣寫不太好,注意是長整型 // 計數器=2 retain方法返回的是對象本身 [p retain]; // 計數器=1,沒有返回值 [p release]; // 計數器=0,對象的內存被釋放,p 成了野指針:指向僵尸對象(不可用內存)的指針 [p release];

   //給野指針發送消息,錯誤!也就是不能使用僵尸對象,人死不能復生! // [p retain]; // 給已經釋放的對象發送了一條-setAge:消息: // p.age = 10;使用野指針,報錯
   //[p setAge:10]; // -[Person setAge:]: message sent to deallocated instance 0x100109a10 //如果繼續 release,也會報錯。重復析構 // EXC_BAD_ACCESS : 訪問了一塊壞的內存(已經被回收、已經不可用的內存

  // 野指針錯誤  // 但是記住:OC不存在空指針錯誤,給空指針發送消息,oc里不報錯,故解決辦法: // 把指針p變成空指針 //p = nil;這樣下面的語就對了,否則就是野指針錯誤 [p release]; [p release]; [p release]; [p release]; [nil release];//ok return 0;}

1.當需要使用int類型的變量的時候,可以像寫C的程序一樣,用int,也可以用NSInteger,但更推薦使用NSInteger,因為這樣就不用考慮設備是32位的還是64位的。

2.NSUInteger是無符號的,即沒有負數,NSInteger是有符號的。

開啟僵尸對象監控

默認情況下,Xcode是不會管僵尸對象的,使用一塊被釋放的內存也不會報錯。為了方便調試,應該開啟僵尸對象監控

 

 

內存管理原則

QQ堂開房間原理:只要房間還有人在用,就不會解散

  • 只要還有人在用某個對象,那么這個對象就不會被回收
  • 只要你想用這個對象,就讓對象的計數器+1
  • 當你不再使用這個對象時,就讓對象的計數器-1

誰創建,誰release

如果你通過alloc、new或[mutable]copy來創建一個對象,那么你必須調用release或autorelease,換句話說,不是你創建的,就不用你去[auto]release

誰retain,誰release

只要你調用了retain,無論這個對象是如何生成的,你都要調用release

總結

有始有終,有加就有減

曾經讓對象的計數器+1,就必須在最后讓對象計數器-1

你想使用(占用)某個對象,就應該讓對象的計數器+1(讓對象做一次retain操作),不想再使用(占用)某個對象,就應該讓對象的計數器-1(讓對象做一次release)

set方法的內存管理

如果有個OC對象類型的成員變量,就必須管理這個成員變量的內存。比如有個Book *_book,而我們之前的做法并不嚴謹。

/*文件名:Car.h */#import <Foundation/Foundation.h>@interface Car : NSObject{    int _speed;}- (void)setSpeed:(int)speed;- (int)speed;@end/*文件名:Car.m */#import "Car.h"@implementation Car- (void)setSpeed:(int)speed{    _speed = speed;}- (int)speed{    return _speed;}- (void)dealloc{    /*只有對象計數器=0,這個方法是自動調用的!     _speed :最直接的訪問成員變量     self->_speed :直接訪問成員變量     self.speed : 兼容的get方法     [self speed] : 原裝的get方法     */    NSLog(@"速度為%d的Car對象被回收了", _speed);    [super dealloc];}@end/*文件名:Person.h */#import <Foundation/Foundation.h>#import "Car.h"@interface Person : NSObject{    Car *_car;    int _age;}- (void)setAge:(int)age;- (int)age;- (void)setCar:(Car *)car;- (Car *)car;@end/*文件名:Person.m */#import "Person.h"// _car -> c1  0@implementation Person- (void)setCar:(Car *)car{    if (car != _car)    {        // 對當前正在使用的車(舊車)做一次release,因為假如換車了,說明舊車不用了!那么沒有這個操作,就會出問題        [_car release];        // 對新車做一次retain操作        _car = [car retain];    }}- (Car *)car{    return _car;}- (void)setAge:(int)age{ // 基本數據類型不需要管理內存    _age = age;}- (int)age{    return _age;}- (void)dealloc{    // 當人不在了,代表不用車了    // 對車做一次release操作    [_car release];    NSLog(@"%d歲的Person對象被回收了", _age);    [super dealloc];}@end/*文件名:Student.h */#import <Foundation/Foundation.h>#import "Car.h"#import "Dog.h"@interface Student : NSObject{    int _no;    NSString *_name;    Car *_car;    Dog *_dog;}- (void)setNo:(int)no;- (int)no;- (void)setName:(NSString *)name;- (NSString *)name;- (void)setCar:(Car *)car;- (Car *)car;- (void)setDog:(Dog *)dog;- (Dog *)dog;@end/*文件名:Student.m */#import "Student.h"@implementation Student- (void)setNo:(int)no{    _no = no;}- (int)no{    return _no;}- (void)setName:(NSString *)name{    //如果換名字了,說明舊名字不用了,那么必須 release,否則出錯!同時別       忘記給新名字 retain(記住原則,我想用或者占用了,就必須 retain 一次,不想要或者丟掉就必須 release 一次)    if ( name != _name )    {        [_name release];        _name = [name retain];    }}    //get 方法不用內存管理,基本數據類型的成員也不要內存管理- (NSString *)name{    return _name;}- (void)setCar:(Car *)car{    if ( car != _car )    {        [_car release];        _car = [car retain];    }}- (Car *)car{    return _car;}- (void)setDog:(Dog *)dog{    if ( dog != _dog )    {        [_dog release];        _dog = [dog retain];    }}- (Dog *)dog{    return _dog;}- (void)dealloc{    [_name release];    [_car release];    [_dog release];        [super dealloc];}@end/*文件名:Dog.h */#import <Foundation/Foundation.h>@interface Dog : NSObject@end/*文件名:Dog.m */#import "Dog.h"@implementation Dog@end//  main.m#import <Foundation/Foundation.h>#import "Car.h"#import "Person.h"#import "Student.h"#import "Dog.h"int main(){    // stu = 1    Student *stu = [[Student alloc] init];        // Car = 2    // 這行內存有內存泄露    //stu.car = [[Car alloc] init];        // stu = 0    // Car = 1    [stu release];            // 這行內存有內存泄露    // [[Car alloc] init].speed = 100;        return 0;}void test3(){    Student *stu = [[Student alloc] init];        Car *c = [[Car alloc] init];    stu.car = c;        Dog *d = [[Dog alloc] init];    stu.dog = d;        NSString *s = @"Jack";        stu.name = s;        [d release];    [c release];    [stu release];}void test2(){    Person *p1 = [[Person alloc] init];    p1.age = 20;        // c1 - 1    Car *c1 = [[Car alloc] init];    c1.speed = 100;    // c1 - 2    p1.car = c1;    // c1 - 1    [c1 release];        Car *c2 = [[Car alloc] init];    c2.speed = 200;    // c1 - 0    p1.car = c2;        [c2 release];        [p1 release];}void test1(){    // p-1    Person *p = [[Person alloc] init];    p.age = 20;        // c1-1    Car *c1 = [[Car alloc] init];    c1.speed = 250;        // c1-2    p.car = c1;        // c1-1    [c1 release];        p.car = c1;    p.car = c1;    p.car = c1;    p.car = c1;    p.car = c1;    p.car = c1;    p.car = c1;        [p release];}void test(){    // p-1    Person *p = [[Person alloc] init];    p.age = 20;        // c1-1    Car *c1 = [[Car alloc] init];    c1.speed = 250;        // p想擁有c1    // c1-2    p.car = c1;  // [p setCar:c1];        // c2-1    Car *c2 = [[Car alloc] init];    c2.speed = 300;        // p將車換成了c2    // c1-1    // c2-2    p.car = c2;        // c2-1    [c2 release];    // c1-0    [c1 release];    // p-0 c2-0    [p release];}

內存管理代碼規范:

 1.只要調用了alloc,必須有release(autorelease),   對象不是通過alloc產生的,就不需要release

 2.set方法的代碼規范

 1> 基本數據類型:直接復制

 - (void)setAge:(int)age {    _age = age; }

 2> OC對象類型

- (void)setCar:(Car *)car {    // 1.先判斷是不是新傳進來對象    if ( car != _car )    {        // 2.對舊對象做一次release        [_car release];        // 3.對新對象做一次retain        _car = [car retain];    } }

 3.dealloc方法的代碼規范

 1> 一定要[super dealloc],而且放到最后面

 2> 對self(當前)所擁有的其他對象做一次release

- (void)dealloc {    [_car release];    [super dealloc]; }

什么是碼農,這樣的重復代碼的編寫就是碼農的工作,so蘋果出了對策,IDE 自動完成一些重復性代碼的編寫工作。

XCODE 可以幫我們省掉編寫那些惡心代碼的工作。使用@property自動生成內存管理的代碼,但是 dealloc 方法還是要自己寫,這時候就有了 ARC,IOS5之后出的新特性。

@property參數

控制set方法的內存管理

  • retain : release舊值,retain新值(用于OC對象)
  • assign : 直接賦值,不做任何內存管理(默認,用于非OC對象類型)
  • copy   : release舊值,copy新值(一般用于NSString *)
/*文件名:Book.h */#import <Foundation/Foundation.h>@interface Book : NSObject@end/*文件名:Book.m */#import "Book.h"@implementation Book@end/*文件名:Person.h */#import <Foundation/Foundation.h>#import "Book.h"@interface Person : NSObject@property int age;// retain : 生成的set方法里面,release舊值,retain新值@property (retain) Book *book;@property (retain) NSString *name;@end/*文件名:Person.m */#import "Person.h"@implementation Person- (void)dealloc{    [_book release];    [_name release];    [super dealloc];}@end/*文件名:Student.h */#import <Foundation/Foundation.h>#import "Book.h"@interface Student : NSObject@property (retain) Book *book;@property (retain) NSString *name;@end/*文件名:Student.m */#import "Student.h"@implementation Student- (void)dealloc{    [_book release];    [_name release];    [super dealloc];}@end//  main.m#import <Foundation/Foundation.h>#import "Person.h"#import "Book.h"int main(){    Book *b = [[Book alloc] init];    Person *p = [[Person alloc] init];        p.book = b;        NSLog(@"%ld", [b retainCount]);        [p release];    [b release];    return 0;}

控制需不需生成set方法

  • readwrite 同時生成set方法和get方法(默認),這里把 set 看成寫,get 看成讀取,就很好理解了。
  • readonly  只會生成get方法(只讀,就是只是獲取,那么就是 get)

多線程管理

  • atomic    性能低(默認)
  • nonatomic 性能高(寫程序要使用這個)

控制set方法和get方法的名稱

  • setter : 設置set方法的名稱,一定有個冒號:
  • getter : 設置get方法的名稱
/*文件名:Person.h */#import <Foundation/Foundation.h>/* 1.set方法內存管理相關的參數 * retain : release舊值,retain新值(適用于OC對象類型) * assign : 直接賦值(默認,適用于非OC對象類型,寫不寫都行) * copy   : release舊值,copy新值  2.是否要生成set方法 * readwrite : 同時生成setter和getter的聲明、實現(默認) * readonly  : 只會生成getter的聲明、實現  3.多線程管理 * nonatomic : 性能高 (一般就用這個) * atomic    : 性能低(默認)  4.setter和getter方法的名稱 * setter : 決定了set方法的名稱,一定要有個冒號 : * getter : 決定了get方法的名稱(一般用在BOOL類型) */@interface Person : NSObject// 返回BOOL類型的方法名一般以is開頭@property (getter = isRich) BOOL rich;//   @property (nonatomic, assign, readwrite) int weight;// setWeight:// weight// @property (readwrite, assign) int height;@property (nonatomic, assign) int age;@property (retain) NSString *name;@end/*文件名:Person.m */#import "Person.h"@implementation Person@end//  main.m#import <Foundation/Foundation.h>#import "Person.h"int main(){    Person *p = [[Person alloc] init];    p.rich = YES;        BOOL b = p.isRich;        return 0;}

循環引用(著名的問題)

@class的使用

使用場景;對于循環依賴關系來說,比方A類引用B類,同時B類也引用A類

這種代碼直接編譯會報錯。當使用@class在兩個類相互聲明,就不會出現編譯報錯

用法概括

使用 @class 類名; 就可以引用一個類,說明一下它是一個類

和#import的區別

#import方式會包含被引用類的所有信息,包括被引用類的變量和方法;

@class方式只是告訴編譯器在A.h文件中 B *b 只是類的聲明,具體這個類里有什么信息,這里不需要知道,等實現文件中真正要用到時,才會真正去查看B類中信息,如果有上百個頭文件都#import了同一個文件,或者這些文件依次被#improt,那么一旦最開始的頭文件稍有改動,后面引用到這個文件的所有類都需要重新編譯一遍,這樣的效率也是可想而知的,而相對來 講,使用@class方式就不會出現這種問題了。

在.m實現文件中,如果需要引用到被引用類的實體變量或者方法時,還需要使用#import方式引入被引用類

循環retain

比如A對象retain了B對象,B對象retain了A對象,這樣會導致A對象和B對象永遠無法釋放

解決方案

當兩端互相引用時,應該一端用retain、一端用assign

/*描述:每個身份證都對應一個人,同時,每個人都對于一個身份證,這就是相互依賴的關系文件名:Card.h */#import <Foundation/Foundation.h>@class Person;@interface Card : NSObject//@property (nonatomic, retain) Person *person;@property (nonatomic, assign) Person *person;@end/*文件名:Card.m */#import "Card.h"#import "Person.h"@implementation Card- (void)dealloc{    NSLog(@"Car被銷毀了");    // [_person release];有 retain 才有 release,否則不能寫    [super dealloc];}@end/* 文件名:Person.h */#import <Foundation/Foundation.h>#import "Card.h"// @class僅僅是告訴編譯器,Card是一個類//@class Card;@interface Person : NSObject@property (nonatomic, retain) Card *card;@end/* 文件名:Person.m */#import "Person.h"#import "Card.h"@implementation Person- (void)dealloc{    NSLog(@"Person被銷毀了");    [_card release];    [super dealloc];}@end//  main.m#import <Foundation/Foundation.h>#import "Card.h"#import "Person.h"int main(){    // p - 1    Person *p = [[Person alloc] init];    // c - 1    Card *c = [[Card alloc] init];        // c - 2    p.card = c;        // p - 1    c.person = p;        // c - 1    [c release];        // p - 0  c - 0,如果不這樣使用( 1> 一端用retain    2> 一端用assign)    [p release];    return 0;}////如果不這樣使用( 1> 一端用retain    2> 一端用assign),會出錯//// p - 1//Person *p = [[Person alloc] init];//// c - 1//Card *c = [[Card alloc] init];////// c - 2//p.card = c;////// p - 2,因為兩個類的 set 方法生成 都是 retain 屬性,那么就是這樣的代碼//c.person = p;////    if (_card != card)////    {//這個步驟要有,舊的(當前的)對象不再被使用,就把它的計數器-1操作,之后再對新的對象使用+1,防止出錯。////        [_card release];////        _card = [book retain];////    }////// c - 1//[c release];////// p - 1  此時不會調用 dealloc 方法,會出現內存泄露問題,而使用了雙端循環引用解決方案,那么p=0,則自動調用 person 類的 dealloc方法,c=0,完美結束。////- (void)dealloc////{////    NSLog(@"Person被銷毀了");////    [_card release];////    ////    [super dealloc];////}//[p release];

@class的作用:僅僅告訴編譯器,某個名稱是一個類
@class Person; 僅僅告訴編譯器,Person是一個類,不會把類的方法等引入

實際開發中引用一個類的規范是:
1> 在.h文件中用@class來聲明類,比如,有100個類同時引用了 Card 類,如果 card 修改了,那么剩下的100個類也要重新引入編譯,效率不高,且還能解決雙端引用(循環引用)的出現錯誤問題。
2> 在.m文件中用#import來包含類的所有東西

為了提高編譯的效率!頭文件不使用#import,只有一個特例,那就是在繼承里,父類需要使用#import 引入到子類

兩端循環引用解決方案,這是特例,區別對待,以前說了,對象用 retain,非對象不需要內存管理,使用 assign 就行了,但是這里特殊
1> 一端用retain
2> 一端用assign 

autorelease方法(半自動釋放)

autorelease

  • 給某個對象發送一條autorelease消息時,就會將這個對象加到一個自動釋放池中
  • 當自動釋放池銷毀時,會給池子里面的所有對象發送一條release消息
  • 調用autorelease方法時并不會改變對象的計數器
  • autorelease 方法返回對象本身
  • autorelease實際上只是把對release的調用延遲了,對于每一次autorelease,系統只是把該對象放入了當前的@autoreleasepool中,當該pool被釋放時,該pool中的所有對象會被調用Release

 使用 autorelease 方法防止了每次使用對象,都要在對象 release 之前使用的弊端,因為那樣總是小心翼翼的,怕出現野指針。但是出現了 ARC 之后這些都不需要了。

#import <Foundation/Foundation.h>int main(int argc, const char * argv[]) {    @autoreleasepool {        // insert code here...        NSLog(@"Hello, World!");    }    return 0;}

ios 5.0后,以后一直使用這個了.

ios 5.0前

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];// .....[pool release]; // 或[pool drain];

在程序運行過程中,可以創建多個自動釋放池,它們是以棧的形式存在內存中,OC對象只需要發送一條autorelease消息,就會把這個對象添加到最近的自動釋放池中(棧頂的釋放池)

/*文件名:Person.h */#import <Foundation/Foundation.h>@interface Person : NSObject@property (nonatomic, assign) int age;@end/*文件名:Person.m */#import "Person.h"@implementation Person- (void)dealloc{    NSLog(@"Person---dealloc");    [super dealloc];}@end//  main.m/* 1.autorelease的基本用法 1> 會將對象放到一個自動釋放池中 2> 當自動釋放池被銷毀時,會對池子里面的所有對象做一次release操作 3> 會返回對象本身 4> 調用完autorelease方法后,對象的計數器不變  2.autorelease的好處 1> 不用再關心對象釋放的時間 2> 不用再關心什么時候調用release  3.autorelease的使用注意 1> 占用內存較大的對象不要隨便使用autorelease 2> 占用內存較小的對象使用autorelease,沒有太大影響  4.錯誤寫法 1> alloc之后調用了autorelease,又調用release @autoreleasepool {    // 1    Person *p = [[[Person alloc] init] autorelease];     // 0    [p release]; }  2> 連續調用多次autorelease @autoreleasepool {    Person *p = [[[[Person alloc] init] autorelease] autorelease]; }  5.自動釋放池 1> 在iOS程序運行過程中,會創建無數個池子。這些池子都是以棧結構存在(先進后出) 2> 當一個對象調用autorelease方法時,會將這個對象放到棧頂的釋放池  6.自動釋放池的創建方式 1> iOS 5.0前 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];  [pool release]; // MAC 上是 [pool drain];  2> iOS 5.0 開始 @autoreleasepool { } */#import <Foundation/Foundation.h>#import "Person.h"int main(){    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];        Person *pp = [[[Person alloc] init] autorelease];        [pool release]; // [pool drain];        @autoreleasepool    {        // 1        Person *p = [[[Person alloc] init] autorelease];        // 0        // [p release];    }        return 0;}void test(){    @autoreleasepool    {// { 開始代表創建了釋放池        // autorelease方法會返回對象本身        // 調用完autorelease方法后,對象的計數器不變        // autorelease會將對象放到一個自動釋放池中        // 當自動釋放池被銷毀時,會對池子里面的所有對象做一次release操作        Person *p = [[[Person alloc] init] autorelease];                p.age = 10;           @autoreleasepool        {            // 1            Person *p2 = [[[Person alloc] init] autorelease];            p2.age = 10;           }           Person *p3 = [[[Person alloc] init] autorelease];        } // } 結束代表銷毀釋放池}

跟release的對比

以前:

Book *book = [[Book alloc] init];

[book release];

現在:

Book *book = [[[Book alloc] init] autorelease];

// 不要再調用[book release];但是這樣顯得代碼很長,臃腫,能不能創建對象的時候,直接就是放入自動釋放池里呢?可以的:

一般可以為類添加一個快速創建對象的類方法

+ (id)book {    return [[[self alloc] init] autorelease];}

外界調用[Book book]時,根本不用考慮在什么時候釋放返回的Book對象,實際開發中常用。

開發中經常會提供一些類方法,快速創建一個已經autorelease過的對象,創建對象時不要直接用類名,用self,因為這樣寫,此類的子類都能調用這個方法,自動識別,self 指向調用這個方法的類,不會出錯。

 

一般來說,除了alloc、new或copy之外,其他的方法創建的對象都被聲明了autorelease

比如下面的對象都已經是autorelease的,不需要再release

NSNumber *n = [NSNumber numberWithInt:100];NSString *s = [NSString stringWithFormat:@"jack"];NSString *s2 = @"rose";

小結;

一、計數器的基本操作

1> retain : +1

2> release :-1

3> retainCount : 獲得計數器

 

二、set方法的內存管理

1> set方法的實現

- (void)setCar:(Car *)car{    if ( _car != car )    {        [_car release];        _car = [car retain];    }}

2> dealloc方法的實現(不要直接調用dealloc)

- (void)dealloc{    [_car release];    [super dealloc];}

 

三、@property參數

1> OC對象類型

@property (nonatomic, retain) 類名 *屬性名;

@property (nonatomic, retain) Car *car;

@property (nonatomic, retain) id car;

// 被retain過的屬性,必須在dealloc方法中release屬性

- (void)dealloc

{

    [_car release];

    [super dealloc];

}

 

2> 非OC對象類型(int/float/enum/struct)

@property (nonatomic, assign) 類型名稱 屬性名;

@property (nonatomic, assign) int age;

 

四、autorelease

1.系統自帶的方法中,如果不包含alloc、new、copy,那么這些方法返回的對象都是已經autorelease過的

[NSString stringWithFormat:....];

[NSDate date];

 

2.開發中經常寫一些類方法快速創建一個autorelease的對象

* 創建對象的時候不要直接使用類名,用self


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 在线免费观看欧美 | av在线大全 | 4399一级成人毛片 | 农村少妇吞精夜夜爽视频 | 亚洲精品一区中文字幕 | xxxx18韩国护士hd老师 | 99re热视频这里只精品 | 免费毛片小视频 | 久久精品站 | www.69色| 欧美性受xxxx白人性爽 | 在线高清中文字幕 | 9797色| 国产精品高潮视频 | 欧美1—12sexvideos | 在线中文字幕亚洲 | 草草在线视频 | a免费视频 | 亚洲欧洲日韩av | 欧美精品亚洲人成在线观看 | 中文字幕免费看 | 国产va在线观看 | 成年免费大片黄在线观看岛国 | 91精选视频在线观看 | 欧美一级精品 | 九九久久视频 | 午夜生活理论片 | 国产一有一级毛片视频 | 久久久久北条麻妃免费看 | 国产精品久久久久网站 | 精国产品一区二区三区四季综 | 日本在线播放一区二区三区 | 久久久无码精品亚洲日韩按摩 | 欧美一级黄视频 | 黄色大片在线观看 | 在线播放免费视频 | 激情综合婷婷久久 | gogo全球大胆高清人露出91 | 日韩视频一区二区三区在线观看 | 久久精品99北条麻妃 | 538任你躁在线精品视频网站 |