2013-06-18 4 views
3

Аварийный журнал внизу.Почему мой [UIScrollView removeFromSuperview] сбой?

Знаете ли вы, по какой-либо причине, почему может произойти сбой [UIScrollView removeFromSuperview]? Scrollview содержит иерархию представлений с различными типами UIViews. Я также обнаружил, что авария ad hoc часто не является отладочной версией. Я не мог найти причин для этого.

Такой же контроллер просмотра загружается в другом потоке в iPhone, который отлично работает. Но в iPad он падает. В iPad, в контроллере контейнера, загружается только viewcontroler.view.

Incident Identifier: EE102239-34D1-4BE7-8B52-41F74AB26203 
CrashReporter Key: 2b11ea2a01ac5618e199ffc5a1e1f321600bb6a9 
Hardware Model:  iPad3,4 
Version:   ??? (???) 
Code Type:  ARM (Native) 
Parent Process: launchd [1] 

Date/Time:  2013-06-18 15:19:16.132 +0200 
OS Version:  iOS 6.1.3 (10B329) 
Report Version: 104 

Exception Type: EXC_BAD_ACCESS (SIGSEGV) 
Exception Codes: KERN_INVALID_ADDRESS at 0x00000000 
Crashed Thread: 0 

Thread 0 name: Dispatch queue: com.apple.main-thread 
Thread 0 Crashed: 
0 libobjc.A.dylib     0x3bab7070 prepareForMethodLookup + 20 
1 libobjc.A.dylib     0x3bab6fb2 lookUpMethod + 42 
2 libobjc.A.dylib     0x3bab6f7e _class_lookupMethodAndLoadCache3 + 14 
3 libobjc.A.dylib     0x3bab6638 objc_msgSend_uncached + 24 
4 QuartzCore      0x357f2a72 CA::Layer::contents_visibility_changed(CA::Transaction*, bool) + 50 
5 QuartzCore      0x357f29de CA::Layer::mark_visible(CA::Transaction*, bool) + 190 
6 QuartzCore      0x357f29b2 CA::Layer::mark_visible(CA::Transaction*, bool) + 146 
7 QuartzCore      0x357f29b2 CA::Layer::mark_visible(CA::Transaction*, bool) + 146 
8 QuartzCore      0x357f29b2 CA::Layer::mark_visible(CA::Transaction*, bool) + 146 
9 QuartzCore      0x357f29b2 CA::Layer::mark_visible(CA::Transaction*, bool) + 146 
10 QuartzCore      0x357f28d2 CA::Layer::update_removed_sublayer(CA::Transaction*, unsigned int) + 18 
11 QuartzCore      0x357f255a CA::Layer::remove_sublayer(CA::Transaction*, CALayer*) + 130 
12 QuartzCore      0x357f246a CA::Layer::remove_from_superlayer() + 34 
13 UIKit       0x35a6e92c -[UIView(Hierarchy) removeFromSuperview] + 144 
14 UIKit       0x35b857bc -[UIScrollView removeFromSuperview] + 60 
15 MyApp   0x000bde8a -[iPadNavigationController vcAnimationDone] (iPadNavigationController.m:400) 
16 UIKit       0x35a55ab6 -[UIViewAnimationState sendDelegateAnimationDidStop:finished:] + 154 
17 UIKit       0x35aca8f8 -[UIViewAnimationState animationDidStop:finished:] + 44 
18 QuartzCore      0x35801304 CA::Layer::run_animation_callbacks(void*) + 204 
19 libdispatch.dylib    0x3bed55d8 _dispatch_client_callout + 20 
20 libdispatch.dylib    0x3bed8e40 _dispatch_main_queue_callback_4CF + 224 
21 CoreFoundation     0x33c051ac __CFRunLoopRun + 1284 
22 CoreFoundation     0x33b78238 CFRunLoopRunSpecific + 352 
23 CoreFoundation     0x33b780c4 CFRunLoopRunInMode + 100 
24 GraphicsServices    0x37733336 GSEventRunModal + 70 
25 UIKit       0x35a942b4 UIApplicationMain + 1116 

Несколько строки из кода (как просили),

previous = showing; 
    showing = [ vc retain ]; 
    showing.view.frame = startFrameIn; 
    [ container addSubview:showing.view ]; 

    CGContextRef context = UIGraphicsGetCurrentContext(); 
    [ UIView beginAnimations:nil context:context ]; 
    [ UIView setAnimationDelegate:self ]; 
    [ UIView setAnimationDidStopSelector:@selector(vcAnimationDone) ]; 
    [ UIView setAnimationCurve:UIViewAnimationCurveEaseOut ]; 
    [ UIView setAnimationDuration:0.4 ]; 

    previous.view.frame = endFrameOut; 
    showing.view.frame = detailFrame; 

    [ UIView commitAnimations ]; 
} 

