簡體   English   中英

removeFromSuperview導致崩潰(非ARC)

[英]removeFromSuperview causes crash (non-ARC)

我在UIViews和手動內存管理方面遇到了一個奇怪的問題。

我有一個視圖( contentView ),它是視圖控制器的主視圖。

長按contentView之后 ,應該會淡入另一個視圖(在其頂部)。

手勢結束后,其他視圖將消失。

問題是:

contentView按時 ,我創建了輔助視圖,將其添加到contentView中 ,然后釋放它,這是ARC之前的日子的慣例。

它可以在iPhone上正常運行,但在iPad上崩潰!

崩潰的行是:

[ZPNowPlayingItemInfoView dealloc]

...當我從contentView移除輔助視圖時觸發

為什么會發生這種情況的任何線索?

如果我注釋掉發布行(請參見代碼中的注釋),則它在兩種設備上都可以正常工作,但是感覺很糟糕

這是代碼:

-(void)longPressDetected:(UILongPressGestureRecognizer*)longPressGR
{
   //Content view of the view controller I'm in
   UIView *contentView = MSHookIvar<UIView*>(self, "_contentView");

   if (longPressGR.state == UIGestureRecognizerStateBegan) {

     id item = MSHookIvar<MPAVItem*>(self, "_item");

     ZPNowPlayingItemInfoView *infoView = 
        [[ZPNowPlayingItemInfoView alloc] initWithFrame:
            CGRectMake(0,0,contentView.frame.size.width,contentView.frame.size.height) 
                item:item];

     //infoView retain count: 1

     [infoView setAlpha:0.f];
     [contentView addSubview:infoView];

     //infoView retain count: 3 (???)

     //iPad goes berserk on this line
     //Commented - Works both on iPhone and iPad
     //Uncommented - Works only on iPhone
     //[infoView release];

     //infoView retain count: 2 (if release is uncommented)

     [UIView animateWithDuration:0.35f animations:^{

         [infoView setAlpha:1.0f];

     } completion:^(BOOL finished) {

         //infoView retain count: 3

     }];

  } else if (longPressGR.state == UIGestureRecognizerStateEnded) {

     ZPNowPlayingItemInfoView* infoView = nil;

    for (UIView *subview in contentView.subviews) {

        if ([subview isKindOfClass:[ZPNowPlayingItemInfoView class]]) {

            infoView = (ZPNowPlayingItemInfoView*)subview;
            break;

        }

    }

    [UIView animateWithDuration:0.35f animations:^{

        [infoView setAlpha:0.f];

    } completion: ^(BOOL finished){

        [infoView removeFromSuperview];

    }];

 }

PS我需要使用手動內存管理。 這是對越獄設備的調整。

堆棧跟蹤:

Thread 0 name:  Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0       libobjc.A.dylib                 0x195287bdc 0x19526c000 + 0x1bbdc   // objc_msgSend + 0x1c
1     + Musix.dylib                     0x10015b19c 0x100154000 + 0x719c    // -[ZPNowPlayingItemInfoView dealloc] + 0x48
2       libsystem_blocks.dylib          0x19590d90c 0x19590c000 + 0x190c    // _Block_release + 0xfc
3       UIKit                           0x188ef8590 0x188eb0000 + 0x48590   // -[UIViewAnimationBlockDelegate dealloc] + 0x44
4       CoreFoundation                  0x1845f1374 0x1845ec000 + 0x5374    // CFRelease + 0x208
5       CoreFoundation                  0x184601004 0x1845ec000 + 0x15004   // -[__NSDictionaryI dealloc] + 0x8c
6       libobjc.A.dylib                 0x19528d720 0x19526c000 + 0x21720   // (anonymous namespace)::AutoreleasePoolPage::pop(void*) + 0x230
7       CoreFoundation                  0x1845f4f90 0x1845ec000 + 0x8f90    // _CFAutoreleasePoolPop + 0x18
8       CoreFoundation                  0x1846c774c 0x1845ec000 + 0xdb74c   // __CFRunLoopRun + 0x5d8
9       CoreFoundation                  0x1845f51f0 0x1845ec000 + 0x91f0    // CFRunLoopRunSpecific + 0x188
10      GraphicsServices                0x18d7575a0 0x18d74c000 + 0xb5a0    // GSEventRunModal + 0xa4
11      UIKit                           0x188f26780 0x188eb0000 + 0x76780   // UIApplicationMain + 0x5cc
12      Music (*)                       0x10006ee28 0x100064000 + 0xae28    // 0x0000adac + 0x7c
13      libdyld.dylib                   0x1958e2a04 0x1958e0000 + 0x2a04    // start + 0x0

ZPNowPlayingItemInfoView:

@interface ZPNowPlayingItemInfoView()

@property (nonatomic, retain) MPAVItem* item;

@property (nonatomic, retain) MPUSlantedTextPlaceholderArtworkView *artworkView;
@property (nonatomic, retain) UILabel *artistLabel;
@property (nonatomic, retain) UILabel *albumLabel;
@property (nonatomic, retain) UILabel *songLabel;

@end

ZPNowPlayingItemInfoView取消分配:

-(void)dealloc
{
    [super dealloc];

    [self.item release];

    [self.artworkView release];
    [self.artistLabel release];
    [self.songLabel release];
}

ZPNowPlayingItemInfoView類中存在一些問題。 什么時候發生此問題? 僅當對象被釋放時。 當您注釋掉[infoView release]時,將永遠不會釋放對象,也不會出現問題-但是,您將發生內存泄漏。

檢查ZPNowPlayingItemInfoView功能,尤其是其dealloc方法。 您確定構建正確嗎? item始終是有效對象嗎?

看到ZPNowPlayingItemInfoView dealloc方法后,問題ZPNowPlayingItemInfoView dealloc清楚了- [super dealloc]必須始終是最后一個調用,而不是第一個調用。 釋放對象后,訪問其屬性是未定義的操作。

在對release注釋時,這是一種可行的解決方法,它表明您已過一次發行它。 它很可能是您注釋掉的唯一一個版本。

removeFromSuperview會將保留計數減少了1。

我建議重新訪問視圖對象的整個生命周期。 但是,這可能很棘手。 每個保留都需要有一個准確的對應發行版或自動發行版。 使用其getter( self.myView = subview )將視圖分配給屬性確實會保留該視圖,並將另一個視圖重新分配給該屬性( self.myView = someOhterview )會釋放subview 相反,直接訪問iVar( myView = subview )不會維護釋放/保留周期。 不僅如此。 添加視圖並將其從數組,集合或字典中刪除會相應地更改保留計數。

因此,去深入了解它。 使用儀器觀察保留計數。

暫無
暫無

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

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