2010-12-10 2 views
3

응용 프로그램 설명 : 저는 새로운 iPhone 개발자입니다. 두 가지 테이블 뷰를 사용한 다음 세부 뷰를 사용하는 응용 프로그램에서 작업하고 있습니다. 첫 번째 수준 테이블보기는 몇 가지 범주를 제시하며, 범주를 선택하면 해당 범주와 관련된 항목 목록이 표시됩니다. 주제가 선택되면 해당 주제와 관련된 상세보기가 표시됩니다. 테이블에서 스크롤 할 때 "EXC_BAD_ACCESS", "- [CFString retain] : 할당 해제 된 인스턴스로 전송 된 메시지"

내가 시뮬레이터 모두에서 응용 프로그램을 실행

은 잘 작동하는 것 같다 (하지만 잠깐!) :

  • 첫 번째 레벨 테이블보기 : 범주이보기 좋은로드하고 아무 문제없이 작동합니다.
  • 주제 목록보기 :이보기는 정상적으로 작동하지만 잠시 동안 만 표시됩니다. 올바른 주제를 모두로드하고 주제의 전체 목록을 신속하게 위아래로 스크롤 할 수 있습니다. 그러나 스크롤하는 동안 (응용 프로그램이 충돌 한 후) 몇 초 동안 만 작동합니다. 주제 중 하나를 선택할 수도 있고 자세히보기를 성공적으로로드 할 수 있습니다.
  • 자세히보기 : 잘 작동하지만 문제가 없습니다.

응용 프로그램에 두 개의 펜촉을 사용하고 있습니다. MainWindow.xib는 첫 번째 수준 및 항목보기 테이블을 표시합니다. TopicDetail.xib는 주제에 대한 세부 정보를 표시하는 데 사용됩니다.

DATA : 첫 번째 레벨보기는 문자열 배열로 구성된 plist에서 데이터를 가져옵니다. 주제 목록보기는 사전의 목록에서 데이터를 가져옵니다. 각 사전은 다섯 개의 문자열로 구성됩니다. 이 문자열 중 하나는 주제와 관련된 카테고리의 "태그"를 포함합니다. 1 단계보기의 범주를 선택하면 주제보기는 선택한 범주와 일치하는 "태그"가있는 주제를 선택하고이를 주제보기 테이블에 표시합니다.

문제 : 내 문제는 두 번째 "주제별보기"입니다. 내가 빨리 다음, 모든 것이 정상적으로 작동 몇 초에 대한 주제 목록을 아래로 응용 프로그램이 충돌을 스크롤하면

  • : 나는 수 있었다있는 몇 가지 방법은 충돌이 발생할 수 있습니다.

  • 화면에서 하나의 셀을 스크롤하면 동일한 셀을 문제없이 화면 위로 스크롤 할 수 있습니다. 이 작업을 반복하면 (화면에서 동일한 셀을 두 번 스크롤 한 다음 다시 화면으로 스크롤 해보십시오), 셀을 화면 위로 스크롤 할 때 응용 프로그램이 충돌합니다.

오류 메시지를 반환 된 초기 오류 메시지가 EXC_BAD_ACCESS했다. 내가 NSZombieEnabled를 사용할 때 오류 메시지가 있어요 "을 - [CFString이 유지] : 메시지 할당이 해제 된 경우로 전송"이러한 오류 메시지와 내 연구를 바탕으로

는, I는 내가 "유지"메모리 할당 문제가 생각 출시 된 객체에서 호출되고 있지만이 문제가 발생하는 곳과 해결 방법을 알 수 없습니다! 어떤 도움이라도 대단히 감사하겠습니다 - 미리 감사드립니다 !!

CODE :

첫 번째 수준보기 Controller.h :

#import 
@class TopicListController; 

@interface FirstLevelViewController : UITableViewController { 
    NSArray *controllers; 
    TopicListController *childController; 
} 
@property (nonatomic, retain) NSArray *controllers; 
@end

첫 번째 수준보기 Controller.m :


#import "FirstLevelViewController.h" 
#import "TopicListController.h" 
#import "TopicAppDelegate.h" 

@implementation FirstLevelViewController 
@synthesize controllers; 

- (void)viewDidLoad 
{ 
    self.title = @"Categories"; 
    NSString *path = [[NSBundle mainBundle] pathForResource:@"TopicCategoryList" ofType:@"plist"]; 
    NSMutableArray *array = [[NSMutableArray alloc] initWithContentsOfFile:path]; 
    self.controllers = array; 
    [array release]; 
    [super viewDidLoad]; 
} 

