ОБНОВЛЕНИЕ (внизу): Добавлен весь viewWillAppear: реализация метода, чтобы показать, как три UIViewController распределяются / освобождаются в UIScrollView.
У меня естькорневой ViewController, который содержит UIScrollView
.Этот UIScrollView
сам содержит 3 различных UIViewController
с (для UITableView
с устанавливается NSFetchedResultControllerDelegate
с)
Мне нужно перезагрузить корневого ViewController UIScrollView
водна точка, когда мы возвращаемся к представлению, поэтому я делаю это в начале:
-(void) viewWillAppear:(BOOL)animated {
[dataViewScroller.subviews
makeObjectsPerformSelector:@selector(removeFromSuperview)];
.......
// and we proceed to re-load the 3 UIViewControllers into the UIScrollView.
// From testing this all seems to work fine.
// The **problem** is that that as soon as this method ends - I get an
// EXC_BAD_ACCESS error described above.
// If the above line is removed, everythign works fine.
}
Вот метод viewDidLoad для каждого из UIViewControllers
, загруженных в UIScrollView
, выглядит следующим образом:
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor clearColor];
self.expensesTableView.backgroundColor = [UIColor clearColor];
self.theTableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
self.theTableView.rowHeight = 44;
UIView *containerView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 280, 44)] autorelease];
containerView.backgroundColor = [UIColor clearColor];
// Setting up and aligning the label in the center of our view.
UILabel *headerLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 200, 20)];
headerLabel.text = NSLocalizedString(self.headerText, @"");
headerLabel.textColor = [UIColor blackColor];
headerLabel.font = [UIFont boldSystemFontOfSize:16];
headerLabel.backgroundColor = [UIColor clearColor];
headerLabel.center = containerView.center;
headerLabel.textAlignment = UITextAlignmentCenter;
[containerView addSubview:headerLabel];
// HOW IS THIS A LEAK? CAUSES EXC_BAD_ACCESS If Not commented out
//NSLog(@"Test - %@", headerLabel);
//[headerLabel release];
[self.view addSubview:containerView];
NSError *error;
if (![[self fetchedResultsController] performFetch:&error]) {
// Update to handle the error appropriately.
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
exit(-1); // Fail
}
}
В приведенном выше коде строка headerLabel release]
закомментирована.С этим программа работает нормально!Если я включаю линию [headerLabel release]
, которую я технически СЛЕДУЕТ включить, так как в противном случае это УТЕЧКА, GDB затем сообщает следующее:
MyAppTest[11110:207] *** -[CFString release]: message sent to deallocated instance 0x5d66b60
(gdb)
This is the output from malloc_history trace using the above memory address:
Identifier: MyAppTest
Version: ??? (???)
Code Type: X86 (Native)
Parent Process: gdb-i386-apple-darwin [10116]
Date/Time: 2011-03-15 03:14:47.855 -0400
OS Version: Mac OS X 10.6.6 (10J567)
Report Version: 6
ALLOC 0x5996770-0x599678f [size=32]: thread_a037a540 |start | main | UIApplicationMain | -[UIApplication _run] | CFRunLoopRunInMode | CFRunLoopRunSpecific | __CFRunLoopRun | __CFRunLoopDoSource1 | __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ | PurpleEventCallback | _UIApplicationHandleEvent | -[UIApplication sendEvent:] | -[UIApplication handleEvent:withNewEvent:] | -[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] | -[UIApplication _reportAppLaunchFinished] | CA::Transaction::commit() | CA::Context::commit_transaction(CA::Transaction*) | CALayerLayoutIfNeeded | -[CALayer layoutSublayers] | -[UILayoutContainerView layoutSubviews] | -[UINavigationController _startDeferredTransitionIfNeeded] | -[UINavigationController _startTransition:fromViewController:toViewController:] | -[AccountViewController viewWillAppear:] | -[NSManagedObjectContext executeFetchRequest:error:] | -[NSPersistentStoreCoordinator executeRequest:withContext:error:] | -[NSSQLCore executeRequest:withContext:error:] | -[NSSQLCore objectsForFetchRequest:inContext:] | -[NSSQLCore newRowsForFetchPlan:] | -[NSSQLCore _newRowsForFetchPlan:selectedBy:withArgument:] | -[NSSQLCore _prepareResultsFromResultSet:usingFetchPlan:withMatchingRows:] | CFStringCreateWithCString | __CFStringCreateImmutableFunnel3 | _CFRuntimeCreateInstance | malloc_zone_malloc
Потянув меня за волосы, потому что абсолютноНУЛЕВЫЕ сообщения или звонки на headerLabel
после того, как я отпустил it.У кого-нибудь есть предложения?пожалуйста ??
---- ОБНОВЛЕНИЕ
- (void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[dataViewScroller.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
[self.myTableViewControllers removeAllObjects];
self.myTableViewControllers = nil;
// All database modifcations should dynamically reload when the view reappears
/* RE-OBTAIN CATEGORIES */
NSManagedObjectContext *context = [myAppTestAppDelegate managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"MyObjectType" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSError *errorInRequest = nil;
NSArray *results = [context executeFetchRequest:fetchRequest error:&errorInRequest];
if(errorInRequest)
{
NSLog(@"Unresolved error %@, %@", errorInRequest, [errorInRequest userInfo]);
abort();
}
[fetchRequest release];
kNumberOfPages = [results count];
dataViewPageControl.numberOfPages = kNumberOfPages;
dataViewPageControl.currentPage = 0;
dataViewScroller.contentSize = CGSizeMake(dataViewScroller.frame.size.width * kNumberOfPages, dataViewScroller.frame.size.height);
// the view controllers are created lazily
// in the meantime, load the array with placeholders which will be replaced on demand
NSMutableArray *controllers = [[NSMutableArray alloc] init];
for (unsigned i = 0; i < kNumberOfPages; i++) {
[controllers addObject:[NSNull null]];
}
self.myTableViewControllers = controllers;
[controllers release];
int index = 0;
for (NSManagedObject *type in results) {
[self loadScrollViewWithPage:index withIdentifier:[type valueForKey:@"name"]];
index++;
}
}
- (void)loadScrollViewWithPage:(int)page withIdentifier:(NSString *)ident {
if (page < 0) return;
if (page >= kNumberOfPages) return;
MyTableListViewController *controller = [myTableViewControllers objectAtIndex:page];
if ((NSNull *)controller == [NSNull null]) {
controller = [[MyTableListViewController alloc] initWithPageNumber:page withHeader:ident];
controller.managedObjectContext = [myAppTestAppDelegate managedObjectContext];
[myTableViewControllers replaceObjectAtIndex:page withObject:controller];
[controller release];
}
if (nil == controller.view.superview) {
CGRect frame = dataViewScroller.frame;
frame.origin.x = frame.size.width * page;
frame.origin.y = 0;
controller.view.frame = frame;
[dataViewScroller addSubview:controller.view];
}
}
Итак, как вы можете видеть, они всегда загружаются динамически при загрузке Root ViewController.Это связано с тем, что пользователь может перейти на страницу администрирования типа Настройки учетной записи и добавить дополнительные категории в свои настройки.При возврате к корневому представлению в представлении прокрутки должны отображаться категории NEW / OR DELETED.Если у них изначально было 3 Cateogories (т.е. 3 TableViewControllers), и они перешли на страницу администратора и создали новую, при возврате UIScrollView должен перезагрузить все 4 категории (4 динамически создаваемых TableViewControllers.) Имеет ли это смысл?