簡體   English   中英

如何將__autoreleasing地址保留為類中的強屬性?

[英]How to keep an __autoreleasing address as a strong property in a class?

如何在NSObject中將變量的地址NSObject強屬性? 我有一個名為SCPFMessageThreadQuery的類,它通過傳遞SCPFMessageThread變量的地址來進行SCPFMessageThread

@interface SCPFMessageThreadQuery ()

// This declaration seems correct.
@property (nonatomic) SCPFMessageThread *__strong *thread;

- (id)initWithRootMessage:(SCPFMessage *)root threadAddress:(SCPFMessageThread **)address;

@end

@implementation SCPFMessageThreadQuery

// Xcode somehow makes the ownership type __autoreleasing here during autocompletion.
- (id)initWithRootMessage:(SCPFMessage *)root threadAddress:(SCPFMessageThread *__autoreleasing *)address
{
    if (self = [super init]) {
        _root = root;

        // ERROR HERE. Xcode complains about changing the ownership of address.
        _thread = address;
    }
    return self;
}

@end

我得到的錯誤是這樣的:

將'SCPFMessageThread * __ autoreleasing *'分配給'SCPFMessageThread * __ strong *'更改指針的保留/釋放屬性

我計划從我的視圖控制器以下列方式使用此類:

SCPFMessageThread *thread = self.thread; // self.thread can be nil
SCPFMessageThreadQuery *query = [[SCPFMessageThreadQuery alloc]
    initWithRootMessage:self.rootMessage threadAddress:&thread];

我真的需要在這里傳遞地址。 我將對API進行多次調用,以便在應用程序代碼中完成單個對象( SCPFMessageThread )的信息。 請不要問我為什么API不會執行JOIN本身。

您不能將__autoreleasing存儲用於除局部變量之外的任何內容。 Autorelease是一種每線程行為。 跨線程或跨可能彈出自動釋放池的堆棧幀共享__autoreleasing存儲是不安全的。

默認情況下, SomeObject **類型的參數是__autoreleasing 您可以更改方法聲明,以便使用強變量。 然后你可以直接用你強大的財產的ivar:

- (id)initWithRootMessage:(SCPFMessage *)root threadAddress:(SCPFMessageThread * __strong *)address

請注意,當您獲取ivar或局部變量的地址時,ARC不會確保包含對象或堆棧幀只要您需要它就可以存活。

要顯示問題:

@interface AppDelegate ()
@property NSString * __strong * ivar;
@end

@implementation AppDelegate
- (void)storeIndirect:(NSString * __autoreleasing *)par
{
  id xpar = *par;
  _ivar = &xpar;
}
@end

通過取消引用,您可以指向可保留對象。 只有這些(而不是 “指向可保留對象的指針”)才是ARC的主題。 因此, xpar指向的對象將被保留 - 並在方法結束時釋放。

當然,您可以將xpar存儲到屬性中以保存它。 但這很明顯整個代碼都沒用:雙重間接將在ARC中丟失。 ARC關心指針后面的對象(如果它是可保留的對象)。 您的指針指向C指針,該指針不是可保留的對象。

我不認為有一個簡單的解決方案。 (但是你可以使用CFRetain()等,如果你不關心或多或少的理論CFRetain()是針對CF對象的問題。)

即使你明確地證實了這一點:為什么你需要額外的間接水平? 如果你真的真的需要它,那么考慮一下中間的額外物體:

@interface NSStringRetainableReference
@property NSString *string;
@end

@implementation
@end

將此類的實例對象作為參數傳遞。 然后你有一個指向可保留對象和另一個間接層的指針。 但在這種情況下,它是從一個對象構建的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM