2

enter image description here我有對象,它使用委託塊。我正在使用ARC。對塊中自我的弱引用有時會導致BAD_EXCESS

@implementation ViewController 

- (void)createGame 
{ 
    _game = [[MRCircusGame alloc] init]; 
    _game.mainView = self.view; 
    _game.stageObjectsDictionary = [self getStageObjectsDictionary]; 
    [_game prepareGame]; 
} 

- (NSMutableDictionary *)getStageObjectsDictionary 
{ 
    StrongMan *strongMan = [[StrongMan alloc] initAndCreateImageViewWithFrame:kStrongManIntroFrame inView:self.view]; 
    strongMan.isTakingTouches = NO; 
    strongMan.isVisible = NO; 
    [tempDictionary setObject:strongMan forKey:kMRCircusStrongMan]; 
    return tempDictionary; 
} 

@interface MRCircusGame 
{ 
@property (nonatomic, strong) NSMutableDictionary *stageObjectsDictionary; 
} 

@implementation StrongMan 
.. 
-(void)method 
{ 
    __weak typeof (self) weak_self = self; 
    self.animator.didEndAnimating = ^{ 
      StrongMan *strongRef = weak_self; 
      strongRef.isAnimating = NO; 
      [strongRef idle]; 
    }; 
} 

一些問題:

如果我不使用弱引用自我,讓Xcode的有關可能的保留週期一定的警示作用。但是,我來看看在儀器沒有檢測到memery泄漏甚至我用self.isAnimating = YES;

如果我不使用這個strongRef解決辦法,有時我BAD_EXCESS所以我認爲這weak_self發佈了是嗎?我應該一直使用strongRef來防止我的應用程序崩潰嗎?

當該塊執行結束時,會釋放strongRef嗎?

+0

從您顯示的代碼中獲取EXEC_BAD_ACCESS是不可能的。是的,如果'self'在塊觸發前被釋放,那麼'weak_self'將是'nil','strongRef'也是。但是你只是在'strongRef'上調用方法,並且在Objective-C中調用'nil'上的方法是可以的。你必須在其他地方遇到問題。 – newacct 2013-04-28 20:11:15

+0

此外,您顯示的圖片與您的代碼不符。這是什麼? – newacct 2013-04-28 20:14:42

+0

不應該把塊內的引用反而變爲weak_self自己? (圖片內) – mnl 2014-05-22 11:18:18

回答

2

對弱引用的強引用是在塊運行時保持自己活着的常用技術。在block的結尾處,strongRef將被釋放。如果

  • 您使用的強引用自身塊
  • 儀器將只顯示一個不可達的對象,並在你的dealloc

  • 沒有零的參考塊,你無對StrongMan的引用
+0

所以我說得對。很高興聽到。 – alexhajdu 2013-04-28 16:32:32

+0

或者我應該只用自己而不在意警告? – alexhajdu 2013-04-28 18:14:27

+0

有三種方法可以打破循環:1)範圍界定:複製變量,因此您不需要引用自我。 2)以編程方式:無導致保留週期的塊屬性。 3)屬性:使用弱引用。你不能使用1),因爲你需要設置自己的屬性,但是你可以根據自己的選擇使用2或3。我更喜歡3)所以我不必記住以後再沒有任何東西。 – Jano 2013-04-28 18:29:55

-1

正確的方法做,這是直接訪問實例變量:

_animator.didEndAnimating = ^{ .... }; 
+0

動畫師是StrongMan超級類的屬性 – alexhajdu 2013-04-28 12:57:03

+0

動畫師沒有問題,但是執行代碼塊內的代碼 – alexhajdu 2013-04-28 12:58:23

+1

@mundi ::這怎麼回事? *真正好奇* – 2013-04-28 15:28:43

0

如果使用弱引用和StrongMan實例的動畫停止您的應用程序會崩潰之前被釋放。爲防止崩潰,應在釋放對象時刪除引用。在dealloc方法使用下面的代碼應該這樣做:

self.animator.didEndAnimating = nil; 
+0

不應該AFAICS __weak自我消失時會消失,不是? – 2013-04-28 15:29:25

+0

是的,你是對的。你在哪一行得到BAD_EXCESS? – murat 2013-04-28 15:34:39

1

我以前遇到過類似的問題。該問題的主要原因是,該對象在動畫結束之前被釋放。所以當這個塊被執行時,引用的「self」不在那裏。

我認爲有兩個解決此問題:

  1. 您覆蓋「的dealloc」方法,然後分配給無self.animator.didEndAnimating。所以在動畫之後沒有執行任何操作。

  2. 在塊中,你可以檢查天氣「自我」是否爲零,然後做你想做的。

+0

1會工作,2我不會得到..但再次AFAICS這不應該需要__弱化變量被剔除,不是嗎? – 2013-04-28 15:30:20

+0

1)我真的需要在動畫完成後執行整個塊。 2)也許它會起作用,但是從一開始就強力參照weak_self並不好? – alexhajdu 2013-04-28 16:36:38

+0

@alexhajdu然後在這種情況下問題是對象的重新分配。你如何保留這個對象?我認爲在這種情況下我們正在討論一個「視圖」,所以如果您將視圖分配給視圖控制器的強變量,就可以按照我的理解解決問題。 – 2013-04-28 18:47:52