[Bài Học Số 3] Cơ Bản Objective Cx

7 447 4
[Bài Học Số 3] Cơ Bản Objective Cx

Đang tải... (xem toàn văn)

Thông tin tài liệu

Lập trình ios

Quản lý bộ nhớ Quản lý bộ nhớ là tiến trình xử lý việc khởi tạo vùng nhớ cho ứng dụng, sử dụng nó và giải phóng nó khi ta đã hoàn thành công việc. Một chương trình quản lý bộ nhớ tốt sẽ sử dụng ít vùng nhớ nhất thể. Quản lý bộ nhớ là một vấn đề rất quan trọng trong lập trình. Một vấn đề thường hay gặp phải đó là leak memory, khi chúng ta khởi tạo mà không giải phóng vùng nhớ. Điều này thể dẫn tới việc lãng phí bộ nhớ hoặc nghiêm trọng hơn là out of memory và dẫn tới crash chương trình. Objective-C cung cấp 3 cách quản lý bộ nhớ • Manual retain-release (MRR) hoặc thể gọi là Manual Reference Counting (MRC) nghĩa là chúng ta sẽ tự quản lý bộ nhớ bằng cách đánh dấu quá trình sử dụng của các object mà ta có. Cụ thể là ta sẽ đếm việc khởi tạo, sử dụng và giải phóng object trong chương trình. • Autiomatic Reference Counting (ARC), hệ thống sẽ dùng bộ đếm tương tự như MRR nhưng nó sẽ thêm vào method quản lý bộ nhớ tự động tại thời điểm compile. Ta nên sử dụng ARC cho các project mới • Garbage Collection (GC), hệ thống sẽ tự động lưu vết và tự động giải phóng vùng nhớ của object không cần thiết nữa. Nó sử dụng kỹ thuật quản lý bộ nhớ khác MRR hoặc ARC tuy nhiên GC chỉ hỗ trợ Mac OS X mà không hỗ trợ iOS Reference Counting Khi một object được sinh ra, Objective-C sử dụng một kỹ thuật gọi là reference counting hoặc đôi khi gọi là retain counting để theo vết vòng đời của object. Mỗi object sẽ một số interger đánh dấu nó, được biết như là reference count hoặc retain count. Khi một đoạn code nào đó tác động tới object, đoạn code đó sẽ tăng retain count, khi kết thúc đoạn code và không sử dụng object nữa, nó sẽ giảm retain count. Khi retain count về 0 cũng nghĩa là nó không sử dụng nữa và lúc này nó sẽ bị hủy khỏi bộ nhớ. Khi object được khởi tạo bằng các từ khóa như alloc, new hoặc xử lý message copy, retain count của object sẽ tự động là 1. Để tăng retain count lên, ta gửi retain message cho object. Để giảm retain count ta gửi release message. Khi retain count của object về 0 và object cần được hủy, Objective-C sẽ tự động gửi dealloc message cho object. Ta thể override dealloc method trong object để release resource nào mà ta muốn. Không nên gọi dealloc method trực tiếp. Để thể biết được retain count hiện tại, ta gửi retainCount message. Tóm lại ta 3 method quan trọng như sau PHP Code: PHP Code: - (id) retain; - (void) release; - (unsigned) retainCount; retain trả về id nên ta thể kết hợp nó với chuỗi message ví dụ [[car retain] setTire:tire atIndex:2]; báo cho object car tăng retain count và gửi message setTire. Ta coi ví dụ sau PHP Code: PHP Code: @interface RetainTracker : NSObject @end @implementation RetainTracker -(id)init { if (self = [super init]) { NSLog(@”init”); } return self; } -(void)dealloc { NSLog(“dealloc”); [super dealloc]; } @end Object RetainTracker trong ví dụ trên override lại dealloc methods để xử lý cần thiết khi object bị hủy, tiếp theo ta sẽ coi vòng đời của object RetainTracker thông qua các methods retain và alloc trong ví dụ dưới. PHP Code: PHP Code: int main(int argc, const char *argv[]) { RetainTracker *tracker = [RetainTracker new]; //count: 1 [tracker retain]; // count: 2 [tracker retain]; // count: 2 [tracker release]; // count: 1 [tracker retain]; // count: 2 [tracker release]; // count: 1 [tracker release]; // count: 0, dealloc return (0); } Qua ví dụ trên, ta thấy rõ cấu quản lý bộ nhớ của Objective-C như thế nào. Object Ownership Cho tới giờ việc quản lý bộ nhớ mà ta biết chưa gì quá phức tạp, nó đi theo chu trình từ lúc khởi tạo thông qua bộ đếm retain count và dealloc khi về 0. Vấn đề sẽ thực sự trở nên rắc rối khi ta đề cập tới khái niệm object ownership. Một object với instance variables trỏ tới một object khác được gọi là own object khác. Ta object CarParts các variables engine trỏ tới object engine và tires trỏ tới các objects tires. Ví dụ trong object CarParts methods PHP Code: -(void)setEngine: (Engine*) newEngine; Và trong hàm main() ta gọi PHP Code: PHP Code: Engine *engine = [Engine new]; [car setEngine: engine]; Trong trường hợp trên ta sẽ gặp rắt rối nảy sinh khi object engine vừa nằm trong hàm main() vừa được sử dụng trong object car (kiểu CarParts) và khó xác định khi nào thực sự object engine bị dealloc. Nếu ta release trong hàm main() thì object engine sẽ bị xóa trong khi CarParts vẫn đang sử dụng, tương tự nếu release trong CarParts object nhưng hàm main() vẫn còn cần nó. Cách giải quyết vấn đề trên là ta sẽ tăng retain count của engine lên 2 ngay khi object CarParts sử dụng nó. Như vậy retain count của engine là 2 và khi ta release khi CarParts không sử dụng nó nữa sau đó release tại main() thì retain count của engine về 0 sẽ được dealloc một cách hợp lý. Retain và Release trong Methods Đầu tiên ta nói kỹ hơn một chút về object CarParts, nó chứa một instance variable engine kiểu Engine* và hàm setEngine được gọi là một accessor method (coi phần Property) chức năng gán object cho engine. Ngoài ra trong dealloc method của object CarParts xử lý cho phần dealloc của engine variables. Quay lại ví dụ ở phần trước, ta sẽ coi cách xử lý trong method setEngine như thế nào: PHP Code: PHP Code: -(void)setEngine: (Engine *)newEngine { engine=[newEngine retain]; //chú ý retain trả về id của Engine } Cách code như trên đã thõa đúng cách giải quyết mà ta đưa ra ban đầu, newEngine (tức là engine mà main method đưa vào) được tăng retain count trong accessor method. Khi dealloc method trong CarParts được gọi thì engine sẽ được release để retain count giảm xuống như phương pháp ta đã nêu ở phía trên. Tuy nhiên cách code này 1 vấn đề là nếu engine variable đang trỏ tới một object Engine khác (tức là ta đã gửi message method setEngine trước đó) thì object đó sẽ không được release khi engine trỏ sang object Engine mới, điều này làm leak object Engine cũ, do đó cách code như trên là không tối ưu. Để khắc phục tình trạng ở phía trên, ta xem thử đoạn code dưới đây PHP Code: PHP Code: -(void)setEngine: (Engine *)newEngine { [engine release]; engine=[newEngine retain]; //chú ý retain trả về id của Engine } Cách code trên đưa ra giải pháp release ngay engine variable trước khi nhận object Engine mới. Nhìn vẻ hợp lý, tuy nhiên đoạn code trên sẽ gặp vấn đề cực kỳ lớn nếu như ta gặp phải đoạn code dưới đây PHP Code: PHP Code: Engine *engine = [Engine new]; //count: 1 Car *car1 = [Car new]; Car *car2 = [Car new]; [car1 setEngine: engine]; //count: 2 [engine release]; //count: 1 [car2 setEngine: [car1 engine]]; //count: 0 AutoRelease AutoRelease là chế mà ta không cần phải quan tâm đến việc release đối tương, nó sẽ tự động giảm retain count xuống và release khi ta không sử dụng nó nữa. Để khai báo autorelease ta sử dụng như sau : PHP Code: [PHP]Car *car1 = [[[Car alloc] init] autorelease]; [/PHP] Tuy nhiên chúng ta nên cẩn thận đối với loại này. Ví dụ hàm ta 1 đối tượng car1 trong class và nó được khai báo như trên trong phương thức A(), ở phương thức B() ta sử dụng đối tượng này sẽ bị crash do khi chạy hết hàm A() thì đối tượng car1 đã bị release. Protocols Khai báo các protocols methods thể được implement trong bất cứ class nào. Protocols thể hữu ích trong ba trường hợp sau: • Khai báo method mà class khác dự định sẽ thực thi • Khai báo interface cho một object và che dấu nội dung bên trong nó • Dễ dàng nắm bắt được cấu trúc nhiều class tương đồng liên quan (khi sử dụng chung interface) Properties Khai báo properties là một chức năng Objective-C cung cấp để ta thể khai báo và truy cập dễ dàng vào các giá trị của object thông qua các accessor methods. Khái quát Ta chủ yếu thể truy cập vào properties của object thông qua cặp method truy cập (accessor methods) được gọi là getter và setter. Sử dụng properties mang lại cho ta rất nhiều thuận lợi: • Cung cấp một cái nhìn rõ ràng cho người dùng, hiểu được cách thức tương tác với API. • Compiler thể tổng hợp các accessor methods (getter/setter) mà ta đã khai báo Khai báo và thực thi Property Trong phần này sẽ 2 phần là khai báo và thực thi property Khai báo Property Một property được khai báo bắt đầu bằng từ khóa @property. @property thể xuất hiện bất cứ ở đâu trong danh sách khai báo các methods. @property cũng xuất hiện trong phần khai báo protocol và category. PHP Code: @property (attribute) type name; Từ khóa @property khai báo một property. Giống như các dạng khác trong Objective-C, mỗi property một kiểu dữ liệu và một cái tên. Ngoài ra như ví dụ trên ta thấy còn tùy chọn các thuộc tính attribute thêm trong dấu ngoặc trong trường hợp đặc biệt, ta sẽ coi ở phần bên dưới. Tiếp theo chúng ta coi ví dụ đơn giản khai báo một property PHP Code: PHP Code: @interface MyClass : NSObject @property float value; @end Trong ví dụ trên thì dòng thứ 2 ta khai báo một property tên value kiểu float. Nó tương đương với dòng lệnh PHP Code: PHP Code: -(float)value; -(void)setValue:(float)newValue; Khai báo Property Attributes Chúng ta thể thêm vào một property các attributes theo cú pháp @property(attribute1, attribute2,…). Nếu ta dùng @synthesize (trong phần implementation) để nói cho compiler tạo các accessor methods truy cập property, compiler sẽ tự động xử lý hoàn toàn. Tuy nhiên nếu ta tự xử lý accessor methods, ta phải chắc rằng nó phù hợp với những gì ta đã khai báo trong interface, kể cả các attributes. Ta sẽ coi rõ trong phần implementation. Accessor Method Names Tên mặc định của getter và setter methods với property là PropertyName và setPropertyName. Ví dụ như property tên foo thì getter method là foo và setter method là setFoo. Tuy nhiên ta thể chỉnh sữa việc này trong property attribute với attributes getter= và setter=. Hai attributes này thể kết hợp với các attribute khác một cách dễ dàng ngoại trừ attribute readonly, vì khi đó ta không được xài setter=. Chú ý là khi ta xài hai attributes này thì trong phần implementation phải xử lý thích hợp. PHP Code: getter=getterName Khai báo trước tên accessor methods getter mà ta phải thực thi trong implementation. Chú ý getter method ko chứa parametters PHP Code: setter=setterName Khai báo trước tên accessor methods setter mà ta phải thực thi trong implementation. Chú ý setter method ko chứa parametters và không đi cùng với attribute readonly. Wriability Những attributes này quyết định khả năng read/write của property, ta thể quyết định một property thể read hay write hay không qua các attributes này PHP Code: PHP Code: readwrite :Property sẽ thể vừa read vừa write, đây là attribute mặc định readonly : Property chỉ thể read, setter method trong implementation là khô ng có. Thực thi Property Trong phần implementation, ta thể dùng @synthesize và @dynamic để báo cho compiler thực thi các property mà ta đã khai báo trên interface. Chú ý là nếu ta không sử dụng các từ kháo trên, ta sẽ phải tự thực thi các getter/setter methods một cách chính xác hoàn toàn (theo các properties đã khai báo kèm). @synthesize Chúng ta dùng @synthesize để nói compiler tạo ngầm các setter/getter methods cho property nếu chúng ta không khai báo chúng trong @implementation. Ta coi ví dụ PHP Code: PHP Code: @interface MyClass : NSObject @property(copy, readwrite) NSString *value; @end @implementation MyClass @synthesize value; @end Ta thể dùng lệnh gán để chỉ định instance variable đặc biệt nào được dùng cho property. Ví dụ PHP Code: @synthesize firstName, lastName, age=yearOld; Dòng lệnh trên tạo các accessor methods cho firstName, lastName và age trong đó giá trị của property age là giá trị của instance variable yearOld. Mặc khác @synthesize sẽ thiết lập các accessor method phù hợp với các attributes mà ta khai báo cho properties. @dynamic Một vài trường hợp accessor methods được tạo động lúc runtime, khi đó ta dùng từ khóa @dynamic để thông báo với hệ thống rằng các accessor methods sẽ được tạo động trong lúc runtime. Ta sẽ sử dụng nó và coi kỹ hơn khi thao tác với NSManagedObject. . Objective- C sử dụng một kỹ thuật gọi là reference counting hoặc đôi khi gọi là retain counting để theo vết vòng đời của object. Mỗi object sẽ có một số. dealloc return (0); } Qua ví dụ trên, ta thấy rõ cơ cấu quản lý bộ nhớ của Objective- C như thế nào. Object Ownership Cho tới giờ việc quản

Ngày đăng: 23/02/2013, 09:29

Từ khóa liên quan

Tài liệu cùng người dùng

  • Đang cập nhật ...

Tài liệu liên quan