2012-11-20 65 views
2

這段代碼用在非ARC編譯罰款:ARC投 - 駭客objc對象的內存

int *privateObjMemory = (int *)[myObject performSelector:@selector(privateMethod)]; 

現在我在ARC我得到:

演員一個Objective-C的指向'int *'的指針不允許使用ARC

我該如何解決這個問題? :)

回答

3

把它寫成:

int* privateObjMemory = [myObject privateMethod]; 

;)

要避免這種情況的是它的曖昧ARC的原因。 performSelector:返回一個對象 - 應該保留int*嗎?嗯...不。

更新基於

的意見,並移除先前改寫:

但是,這並不是一個很好的解決方案。如果你正在調用一個特定的私有API,那麼你必須知道它的簽名(例如參數和返回類型)。如果它是您的私有API,那麼找出一種方法使該私有界面有選擇性地可見。

如果是別人的私有API,則在具有正確參數和返回類型的類型上聲明一個類別。

然後,選擇器被正確聲明,並且編譯器將能夠通過直接消息傳遞對象來正確設置呼叫 - 無需使用performSelector:

+0

問題是,privateMethod不可見,所以''myObject privateMethod];''觸發器:>>'「MyObject沒有可見的@interface聲明選擇器privateMethod」'。因爲它是私人的:p – nacho4d

+0

@ nacho4d使用未命名的選擇器也可能導致警告。因爲你顯然超出了安全的地步,這裏= p只是用正確類型的原型聲明一個類別。如果它是您自己的私有API,那麼只需找出一個更好的方法來使該私有界面可見*選擇性*。這些都比使用上面的'void *'更安全。 – justin

+0

API是Appl ...啊哈......別人。創建類別似乎工作正常。雖然我用它來做:'if([myObject respondsToSelector:@selector(privateMethod)]){...'以確保這個黑客不會導致崩潰。現在,即使真實的實現不存在,新的屬性該子句總是YES。我如何檢查'privateMethod'確實存在,如果我聲明屬性? – nacho4d

0

我不認爲這是真的與ARC聯繫在一起。 ARC只會導致警告或錯誤。 AFAIK(並且我不在血液中籤名)使用performSelector調用的方法的返回值是nil或id。因此它必須是一個不是標準的對象。它可能適用於int *,因爲id是對一個對象的引用(而不是標量)。爲了節省一方,你應該改變你的代碼並返回一個NSNubmer對象。

0

使用id作爲您的對象的類型。

2

不要將Obj-C指針投向int *,如果使用ARC,則沒有辦法解決此問題。

是這樣的原因,是因爲ponter轉換爲int*在運行時意味着沒有方法來跟蹤指針指向的對象的內存。因此,在不使用ARC時允許(因爲您可以自己管理內存),但在ARC處於活動狀態時不能使用。

如果必須做到這一點,那麼你可以在它的正在使用的文件禁用ARC。使用上實現文件的-fno-objc-arc編譯器標誌,項目設置之內。

enter image description here

+0

這將是我的最後一個選擇...... :)我真的希望有一種方法可以做到這一點與ARC – nacho4d

+0

我會重申,「不要投出一個Obj-C指針int *,這是沒有辦法解決這個如果使用ARC「。這個解決方案意味着你可以保持你的代碼的原樣,所以它的風險要小得多,尤其是當我假設它已經過去嘗試和測試的時候;) – WDUK

0

在ARC documentation,它們是專門說..

id和void *之間沒有隨意的轉換。

performSelector返回一個id並且它不能用非客觀的C對象引用鑄造。

在我鏈接的文檔中,向下滾動並在「管理免費橋接」一節下閱讀。