2011-04-30 110 views
0

注意:此問題不在此代碼中,但對於EXC_BAD_ACCESS的答案是@strange所說的。EXC_BAD_ACCESS第二次啓動我的應用程序並調用reloadTable

在viewForHeaderInSection方法被調用後,我得到這個EXC_BAD_ACCESS,這些傢伙我最近幾個小時已經調試過了,所以第一次我的表在這裏被加載的時候是被調用的方法序列。

注:我有兩個部分,每個只有一行。

  1. numberOfSectionsInTableView
  2. viewForHeaderInSection(對於第1部分)
  3. heightForHeaderInSection(對於第1部分)
  4. numberOfRowsInSection(對於第1部分)
  5. heightForRowAtIndexPath(對於部分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我的代碼去主要方法在下一行

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

顯示EXC_BAD_ACCESS 。

我在環境變量中啓用了NSZombie,但沒有幫助,我試過配置和殭屍工具,但找不出任何東西。

任何幫助將是有用的。

編輯:我有一個customView爲節頭和我的cell.contentView添加customView

EDIT2:爲惑對不起球員,在reloadTable被正確執行這個異常是從其他地方來了,我仍然試圖從哪裏找出答案。

編輯3:您好我有一些更多的信息可以共享,當我全新安裝應用程序在模擬器上,這意味着從模擬器中刪除應用程序,並從xcode新鮮安裝它一切正常,現在全新安裝後,我停止通過Xcode並通過Xcode中再次運行,我收到以下錯誤消息NSZombie

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

我reloadTable後某處,我正好不知道在哪裏的錯誤來。

(GDB)PO 0x19384fd0 2011-05-01 07:08:06.194使者報[51635:207] * - [CALayer的respondsToSelector:]:消息發送到釋放的實例0x19384fd0

方案接收信號SIGTRAP ,跟蹤/斷點陷阱。 0x012f1657在轉發() 被調試的程序在從GDB調用的函數中發送信號。 GDB已將上下文恢復到調用之前的狀態。 要更改此行爲,請使用「set unwindonsignal off」 將放棄包含函數(_NSPrintForDebugger)的表達式的評估。 (GDB)回溯

0 0x012f1657在在CFGetRetainCount()

3在CA 0x000d9dc1轉發()

1 0x012f1522在forwarding_prep_0_()

2 0x012bf990: :release_root_if_unused()

4 0x0015830f在x_hash_table_remove_if()

5 CA 0x000da246 ::交易::提交()

6 0x000da46d在CA ::交易:: observer_callback()

7 0x0136189b在CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION()

8 __CFRunLoopDoObservers()

9 0x012bf1d7在__CFRunLoopRun()

x012f66e

10 0x012be840在CFRunLoopRunSpecific()

11 0x012be761在CFRunLoopRunInMode()

12 0x01ec71c4在GSEventRunModal()

13 0x01ec7289在GSEventRun()

14 UIApplicationMain 0x004a1c93()

15 0x000025d4 in main(argc = 1,argv = 0xbfffef2c)at main.m:13

之後,我得到這個異常的流程序列。

我正在運行異步nsurlconnection,一旦我找回了connectionDidFinishLoading中的響應,我將該數據保存到數據庫,通過調用一個方法讓我們在saveData方法中調用saveData在我的數據庫幫助器類中設置一個布爾變量

dataSaved = YES 

我的視圖控制器中的兩個(其中具有表)正在觀察這個布爾變量,只要變量設置爲YES,這兩個視圖控制器開始他們

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

通知我重新加載桌子,一旦relo廣告表完成,是的,它完成後,控制回到 connectionDidFinishLoading,然後它正確存在,然後繁榮我得到這個異常,我嚇了一大跳,從我的代碼的哪一行這個異常即將到來不知道。

另外有趣的是,如果我沒有設置布爾標誌dataSaved = YES,那麼observeValueForKeyPath不會被調用,我的表不會重新加載,在這種情況下,我的異常不會崩潰。這就是爲什麼最初我認爲這是由於重新加載表,實際上這仍然是真的。

我把我的一些代碼來解釋流動

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]; 
     } 
} 
} 
+0

很難想象,請給出一些代碼。 – 2011-04-30 23:25:58

+0

@Nick我不知道我應該在這裏放什麼代碼,但是有一點,我忘了告訴我是有一個customView的頭,並有一個自定義的uitableviewcell,讓我知道哪些代碼將幫助,以便我可以粘貼它們這裏 – Yogesh 2011-04-30 23:41:34

+0

很多次代碼幫助解決這裏的問題。請至少發佈堆棧跟蹤。我對此有一種感覺:) – 2011-05-01 07:53:08

回答

0

你需要告訴我們如何以及何時創建自定義視圖。請注意:每次調用viewForHeaderInSection時,應該總是創建'new'自定義視圖,然後在調用[tableView reloadData]之前返回OR分配併爲每個'header'創建自定義視圖時自動釋放它們,然後再釋放它們。你看到的這個錯誤很可能是由於你自己用'autorelease'返回customview,然後在某個時候嘗試重新使用該對象。

當您嘗試釋放已釋放的對象或試圖訪問釋放的對象時,通常會發生此錯誤,該對象現在是指向內存其他部分的懸掛指針。例如,這會導致這樣的問題:

  1. 創建在 'viewDidLoad中' 自定義視圖中是這樣的:

    MyView的= [[CustomView的alloc] initWithFrame ....]; ....

  2. 在viewForHeaderInSection你這樣它返回:

    回報[MyView的自動釋放]

或者是這樣的:

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

.... 


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

,然後再次返回它viewForHeaderInSection: 回報MyView的;

換句話說,這與你如何分配它,你如何重新使用它有關,或者你如何自動釋放它。只要確保您在手動創建該視圖並釋放完整的viewController時(或在您下次調用[tableView reloadData之前])或者在每次調用viewForHeaderInSection時創建一個新的自定義視圖,如下所示:

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

是我檢查了我的代碼,它似乎像所有這一切都很好,實際上表正在得到正確加載,問題是其他地方,對不起混淆 – Yogesh 2011-04-30 23:59:20

0

可能是你返回noOfSection超過你的需要。看看是否是這種情況。嘗試檢查有多少部分。

+0

@Rahul感謝您查看此問題,我已添加更多信息這似乎是表正在重新加載正確的問題正在發生一些其他地方。 – Yogesh 2011-05-01 14:35:46

+0

@yogesh如果你可以發送來源我可以看看這個問題。 – 2011-05-01 15:18:09

+0

@Rahul,我在這裏添加了代碼,如果您需要更多我可以通過查看您的代碼,將它發送到您的電子郵件 – Yogesh 2011-05-01 16:00:14

相關問題