- (void)viewDidUnload 
{ 
    self.controllers = nil; 
    [childController release]; 
    childController = nil; 
    [super viewDidUnload]; 
} 

- (void) dealloc 
{ 
    [controllers release]; 
    [childController release]; 
    [super dealloc]; 
} 

#pragma mark - 
#pragma mark Table Data Source Methods 

- (NSInteger)tableView:(UITableView *)tableview numberOfRowsInSection:(NSInteger)section 
{ 
    return [self.controllers count]; 
} 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    static NSString *FirstLevelCell = @"FirstLevelCell";  
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:FirstLevelCell]; 

    if (cell == nil) { 
     cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:FirstLevelCell] autorelease]; 
    } 
    NSUInteger row = [indexPath row]; 
    cell.textLabel.text = [controllers objectAtIndex:row]; 
    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; 
    return cell; 
} 

#pragma mark - 
#pragma mark Table View Delegate Methods 

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    if (childController == nil) { 
     childController = [[TopicListController alloc] init]; 
    } 

    childController.title = @"Topics"; 
    NSUInteger row = [indexPath row]; 

    NSString *selectedCategory = [self.controllers objectAtIndex:row]; 
    childController.selectedCategory = selectedCategory; 
    [self.navigationController pushViewController:childController animated:YES]; 
}        

@end 

주제 목록 Controller.h :

#import 
@class TopicDetailController; 

@interface TopicListController : UITableViewController { 

    NSArray *list; 
    NSString *selectedCategory; 
    TopicDetailController *childController; 

} 

@property (nonatomic, retain) NSArray *list; 
@property (nonatomic, retain) NSString *selectedCategory; 

@end

주제 목록 Controller.m

#import "TopicListController.h" 
#import "TopicAppDelegate.h" 
#import "TopicDetailController.h" 
#import "NSArray-MutableDeepCopy.h" 
#import "TopicConstants.h" 

@implementation TopicListController 

@synthesize list; 
@synthesize selectedCategory; 

- (void)viewWillAppear:(BOOL)animated 
{ 
    NSString *path = [[NSBundle mainBundle] pathForResource:@"TopicContent" ofType:@"plist"]; 

    NSMutableArray *fullArray = [[NSMutableArray alloc] initWithContentsOfFile:path]; 
    NSMutableArray *fullArrayCopy = [fullArray mutableDeepCopy]; 

    NSUInteger items = [fullArrayCopy count]; 
    NSUInteger item=0; 

     for (item; item /*less than*/ items; item++) { 
      if ([[[fullArrayCopy objectAtIndex:item] objectForKey:CATEGORIES_KEY] 
      rangeOfString:selectedCategory 
      options:NSCaseInsensitiveSearch].location == NSNotFound) 
     { 
      [fullArrayCopy removeObjectAtIndex:item]; 
      item--; 
      items--; 
     } 
    } 

    self.list = fullArrayCopy; 
    [fullArray release]; 
    [self.tableView reloadData]; 
    [super viewWillAppear:animated]; 
} 

- (void)viewDidUnload 
{ 
    self.list = nil; 
    self.selectedCategory = nil; 
    [childController release]; 
    childController = nil; 
} 

- (void)dealloc 
{ 
    [list release]; 
    [selectedCategory release]; 
    [childController release]; 
    [super dealloc]; 
} 

#pragma mark - 
#pragma mark Table Data Source Methods 

- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger) section 
{ 
    return [list count]; 
} 

- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *) indexPath 
{ 
    static NSString *DisclosureButtonCellIdentifier = @"DisclosureButtonCellIdentifier"; 

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:DisclosureButtonCellIdentifier]; 

    if (cell==nil) { 
     cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:DisclosureButtonCellIdentifier] 
       autorelease]; 
    } 

    NSUInteger row = [indexPath row]; 
    NSString *rowString = [[list objectAtIndex:row] objectForKey:TITLE_KEY]; 
    NSString *rowDetailString = [[list objectAtIndex:row] objectForKey:SUBTITLE_KEY]; 
    cell.textLabel.text = rowString; 
    cell.detailTextLabel.text = rowDetailString; 
    cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton; 
    [rowString release]; 
    [rowDetailString release]; 
    return cell; 
} 