- (void) vcAnimationDone { 
    if (previous != nil) { 
     if (previous.view.superview != nil) { 
      [previous.view removeFromSuperview]; 
     } 
     [ previous release ]; 
     previous = nil; 
    } 
+0

Можете ли вы опубликовать код, который вызвал сбой. –

+0

Возможно ли, что еще одна анимация работает? Кажется, что какое-то сообщение отправляется на экземпляр «nil». Составлен ли он в составе ARC? – Sulthan

+0

попробуйте запустить его в симуляторе с инструментом, ищущим зомби –

ответ

1

Спасибо всем за ваши ответы, советы и рекомендации. Однако одна вещь, которую я хочу поделиться с вами, является причиной крушения. Я обнаружил, что авария была в разных потоках в разное время. У меня было несколько просмотров, загруженных с нажатием кнопки/меню в приложении для iPad. Некоторые кнопки нажимают на выборку данных из веб-службы. Таким образом, я был немного смущен, чтобы получить cuase от сбоя, анимации или URL-соединения и т. Д. ... Я пытался с включенными объектами NSZombie, но он не показывал никакой информации. Тогда я попробовал с Гвардом Малкоком. Это работает только в Simulator. И волшебным образом я нашел кодовую точку крушения. У меня есть функция для преобразования шестнадцатеричной строки в данные. Там у меня есть строка кода, чтобы завершить нулевую строку C. где я присвоил 0 в последнем индексе. и это делает крушение!

tmpCh[count] = 0; 

Я не знаю почему, но, вероятно, это занимает некоторое время в процедуре управления памятью в прошивке, так что сбой в другом потоке в разное время. Но с Guard malloc в Simulator, он всегда указывает здесь, и когда я переписываю код, авария исчезла.

/* Converts a hex string to bytes. 
Precondition: 
. The hex string can be separated by space or not. 
. the string length without space or 0x, must be even. 2 symbols for one byte/char 
. sample input: 23 3A F1 OR 233AF1 
*/ 
+ (NSData *) dataFromHexString:(NSString*)hexString 
{ 

    if (hexString.length < 1) { 
     return nil; 
    } 

    char * tmpCh = (char *) malloc([hexString length] * sizeof(char)); 
    int count = 0; 
    for (int k=0; k<hexString.length;k++) { 
     char c = [hexString characterAtIndex:k]; 

     if (c == (char)0x20) { //skip space 
      continue; 
     } 

     if (c == '0') { // skip 0x 
      if(k+1 < hexString.length){ 
       if ([hexString characterAtIndex:k+1] == 'x' 
        || [hexString characterAtIndex:k+1] == 'X') 
       { 
        k = k + 1; 
        continue; 
       } 
      } 
     } 

     tmpCh[count] = c; 
     count++; 
    } 
    tmpCh[count] = 0; // make null terminated string 

    if (count % 2) { 
     return nil; 
    } 

    NSString *temp = [[NSString alloc] initWithUTF8String:tmpCh]; 
    free(tmpCh); 

    if ([temp length] % 2 != 0) { 
     return nil; 
    } 

    NSMutableData *result = [[NSMutableData alloc] init]; 
    unsigned char byte; 
    char hexChars[3] = {0}; 
    for (int i=0; i < (temp.length/2); i++) { 
     hexChars[0] = [temp characterAtIndex:i*2]; 
     hexChars[1] = [temp characterAtIndex:i*2+1]; 

     if (![Util isValidChar:hexChars[0]] || ![Util isValidChar:hexChars[1]]) { 
      return nil; 
     } 
     byte = strtol(hexChars, NULL, 16); 
     [result appendBytes:&byte length:1]; 
    } 

    NSData * data = [NSData dataWithData:result]; 
    [result release]; 
    return data; 
} 
2

Весьма вероятной причиной является то, что вы overreleasing ваш Scrollview или один из взглядов внутри него.

Вызов removeFromSuperview затем отменяет вид вместо простого уменьшения количества удержания.

1

На самом деле, если вы все еще придерживаетесь проекта, отличного от ARC, Static Code Analysis очень полезен для такого рода ошибок. Вопросы балансировки остатка/выпуска трудно поддаются, и почти невозможно с неполным методом, поэтому я предлагаю вам, если возможно, разместить тело полного метода.