EXC_BAD_ACCESS второй раз, когда я запускаю свое приложение и вызываю reloadTable - PullRequest
0 голосов
/ 01 мая 2011

ПРИМЕЧАНИЕ. ПРОБЛЕМА НЕ В ЭТОМ КОДЕ, НО ОТВЕТ ЗА EXC_BAD_ACCESS - это то, что сказал @strange.

Я получаю этот EXC_BAD_ACCESS после вызова метода viewForHeaderInSection, ребята, я отлаживал это для последней парычасов, поэтому моя первая таблица загружается здесь - это последовательность вызываемого метода.

ПРИМЕЧАНИЕ. У меня есть две секции, каждая из которых содержит только одну строку.

  1. numberOfSectionsInTableView
  2. viewForHeaderInSection (для секции 1)
  3. heightForHeaderInSection (для секции 1)
  4. numberOfRowsInSection (для секции 1)
  5. heightForRowAtIndexath для строки 1 для строки (для секции 1)0)
  6. viewForHeaderInSection (для секции 0)
  7. heightForHeaderInSection (для секции 0)
  8. numberOfRowsInSection (для секции 0)
  9. heightForRowAtIndexPath (для секции 0,строка 0)
  10. cellForRowAtIndexPath (для раздела 0, строка, 0)
  11. cellForRowAtIndexPath (для раздела 1, строка, 0)
  12. viewForHeaderInSection (для секции 0)
  13. viewForHeaderInSection (для секции 1)

И тогда моя таблица отображается правильно.

Теперь я звоню

 [self.tableView reloadTable]

Все перечисленные выше 13 методов вызываются в той же последовательности, но после числа 13 мой код переходит к методу main в следующей строке

 int retVal = UIApplicationMain(argc, argv, nil, nil); 

, показывающей EXC_BAD_ACCESS.

Я включил NSZombie в переменной окружения, но без помощи, я попробовал распределение и инструменты зомби, но ничего не понял.

Любая помощь будет полезна.

РЕДАКТИРОВАТЬ: У меня есть customView для заголовка раздела и я добавляю customView на cell.contentView

EDIT2: Извините, ребята запутаница, reloadTable выполняется правильно, это исключение исходит из какого-то другого места, я все еще пытаюсь выяснить, откуда.

EDIT3: Привет, у меня есть еще какая-то информация для обмена, когда я заново устанавливаю приложение насимулятор, то есть удаление приложения из симулятора и установка его свежим из xcode все работает нормально, теперь после новой установки я останавливаюсь через Xcode и снова запускаю через Xcode, я получаю следующее сообщение об ошибке с NSZombie

 [CALayer retainCount]: message sent to deallocated instance 0x19384fd0

где-то после того, как я перезагрузил таблицу, я точно не уверен, где эта ошибка.

(gdb) po 0x19384fd0 2011-05-01 07: 08: 06.194 Doot [51635: 207] *- [CALayer responsedsToSelector:]: сообщение, отправленное на освобожденный экземпляр 0x19384fd0

Программа получила сигнал SIGTRAP, Trap / прерывание прерывания.0x012f1657 в forwarding () Отлаживаемая программа получила сигнал, находясь в функции, вызываемой из GDB.GDB восстановил контекст до того, что было до вызова.Чтобы изменить это поведение, используйте «set unwindonsignal off». Оценка выражения, содержащего функцию (_NSPrintForDebugger), будет прекращена.(gdb) обратная трассировка

0 0x012f1657 в пересылка ()

1 0x012f1522 в forwarding_prep_0_ ()

2 0x012bf990 в CFGetRetainCount ()

3 0x000d9dc1 в CA :: release_root_if_unused ()

4 0x0015830f в x_hash_table_remove_if ()

5 0x0006commit ()

6 0x000da46d в CA :: Transaction :: наблюдатель_callback ()

7 0x0136189b в CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION (0 * 0) 0,60 * фин..1100 *

13 0x01ec7289 в GSEventRun ()

14 0x004a1c93 в UIApplicationMain ()

15 0x000025d4 в основном (argc = 1, argv = 0xbfffef2c) в main.m: 13

Последовательность потока, после которой я получаю это исключениеption.

Я выполняю асинхронную nsurlconnection, как только я получаю ответ в connectionDidFinishLoading, я сохраняю эти данные в базе данных, вызывая метод, позволяющий нам вызывать его saveData в моем классе databasehelper, в методе saveData я устанавливаю логическую переменную

   dataSaved = YES 

Два из моего контроллера представления (с таблицей в нем) наблюдают за этой логической переменной, и как только переменная установлена ​​в YES, эти два контроллера представления получают уведомление о своих

 (void)observeValueForKeyPath:(NSString *)keyPath
                  ofObject:(id)object
                    change:(NSDictionary *)change
                   context:(void *)context 

