2011-12-21 27 views
23

Tôi đang cố chuyển đổi dự án cũ sang ARC. Tôi có một chức năng mà tạo ra UUIDs, nhưng dường như đây không còn được hỗ trợ khi sử dụng ARC:NSMakeCollectable và ARC không hoạt động

NSString *uuid = nil; 
    CFUUIDRef theUUID = CFUUIDCreate(kCFAllocatorDefault); 
    if (theUUID) { 
     uuid = NSMakeCollectable(CFUUIDCreateString(kCFAllocatorDefault, theUUID)); 
     //[uuid autorelease]; 
     CFRelease(theUUID); 
    } 

tôi nhận được lỗi biên dịch (khi cố gắng để chuyển đổi): 'NSMakeCollectable' không có sẵn: không có sẵn trong tính tham khảo tự động chế độ.

Vì vậy, câu hỏi của tôi là: làm cách nào để tạo UUID khi sử dụng ARC? Có cách nào khác mà tôi nên sử dụng không?

Trả lời

30

NSMakeCollectable() là vì lợi ích của bộ thu rác Objective-C (bản chất không được chấp nhận). ARC không biết gì về nó.

Bạn phải sử dụng thuộc tính truyền đặc biệt, thường là __bridge_transfer, để đảm bảo rằng bộ nhớ không bị rò rỉ. __bridge_transfer được sử dụng như sau:

id MakeUUID(void) { 
    id result = nil; 
    CFUUIDRef uuid = CFUUIDCreate(NULL); 
    if (uuid) { 
     result = (__bridge_transfer id)uuid; // this "transfers" a retain from CF's control to ARC's control. 
    } 
    return result; 
} 

Sửa: Như câu trả lời khác đã đề cập, CFBridgingRelease() thực hiện điều này cho bạn. Vì vậy, thay vì sử dụng (__bridge_transfer id)uuid, nó có thể sạch hơn để viết CFBridgingRelease(uuid). Họ là tương đương mặc dù, do đó, nó vào bạn mà bạn tìm thấy dễ đọc hơn.

-2

đó là định nghĩa của NSMakeCollectable

NS_INLINE id NSMakeCollectable(CFTypeRef cf) { 
    return cf ? (id)CFMakeCollectable(cf) : nil; 
} 

Tôi nghĩ rằng điều này sẽ làm việc

uuid =CFUUIDCreateString(kCFAllocatorDefault, theUUID); 
+0

Điều này sẽ rò rỉ UUID vì nó có thêm 'CFRetain' được đính kèm từ lệnh' Create'. –

+0

bạn có thể sử dụng CFRelease để phát hành – IPaPa

+1

CFRelease những gì? Bạn đã gán nó cho một '' id', mà không còn có thể được chuyển trực tiếp đến 'CFRelease()'. Bạn có thể bỏ nó trở lại, nhưng đó là chiến đấu với ARC. Đây là những gì 'CFBridgingRelease()' và '__bridge_transfer' tương đương được xây dựng để giải quyết. –

8

Khi bạn chuyển đối tượng CFString-NSString, bạn cần để cho ARC biết làm thế nào bạn muốn xử lý quản lý bộ nhớ . Trong trường hợp này, tôi sẽ đề xuất:

uuid = CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, theUUID)); 

Điều này chỉ thị CoreFoundation giải phóng đối tượng (theo yêu cầu để cân bằng Create). Cacao sẽ giữ lại đối tượng khi nó được gán cho uuid.

1
CFUUIDRef theUUID = CFUUIDCreate(NULL); 

NSString *s2ndUuid = (__bridge_transfer NSString*)CFUUIDCreateString(kCFAllocatorDefault, theUUID); 
1

Để có một UUID duy nhất trên toàn bộ ứng dụng, tôi nghĩ cách tốt nhất để đạt được điều đó là chạy nó một lần trong toàn bộ vòng đời của ứng dụng.

static NSString *uuid; 
- (NSString *)theCurrentDeviceUniqueIdentifier { 

    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
     CFUUIDRef theUUID = CFUUIDCreate(kCFAllocatorDefault); 
     if (theUUID) { 
      uuid = CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, theUUID)); 
      CFRelease(theUUID); 
     } 
    }); 

    return uuid; 
} 
Các vấn đề liên quan