#pragma mark - 
#pragma mark Table Delegate Methods 

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    if (childController == nil) { 
     childController = [[TopicDetailController alloc] initWithNibName:@"TopicDetail" bundle:nil]; 
    } 


    NSUInteger row = [indexPath row]; 

    NSString *selectedTopicInformation = [[list objectAtIndex:row] objectForKey:INFORMATION_KEY]; 
    NSString *selectedTopicTitle = [[list objectAtIndex:row] objectForKey:TITLE_KEY]; 
    NSString *selectedTopicSubtitle = [[list objectAtIndex:row] objectForKey:SUBTITLE_KEY]; 
    NSString *selectedTopicTips = [[list objectAtIndex:row] objectForKey:TIPS_KEY]; 

    NSString *detailMessageInformation = [[NSString alloc] initWithFormat:@"%@.", selectedTopicInformation]; 
    NSString *detailMessageTitle = [[NSString alloc] initWithFormat:@"%@", selectedTopicTitle]; 
    NSString *detailMessageSubtitle = [[NSString alloc] initWithFormat:@"%@", selectedTopicSubtitle]; 
    NSString *detailMessageTips = [[NSString alloc] initWithFormat:@"%@", selectedTopicTips]; 

    childController.messageInformation = detailMessageInformation; 
    childController.messageTitle = detailMessageTitle; 
    childController.messageSubTitle = detailMessageSubtitle; 
    childController.messageTips = detailMessageTips; 

    childController.title = @"Topic Detail"; 

    [detailMessageInformation release]; 
    [detailMessageTitle release]; 
    [detailMessageSubtitle release]; 
    [detailMessageTips release]; 
    [self.navigationController pushViewController:childController animated:YES]; 


} 

- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath 
{ 
    if (childController == nil) { 
     childController = [[TopicDetailController alloc] initWithNibName:@"TopicDetail" bundle:nil]; 
    } 

    NSUInteger row = [indexPath row]; 

    NSString *selectedTopicInformation = [[list objectAtIndex:row] objectForKey:INFORMATION_KEY]; 
    NSString *selectedTopicTitle = [[list objectAtIndex:row] objectForKey:TITLE_KEY]; 
    NSString *selectedTopicSubtitle = [[list objectAtIndex:row] objectForKey:SUBTITLE_KEY]; 
    NSString *selectedTopicTips = [[list objectAtIndex:row] objectForKey:TIPS_KEY]; 

    NSString *detailMessageInformation = [[NSString alloc] initWithFormat:@"%@.", selectedTopicInformation]; 
    NSString *detailMessageTitle = [[NSString alloc] initWithFormat:@"%@", selectedTopicTitle]; 
    NSString *detailMessageSubtitle = [[NSString alloc] initWithFormat:@"%@", selectedTopicSubtitle]; 
    NSString *detailMessageTips = [[NSString alloc] initWithFormat:@"%@", selectedTopicTips]; 

    childController.messageInformation = detailMessageInformation; 
    childController.messageTitle = detailMessageTitle; 
    childController.messageSubTitle = detailMessageSubtitle; 
    childController.messageTips = detailMessageTips; 

    childController.title = @"Topic Detail"; 

    [detailMessageInformation release]; 
    [detailMessageTitle release]; 
    [detailMessageSubtitle release]; 
    [detailMessageTips release]; 
    [self.navigationController pushViewController:childController animated:YES]; 
} 

@end

답변

10

귀하의 문제는 tableView:cellForRowAtIndexPath:입니다. 다음을 해제해서는 안 :

[rowString release]; 
[rowDetailString release]; 

이 같은 문자열을 얻을 때 :

NSString *rowString = [[list objectAtIndex:row] objectForKey:TITLE_KEY]; 
NSString *rowDetailString = [[list objectAtIndex:row] objectForKey:SUBTITLE_KEY]; 

그들은 오토 릴리즈 객체로 반환됩니다. 자신이 보유한 무언가, 즉 새로운 것으로 시작하는 방법에서 할당했거나 보유했거나 확보 한 것만 공개해야합니다. 이것을 설명하는 좋은 기사는 objective-c memory management for lazy people입니다. 그러나 중요한 부분을 인용하는 것 :

  • 당신이 그것을 할당하면 당신은 그것을 소유합니다.
  • 복사하면 소유 할 수 있습니다.
  • 새 것으로 설정하면 소유하고 있습니다. (New는 단순히 alloc/init의 바로 가기입니다).
+0

감사합니다 !!!!!! 그 라인들은 범인이었다. 나는 이것을 추적하려고 내 머리카락을 꺼내왔다. 다시 한 번 감사드립니다! – Taz

관련 문제