Я перезагружаю таблицу, как только таблица перезагружена, ДА, это сделано, элемент управления возвращается к connectionDidFinishLoading и затем он существует должным образом, а затем бум, я получаю это исключение, я не волнуюсь, какая строка моего кодаэто исключение наступает.

Кроме того, интересно то, что если я не установлю этот логический флаг dataSaved = YES, тогда наблюдаемыйValueForKeyPath не будет вызван, и моя таблица не перезагрузится, в этом случае мое исключениене падаетвот почему изначально я думал, что это из-за перезагрузки таблицы, и на самом деле это все еще может быть правдой.

Я помещаю часть своего кода, чтобы объяснить поток

MyAppDelegate.m

if ([facebook isSessionValid]) {  
    locationHelper = [LocationHelper sharedInstance];
    tabBarController = [[AppTabBarController createTabBarController:self] retain];
    [self.window addSubview:tabBarController.view];
}else{
    loginPageController = [[LoginPageController alloc]initWithFacebook:facebook];
    loginNavigationController = [[UINavigationController alloc] initWithRootViewController:loginPageController];
    loginNavigationController.navigationBar.barStyle = UIBarStyleBlack;
    loginPageController.navigationItem.hidesBackButton = YES;
    [self.window addSubview:loginNavigationController.view];
    [loginPageController release];
    //[localNavigationController release];
}

AppTabBarController.m

+ (UITabBarController*) createTabBarController:(id)delegate {
   UINavigationController *localNavigationController;
   NSMutableArray *localControllersArray = [[NSMutableArray alloc] initWithCapacity:2];


   FirstViewController *firstTabController = [[FirstViewController alloc]init];
   localNavigationController = [[UINavigationController alloc]   
      initWithRootViewController: firstTabController];
localNavigationController.navigationBar.barStyle = UIBarStyleBlack;
    [localControllersArray addObject:localNavigationController];

   // release since we are done with this for now they are not part of the array
   [localNavigationController release];
   [firstTabController release];

    FirstViewController *secondTabController = [[FirstViewController alloc]init];
localNavigationController = [[UINavigationController alloc]           
     initWithRootViewController: secondTabController];
     localNavigationController.navigationBar.barStyle = UIBarStyleBlack;
     [localControllersArray addObject:localNavigationController];

// release since we are done with this for now they are not part of the array
[localNavigationController release];
[secondTabController release];


UITabBarController* tabBarController = [[[UITabBarController alloc] init ] autorelease];

// load up our tab bar controller with the view controllers
tabBarController.viewControllers = localControllersArray;
tabBarController.delegate = delegate;
// release the array because the tab bar controller now has it
[localControllersArray release];
return tabBarController;

}

LoginPageController.m

 -(id)initWithFacebook:(Facebook*)facebookInstance{
self.facebook = facebookInstance;
return self;
   }

  - (IBAction)fbButtonClick:(id)sender {
NSArray *permissions;
permissions =  [NSArray arrayWithObjects:
                @"email", nil];
[facebook authorize:permissions delegate:self];
  }

 - (void)fbDidLogin {
NSLog(@"Inside LoginpageController fbDidLogin");
//NSLog(@"Access Token is %@", facebook.accessToken );
//NSLog(@"Expiration Date is %@", facebook.expirationDate );
// Store the value in the NSUserDefaults
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    [defaults setObject:facebook.accessToken forKey:ACCESS_TOKEN_KEY];
    [defaults setObject:facebook.expirationDate forKey:EXPIRATION_DATE_KEY];
    [defaults synchronize];

// This is the best place to get user details because here we know that user has already logged in
[facebook requestWithGraphPath:@"me" andDelegate:self];

}

   - (void)request:(FBRequest *)request didLoad:(id)result {
        NSLog(@"Inside LoginPageController didLoad");
         //NSLog(@"request returns user data %@",result);
        MyAppDelegate* myAppDelegate = (MyAppDelegate*)[[UIApplication    sharedApplication]delegate];
        [self.navigationController pushViewController:[AppTabBarController myAppDelegate] animated:YES];

    }

LocationHelper.m // Когда это инициализируется, я делаю

 [self.locationManager startUpdatingLocation];

 - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
//if the time interval returned from core location is more than two minutes we ignore it because it might be from an old session
        [self.locationManager stopUpdatingLocation];
        self.currentLocation = newLocation;
        [self updateDataBase];

 }

 -(void)updateDataBase{
NSLog(@"Inside updateDataBase");
BackendHelper *backendHelper = [BackendHelper sharedInstance];
[backendHelper getData];

}

BackendHelper.m

 -(void) getData{

 NSURL *getURL = [NSURL URLWithString: @"my url"];  

NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] autorelease];

