QUẢN LÝ BỘ NHỚ TRONG OBJECITVE C (MEMORY MANAGEMENT) Một vấn đề quan tâm lập trình ios quản lý nhớ (Memory Management), bạn đặt câu hỏi phần mềm Iphone, Mac os, IPad… chạy mượt sau thời gian dài sử dụng Đó khác biệt tuyệt vời.Đối với ngôn ngữ, Android , Windows phone… quản lý nhớ, giải phóng nhớ, thu rọn rác hoàn toàn tự động Các phương pháp quản lý nhớ Objective C: Manual Reference Counting (MRC) : quản lý nhớ thủ công, có nghĩa tự quản lý nhớ cách đánh dấu, theo vết vòng đời object Cụ thể ta đếm việc khởi tạo, sử dụng giải phóng object chương trình Autiomatic Reference Counting (ARC) : quản lý nhớ tự động, hệ thống dùng đếm tương tự MRC thêm vào phương thức quản lý nhớ tự động thời điểm compile Garbage Collection (GC) : hệ thống tự động lưu vết tự động giải phóng vùng nhớ object không cần thiết Nó sử dụng kỹ thuật quản lý nhớ khác với MRC ARC, nhiên GC hỗ trợ Mac OS X mà không hỗ trợ iOS IOS sử dụng trình ARC để giải phóng nhớ, rọn rác Tuy nhiên quản lý biến thuộc tính cho phép tham chiếu đến đối tượng nào? phép giải phóng? … Quản lý nhớ biến: Trước vào cụ thể có lưu ý số thuật ngữ sau tiện cho sử dụng Lưu ý: Trỏ đến = tham chiếu đến Sở hữu đối tượng = có quyền định đến tồn đối tượng Strong trỏ đến đối tượng có quyền sở hữu đối tượng, nghĩa có quyền định đến tồn đối tượng – Mặc định strong: Khi bị gán nghĩa trỏ đến đối tượng ô nhớ chứa đối tượng cũ bị giải phóng strong NSArray *Arr=@[@(1)]; Arr=@[@(10)];//Arr trỏ đến vùng nhớ Vùng nhớ cũ bị giải phóng. NSLog(@"%@",Arr); Ở Arr biến strong, kiểu liệu NSArray, trỏ tới vùng nhớ chứa giá trị:@[@(1)], sở hữu vùng nhớ Arr=@[@(10)]; Arr trỏ đến vùng nhớ chứa giá trị @[@(10)] dẫn tới vùng nhớ chứa giá trị @[@(1)] trỏ tới bị giải phóng =>Ngay lật tức vùng nhớ cũ bị ARC giải phóng kết quả: Arr=10 – Đối với strong gán strong : // biến kiểu strong gán strong strong NSArray *Arr1=@[@(1)]; strong NSArray *Arr2=Arr1;// gán mảng trỏ đến vùng nhớ!!! quyền sở hữu Arr1=@[@(10)];// thay đổi vùng nhớ cho Arr1 nhiên thằng Arr2 trỏ đến, vùng nhớ cũ tồn NSLog(@"%@",Arr2); strong Arr1 trỏ vào vùng nhớ đối tượng có giá trị @[@(1)], có quyền sở hữu đối tượng Arr2=Arr1 => Arr2 trỏ đến vùng nhớ đối tượng Arr1 trỏ với, có quyền sở hữu Vì gán lại Arr1=@[(10)] vùng nhớ cũ không bị giải phóng Kết Arr2=1; -Đối với weak gán strong: Weak trỏ tới đối tượng , quyền sở hữu đến đối tượng, nghĩa quyền định đến tồn đối tượng thêm đoạn mã sau: // kiểu weak gán strong strong NSArray *Arr3=@[@(1)]; weak NSArray *Arr4=Arr3;// Arr4 trỏ vào vùng nhớ Arr3, phụ thuộc Arr3 vùng nhớ Arr3 bị xoá Arr4 nil Arr3=@[@(10)]; NSLog(@"%@",Arr4); strong Arr3 trỏ vào vùng nhớ đối tượng có giá trị @[@(1)], có quyền sở hữu đối tượng weak Arr4 = Arr3 => Arr trỏ đến vùng nhớ đối tượng Arr3, quyền sở hữu vùng nhớ đó, tham chiếu gián tiếp thông qua Arr3 Khi Arr3=@[@(10)]; Arr3 trỏ đến vùng nhớ chứa đối tượng mới, mà Arr3 có quyền sở hữu vùng nhớ cũ dẫn tới vùng nhớ cũ bị giải phóng , dẫn tới Arr4=nil rỗng kết Arr4=nil; unsafe_unretained: unsafe_unretained trỏ vùng nhớ cũ.khi vùng nhớ bị giải phóng trỏ đến vùng nhớ giải phóng, dẫn đến crash chương trình vùng nhớ bị xoá Tuy nhiên :giải phóng nghĩa vùng nhớ bị xoá kiểu thùng rác quản lý máy tính lưu lại thời gian sau xóa Kiểu gán không làm tăng vùng nhớ, dùng gán biến tạm strong NSArray *Arr5=@[@(1)]; unsafe_unretained NSArray *Arr6=Arr5; Arr5=@[@(10)]; NSLog(@"%@",Arr6); Thằng Arr6 trỏ vùng nhớ cũ Arr5 cho dù Arr5 giải phóng vùng nhớ cũ May mắn kết quả: Arr6=1 Tuy nhiên để thời gian không sử dụng biến gây crash chương trình vùng nhớ giải phóng lưu lại thùng rác mà chưa bị xoá, sau thời gian đầy thùng rác bị xoá gây crash chương trình Quản lý vùng nhớ property : Tính đồng hóa thread: nonatomic: Không độc quyền nghĩa nhiều thread thời điểm thay đổi giá trị thuộc tính, dẫn tới không an toàn Lưu ý:Nếu có luồng truy cập vào biến tốc độ nhanh atomic (default): Độc quyền, nghĩa nhiều thread truy cập thread gán giá trị chỉnh sửa xong cho phép thread khác sử dụng biến để chỉnh sửa Lưu ý:Truy cập chậm nonatomic có luồng có chế khóa mặc định có nhiều luồng truy cập! Tính cho phép đọc ghi liệu vào thuộc tính Property: (IVar đọc ghi bình thường) readwrite (default): cho phép đọc, ghi vào thuộc tính readonly : cho phép đọc, không cho phép ghi (set),”các biến thể đọc ghi bình thường” Thay đổi tên mặc định cho hàm get, set Property: Do tên set get thường tính từ, thuộc tính danh từ, or ta muốn quản lý lại get set, nên ta cần nhu cầu thay đổi tên get set mặc định @property(assign,getter=isAge,setter=setIsAge:) int age; sử dụng “getter = tên getter mới”, “setter=tên setter mới:” Quản lý nhớ thuộc tính đối tượng Đối với thuộc tính kiểu đối tượng Objective C: Lưu ý: nhắc lại Trỏ đến = tham chiếu đến Sở hữu đối tượng = có quyền định đến tồn đối tượng Strong pointer weak pointer đề cập đến việc tham chiếu mạnh hay yếu tới object Strong pointer: trỏ, trỏ đến đối tượng sở hữu (own) đối tượng đó.biến iVar weak pointer Weak pointer: trỏ, trỏ đến đối tượng không sở hữu (own) đối tượng đó.weak thường kèm với đối tượng kiểu strong.” biến iVar strong pointer, tương đương với retain Ví vụ minh họa: Ta khai báo class sinhVien sau: @interface sinhVien : NSObject @property(strong,nonatomic) NSArray *model; -(void) infor; @end Thực thi hàm infor: @implementation sinhVien -(void) infor{ NSArray *arr=@[@(0)]; self.model=arr; arr=nil; NSLog(@"strong : %@",self.model); } @end Tương tự kiểu strong biến mà giải thích trên: kết model=0 có quyền sở hữu tham chiếu mạnh ta thay đổi strong thành weak @property(weak,nonatomic) NSArray *model; model=nil tham chiếu yếu quyền sở hữu đối tượng Tương tự weak biến mà giải thích unsafe_unretained: Tương tự unsafe_unretained biến, Dùng cho kiểu thuộc tính đối tượng Copy: copy: cố gắng copy property gán copy chép toàn đối tượng property gán! xong lưu đối tượng vào vùng nhớ Copy phát huy tác dụng muốn tạo chỉnh sửa mà không ảnh hưởng đến đối tượng cũ Sử dụng chủ yếu NSMutableDictionary, NSMutableString, NSMutableArray, lấy liệu tuỳ chỉnh Ví dụ sau: @interface sinhVien : NSObject @property(copy,nonatomic) NSMutableArray *model; -(void) infor; @end Thực thi hàm infor: @implementation sinhVien -(void) infor{ NSMutableArray *arr=@[@(0)]; self.model=arr; arr=nil; NSLog(@"strong : %@",self.model); } @end Khi giải phóng vùng nhớ arr=nil, kết quả: model=0 taon trỏ đến vùng nhớ nên vùng nhớ cũ bị giải phóng không ảnh hưởng đến kết model Đối với thuộc tính kiểu nguyên thủy C: Assign(default): trỏ vào ô nhớ tương tự unsafe_unretained, nhiên dùng nhẹ nhàng nhiều, dùng cho kiểu nguyên thủy C Chú ý: kiểu nguyên thủy C khai báo trỏ vào vùng nhớ mà không bị thay đổi vùng nhớ, tham chiếu giá trị cho biến Assign phát huy ưu điểm trỏ vào vùng nhớ