2011-12-21 15 views
23

私の古いプロジェクトをARCに変換しようとしています。私は、UUIDを作成する機能を持っていませんが、ARCを使用する際に明らかにこれはもはやサポートされています。NSMakeCollectableとARCが機能しない

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

私はコンパイラエラー(変換しようとして)を取得:「NSMakeCollectable」は使用できません:自動参照カウントでは使用できませんモード。

私の質問は、どのようにARCを使用する際にUUIDを作成するのですか?私は今使用すべき別の方法がありますか?

答えて

30

NSMakeCollectable()は、(基本的に非難される)Objective-Cガベージコレクタのためのものです。 ARCはそれについて何も知らない。

メモリがリークしないようにするには、特別なキャスト属性(通常は__bridge_transfer)を使用する必要があります。

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; 
} 

編集__bridge_transferはそうのように使用される他の回答が述べたように、CFBridgingRelease()はあなたのためにこれを行います。したがって、(__bridge_transfer id)uuidを使用する代わりに、CFBridgingRelease(uuid)と書くときれいになる場合があります。彼らは同等ですが、それはあなたが読めるようになるのはあなた次第です。

-2

それは私はあなたがNSStringCFStringからオブジェクトを転送すると、これは、あなたがARCは、あなたがメモリ管理を処理する方法を知っている必要があり

uuid =CFUUIDCreateString(kCFAllocatorDefault, theUUID); 
+0

これは、 'Create'呼び出しから追加された' CFRetain'を持っているため、UUIDがリークします。 –

+0

CFReleaseを使用して – IPaPa

+1

CFをリリースすることができます。これをARC 'id'に割り当てました。これはもはや' CFRelease() 'に直接渡すことはできません。あなたはそれをもう一度キャストできますが、それはARCと戦っています。これは 'CFBridgingRelease()'とそれに相当する '__bridge_transfer'が作成するものです。 –

8

を動作するはずだと思う

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

NSMakeCollectable

の定義です。この場合、私はお勧めします:

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

これは(Createのバランスを取るために必要とされるような)オブジェクトを解放するためにCoreFoundationのを指示します。ココアは、uuidに割り当てられているオブジェクトをARC保持します。

1
CFUUIDRef theUUID = CFUUIDCreate(NULL); 

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

全アプリにまたがる単一のUUIDを持って、私はそれを達成するための最良の方法は、それが全体のアプリケーションのライフサイクルに一度実行させることだと思います。

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; 
} 
関連する問題