ПРИМЕЧАНИЕ. ПРОБЛЕМА НЕ В ЭТОМ КОДЕ, НО ОТВЕТ ЗА EXC_BAD_ACCESS - это то, что сказал @strange.
Я получаю этот EXC_BAD_ACCESS после вызова метода viewForHeaderInSection, ребята, я отлаживал это для последней парычасов, поэтому моя первая таблица загружается здесь - это последовательность вызываемого метода.
ПРИМЕЧАНИЕ. У меня есть две секции, каждая из которых содержит только одну строку.
- numberOfSectionsInTableView
- viewForHeaderInSection (для секции 1)
- heightForHeaderInSection (для секции 1)
- numberOfRowsInSection (для секции 1)
- heightForRowAtIndexath для строки 1 для строки (для секции 1)0)
- viewForHeaderInSection (для секции 0)
- heightForHeaderInSection (для секции 0)
- numberOfRowsInSection (для секции 0)
- heightForRowAtIndexPath (для секции 0,строка 0)
- cellForRowAtIndexPath (для раздела 0, строка, 0)
- cellForRowAtIndexPath (для раздела 1, строка, 0)
- viewForHeaderInSection (для секции 0)
- 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];
}
}
}