//add our HTTP headers and URL
[request setValue: @ "plain/text" forHTTPHeaderField : @"Content-Type"];
[request setHTTPMethod:@"GET"];
[request setURL : getURL];


// Use NSURLConnection to asynchronously download the data. This means the main thread will not
// be blocked - the application will remain responsive to the user. 
//
// IMPORTANT! The main thread of the application should never be blocked!
// Also, avoid synchronous network access on any thread.
//

 NSURLConnection* urlConnection =
   [[[NSURLConnection alloc] initWithRequest:request delegate:self] autorelease];

}

 - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
// check for HTTP status code for proxy authentication failures
// anything in the 200 to 299 range is considered successful,
// also make sure the MIMEType is correct:
//
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
if ((([httpResponse statusCode]/100) == 2) && [[response MIMEType] isEqual:@"text/html"]) {
    NSLog(@"Response status code is:%d", [httpResponse statusCode]);
    self.responseData = [[NSMutableData alloc] init];
} else { 
    NSLog(@"didReceiveResponse error");
}

}

 - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    NSLog(@"didReceiveData");
[responseData appendData:data];
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
NSLog(@"didFailWithError");

}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSLog(@"connectionDidFinishLoading");
[self handleResponseData:responseData];
[self.responseData release];
self.responseData = nil;
}



- (void) handleResponseData:(NSData*)data {
NSString * strResult = [[NSString alloc] initWithData: data encoding:NSUTF8StringEncoding];
[[DatabaseHelper sharedInstance] saveData: strResult];
[strResult release];
}

-(void) saveData:(NSString*) strResult{
// save data to the database

dataSaved = YES;

}

FirstViewController.m

- (void)viewDidLoad 
{   
[databaseHelper addObserver:self forKeyPath:@"dataSaved" options:NSKeyValueObservingOptionNew context:nil];
uiTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 320, 372) style:UITableViewStylePlain];
uiTableView.dataSource = self;
uiTableView.delegate = self;
uiTableView.separatorStyle = UITableViewCellSeparatorStyleNone;
UIColor *background = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:@"doot_background.png"]];
self.uiTableView.backgroundColor = background;//[UIColor blackColor];
uiTableView.scrollEnabled = NO;
[background release];
[self.view addSubview:uiTableView];

}

- (void)observeValueForKeyPath:(NSString *)keyPath
                  ofObject:(id)object
                    change:(NSDictionary *)change
                   context:(void *)context 
{
if([keyPath isEqualToString:@"dataSaved"]){

    DatabaseHelper *databaseHelperObject = (DatabaseHelper*)object;
    if(databaseHelperObject.dootUpdated){
            //getData from the database
            [self.uiTableView reloadData];
        }
}
}

Ответы [ 2 ]

0 голосов
/ 01 мая 2011

возможно, вы возвращаете noOfSection больше, чем вам нужно. посмотрим, так ли это. Попробуйте проверить, сколько там разделов.

0 голосов
/ 01 мая 2011

Вам необходимо показать нам, как и когда создается этот пользовательский вид.Обратите внимание: вы всегда должны создавать «новые» настраиваемые представления каждый раз, когда этот метод вызывается viewForHeaderInSection, а затем автоматически освобождать их при возврате ИЛИ выделять и создавать настраиваемые представления для каждого «заголовка» перед вызовом [tableView reloadData], а затем освобождать их позже.Эта ошибка, скорее всего, возникает из-за того, что вы сами возвращаете настраиваемое представление с помощью «autorelease», а затем через некоторое время пытаетесь повторно использовать объект.

Эта ошибка обычно возникает, когда вы пытаетесь выпуститьобъект, который уже был освобожден или пытается получить доступ к освобожденному объекту, который теперь является висящим указателем, указывающим на некоторую другую часть памяти.Например, это может вызвать эту проблему:

  1. Вы создаете пользовательское представление в 'viewDidLoad' следующим образом:

    myView = [[CustomView alloc] initWithFrame ....];....

  2. В viewForHeaderInSection вы возвращаете его так:

    return [autoView reise myView];

ИЛИчто-то вроде этого:

viewDidLoad:
myView = [[CustomView alloc] initWithFrame....];

....


cellForRow:
cell.contentView = myView;
[myView autorelease];

и затем возвращаем его снова viewForHeaderInSection: return myView;

Другими словами, это как-то связано с тем, как вы его выделяете, как вы«повторное использование» или как вы можете автоматически выпустить его.Просто убедитесь, что вы либо создаете это представление перед выполнением, и освобождаете, когда полный viewController освобождается (или перед следующим вызовом [tableView reloadData]), ИЛИ вы создаете новое настраиваемое представление для каждого вызова viewForHeaderInSection, например:

- (UIView*) viewForHeaderInSection:
return [[[CustomView alloc] init] autorelease];
...