Так что я думаю, что сойду с ума.Сказка о двух UIViewControllers
Я обновил XCode 4.2, поэтому у меня был бы IOS 5 SDK.
У меня есть приложение, которое отлично работает до обновления. Теперь у меня странная проблема. Он не работает на моем IOS 5 iPad 2, и он не будет работать в симуляторе IOS 5. Прекрасно работает в 4.3 симуляторе.
Для целей этого вопроса у меня есть два класса на основе UIViewController. Они не используют файлы NIB. Один, называемый HistoryBrowser, отлично работает. Другой, NoteBrowseViewController, построенный по тем же линиям, не работает.
От NoteBrowseView.Controller.h:
@interface NoteBrowseViewController : UIViewController <UITableViewDelegate, UITableViewDataSource, NSFetchedResultsControllerDelegate, UIActionSheetDelegate, UISearchDisplayDelegate, UITabBarDelegate, MKMapViewDelegate> {
UITableView* tableView;
... buncha other vars ...
}
@property (retain, nonatomic) UITableView* tableView;
... buncha other properties ...
От NoteBrowseViewController.m:
@synthesize tableView
- (id)initWithEditing:(BOOL)inEditingMode inserting:(BOOL)inserting {
self=[super init];
if (self) {
self.isInserting=inserting;
self.isEditing=inEditingMode;
self.viewIsMap=NO;
self.insertType=defInsertTypeLink;
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSDictionary *appDefaults = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:0],@"viewSortOrder",
[NSNumber numberWithInt:1],@"priorityView",
[NSNumber numberWithBool:NO],@"simpleView",
nil];
[defaults registerDefaults:appDefaults];
self.viewIsSimple=[[NSUserDefaults standardUserDefaults]boolForKey:@"simpleView"];
}
return self;
}
-(void)loadView {
self.view=[[UIView alloc]initWithFrame:[[UIScreen mainScreen] applicationFrame]];
UIButton* aButton;
UIImage* buttonImage;
UIBarButtonItem* spacer=[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
UISegmentedControl* sc=[[UISegmentedControl alloc]initWithItems:[NSArray arrayWithObjects:@"Alpha",@"Edit", @"View", nil]];
[sc addTarget:self action:@selector(segmentedControlValueChanged:) forControlEvents:UIControlEventValueChanged];
[sc setWidth:55.0 forSegmentAtIndex:0];
[sc setWidth:55.0 forSegmentAtIndex:1];
[sc setWidth:55.0 forSegmentAtIndex:2];
sc.selectedSegmentIndex=[[NSUserDefaults standardUserDefaults] integerForKey:@"viewSortOrder"];
sc.segmentedControlStyle=UISegmentedControlStyleBar;
UISegmentedControl* prisc=[[UISegmentedControl alloc]initWithItems:[NSArray arrayWithObjects:@"Open",@"All", nil]];
[prisc addTarget:self action:@selector(prioritySegmentedControlValueChanged:) forControlEvents:UIControlEventValueChanged];
[prisc setWidth:55.0 forSegmentAtIndex:0];
[prisc setWidth:55.0 forSegmentAtIndex:1];
prisc.selectedSegmentIndex=[[NSUserDefaults standardUserDefaults] integerForKey:@"priorityView"];
prisc.segmentedControlStyle=UISegmentedControlStyleBar;
UIBarButtonItem* segmentedButton=[[UIBarButtonItem alloc]initWithCustomView:sc];
UIBarButtonItem* prioritySegmentedButton=[[UIBarButtonItem alloc]initWithCustomView:prisc];
buttonImage=[UIImage imageNamed:@"13-plus.png"];
aButton=[UIButton buttonWithType:UIButtonTypeCustom];
[aButton setImage:buttonImage forState:UIControlStateNormal];
aButton.frame=CGRectMake(0.0, 0.0, buttonImage.size.width, buttonImage.size.height);
UIBarButtonItem* addButton=[[UIBarButtonItem alloc]initWithCustomView:aButton];
[aButton addTarget:self action:@selector(addButton:) forControlEvents:UIControlEventTouchUpInside];
buttonImage=[UIImage imageNamed:@"187-pencil.png"];
aButton=[UIButton buttonWithType:UIButtonTypeCustom];
[aButton setImage:buttonImage forState:UIControlStateNormal];
aButton.frame=CGRectMake(0.0, 0.0, buttonImage.size.width, buttonImage.size.height);
UIBarButtonItem* editButton=[[UIBarButtonItem alloc]initWithCustomView:aButton];
[aButton addTarget:self action:@selector(editButton:) forControlEvents:UIControlEventTouchUpInside];
buttonImage=[UIImage imageNamed:@"21-circle-east.png"];
aButton=[UIButton buttonWithType:UIButtonTypeCustom];
[aButton setImage:buttonImage forState:UIControlStateNormal];
aButton.frame=CGRectMake(0.0, 0.0, buttonImage.size.width, buttonImage.size.height);
UIBarButtonItem* simplify=[[UIBarButtonItem alloc]initWithCustomView:aButton];
[aButton addTarget:self action:@selector(simplify:) forControlEvents:UIControlEventTouchUpInside];
buttonImage=[UIImage imageNamed:@"25-circle-west.png"];
aButton=[UIButton buttonWithType:UIButtonTypeCustom];
[aButton setImage:buttonImage forState:UIControlStateNormal];
aButton.frame=CGRectMake(0.0, 0.0, buttonImage.size.width, buttonImage.size.height);
UIBarButtonItem* complexify=[[UIBarButtonItem alloc]initWithCustomView:aButton];
[aButton addTarget:self action:@selector(complexify:) forControlEvents:UIControlEventTouchUpInside];
buttonImage=[UIImage imageNamed:@"243-globe.png"];
aButton=[UIButton buttonWithType:UIButtonTypeCustom];
[aButton setImage:buttonImage forState:UIControlStateNormal];
aButton.frame=CGRectMake(0.0, 0.0, buttonImage.size.width, buttonImage.size.height);
UIBarButtonItem* map=[[UIBarButtonItem alloc]initWithCustomView:aButton];
[aButton addTarget:self action:@selector(mapify:) forControlEvents:UIControlEventTouchUpInside];
buttonImage=[UIImage imageNamed:@"162-receipt.png"];
aButton=[UIButton buttonWithType:UIButtonTypeCustom];
[aButton setImage:buttonImage forState:UIControlStateNormal];
aButton.frame=CGRectMake(0.0, 0.0, buttonImage.size.width, buttonImage.size.height);
UIBarButtonItem* notes=[[UIBarButtonItem alloc]initWithCustomView:aButton];
[aButton addTarget:self action:@selector(showNotes:) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem* cancelButton=[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(cancelButtonPressed:)];
self.doneToolbar=[NSArray arrayWithObjects:spacer, cancelButton, nil];
self.toolbar=[[[UIToolbar alloc]init]autorelease];
if(self.isEditing) {
self.complexToolbar=[NSArray arrayWithObjects:simplify, spacer, segmentedButton, prioritySegmentedButton, spacer, cancelButton, nil];
self.simpleToolbar=[NSArray arrayWithObjects:complexify, spacer, cancelButton, nil];
}
else {
self.complexToolbar=[NSArray arrayWithObjects:simplify, map, spacer, segmentedButton, prioritySegmentedButton, spacer, addButton, editButton, cancelButton, nil];
self.simpleToolbar=[NSArray arrayWithObjects:complexify, map, spacer, addButton, editButton, cancelButton, nil];
}
self.mapToolbar=[NSArray arrayWithObjects:notes, spacer, prioritySegmentedButton, spacer, cancelButton, nil];
if (self.viewIsSimple) {
[self.toolbar setItems:self.simpleToolbar animated:YES];
}
else {
[self.toolbar setItems:self.complexToolbar animated:YES];
}
self.toolbar.autoresizingMask=UIViewAutoresizingFlexibleWidth;
[self.toolbar sizeToFit];
CGFloat toolbarHeight = [self.toolbar frame].size.height;
CGRect rootViewBounds=self.view.bounds;
CGFloat rootViewHeight = CGRectGetHeight(rootViewBounds);
CGFloat rootViewWidth = CGRectGetWidth(rootViewBounds);
[self.toolbar setFrame:CGRectMake(0,0, rootViewWidth, toolbarHeight)];
self.mapView=[[[MKMapView alloc]initWithFrame:CGRectMake(0, toolbarHeight, rootViewWidth, rootViewHeight-(self.isInserting?49:0)-toolbarHeight)]autorelease];
self.mapView.delegate=self;
self.mapView.zoomEnabled=YES;
self.mapView.scrollEnabled=YES;
self.mapView.autoresizingMask=UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleBottomMargin;
self.tableView=[[UITableView alloc]initWithFrame:CGRectMake(0, toolbarHeight, rootViewWidth, rootViewHeight-(self.isInserting?49:0)-toolbarHeight)
style:UITableViewStylePlain];
self.tableView.delegate=self;
self.tableView.dataSource=self;
self.tableView.autoresizingMask=UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleBottomMargin;
self.view.autoresizesSubviews = YES;
self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
UISearchBar* searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 44, rootViewWidth, 44.0)];
searchBar.autoresizingMask = UIViewAutoresizingFlexibleWidth;
searchBar.autocorrectionType = UITextAutocorrectionTypeNo;
self.tableView.tableHeaderView = searchBar;
self.searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:searchBar contentsController:self];
self.searchDisplayController.delegate = self;
self.searchDisplayController.searchResultsDataSource = self;
self.searchDisplayController.searchResultsDelegate = self;
[self.view addSubview:self.tableView];
[self.view addSubview:self.toolbar];
if (self.isInserting) {
UITabBarItem* item1=[[[UITabBarItem alloc]initWithTitle:@"Link" image:nil tag:defInsertTypeLink]autorelease];
UITabBarItem* item2=[[[UITabBarItem alloc]initWithTitle:@"Contents Later" image:nil tag:defInsertTypeContentsLater]autorelease];
UITabBarItem* item3=[[[UITabBarItem alloc]initWithTitle:@"Contents Now" image:nil tag:defInsertTypeContentsNow]autorelease];
UITabBar* tabbar=[[UITabBar alloc]initWithFrame:CGRectMake(0, rootViewHeight-49, rootViewWidth, 49)];
tabbar.autoresizingMask=UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleTopMargin|UIViewAutoresizingFlexibleBottomMargin;
[tabbar setDelegate:self];
[tabbar setItems:[NSArray arrayWithObjects:item1, item2, item3, nil] animated:YES];
[tabbar setSelectedItem:item1];
[self.view addSubview:tabbar];
}
if(self.viewIsSimple) {
self.contentSizeForViewInPopover = CGSizeMake(200.0, 625.0);
}
else {
self.contentSizeForViewInPopover = CGSizeMake(450.0, 625.0);
}
self.view.autoresizesSubviews = YES;
self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
self.note=nil;
[sc release];
[prisc release];
[addButton release];
[prioritySegmentedButton release];
[cancelButton release];
[segmentedButton release];
[spacer release];
[editButton release];
[map release];
[simplify release];
[complexify release];
}
И, наконец, NoteBrowseViewController конкретизируется константы выглядит с другого контроллера вида:
self.noteBrowseViewController=[[NoteBrowseViewController alloc]initWithEditing:NO inserting:NO];
self.noteBrowseViewController.delegate=self;
self.popoverController = [[UIPopoverController alloc]initWithContentViewController:self.noteBrowseViewController];
self.popoverController.delegate = self;
[self.popoverController presentPopoverFromRect:((UIButton*)sender).frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
Так вот что происходит. Если я запускаю это в отладке, и следовать, как только исполнение попадает в эту линию:
CGRect rootViewBounds=self.view.bounds;
программа падает со следующими ошибками:
2011-10-20 11:42:02.703 ActionNote3[12332:15803] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil'
*** First throw call stack:
(0x1eb0052 0x2a60d0a 0x1e9d36e 0x1e9e220 0x1968cb6 0x5153b 0x50e11 0x50879 0x52e4a 0xdcc64e 0x4bcb3 0x72d1 0x1eb1ec9 0xd095c2 0xd0955a 0xdaeb76 0xdaf03f 0xdae2fe 0xd2ea30 0xd2ec56 0xd15384 0xd08aa9 0x20c7fa9 0x1e841c5 0x1de9022 0x1de790a 0x1de6db4 0x1de6ccb 0x20c6879 0x20c693e 0xd06a9b 0x2dbd 0x2d35)
terminate called throwing an exception
Наблюдая вещи во время отладки, я знаете, что self.view настроен правильно и что loadView вызывается, когда это должно быть. И это не та линия, которая заставляет ее потерпеть неудачу - это все, что относится к self.view! какие???
Что действительно заставляет меня сходить с ума, так это то, что у меня есть еще один подклассовый контроллер, HistoryBrowser, который загружается точно так же ... и он отлично работает.
Таким образом, помимо того, что расстроен тем, что я не могу понять это, я хотел бы понять:
- Что изменилось в XCode 4.2 (из 4.1), что приведет к этому, или это ИОС 5 выпуск?
- Что означает эта ошибка, и что я могу сделать ?
EDIT:
Так на основе предложений от ответа Abberant в поле ниже, я:
- изменил initwithnib просто быть INIT
- удален метод loadView
- добавившие полное сообщение об ошибке
- добавлен более релевантный код метода init
И теперь ссылка на self.view работает правильно. Но вещи только что стали незнакомыми.
Выполнение делает это мимо первой ссылки на self.view без ошибок. Однако теперь он прекращается:
self.tableView.tableHeaderView = searchBar;
в методе init.
Сообщение об ошибке получила жуть похож на тот, который я получал раньше:
2011-10-20 12:34:04.818 ActionNote3[13487:15803] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil'
*** First throw call stack:
(0x1eaf052 0x2a5fd0a 0x1e9c36e 0x1e9d220 0x1967cb6 0x50b4b 0x50421 0x4fe89 0x4d757 0x6641 0x1eb0ec9 0xd085c2 0xd0855a 0xdadb76 0xdae03f 0xdad2fe 0xd2da30 0xd2dc56 0xd14384 0xd07aa9 0x20c6fa9 0x1e831c5 0x1de8022 0x1de690a 0x1de5db4 0x1de5ccb 0x20c5879 0x20c593e 0xd05a9b 0x212d 0x20a5)
terminate called throwing an exception
Так что, если я комментирую, что линейный выход, выполнение Procedes, пока он не достигнет этой группы линий, где она терпит неудачу, когда его попытки выполнить функцию performFetch.
NSError *error = nil;
if (![[self currentFetchedResultsController] performFetch:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
отладки в код [само currentFetchedResultsController] показывает, что контроллер извлекаются результаты создается правильно и без проблем.
Ошибка, полученная здесь, такая же, как указано выше. Цифры в первом стеке вызова бросаются, но в противном случае ошибка будет одинаковой.
Так что я остался думать, что у меня больше проблема. Я просто понятия не имею, как его отслеживать. Как я уже говорил, где-то там, у меня есть другой взгляд, построенный таким же образом, который загружается нормально.
Edit:
Так NJones в своем ответе ниже предложил следующие руководящие принципы Apple, путем размещения соответствующего кода в loadView и viewDidLoad. Так я и сделал. Я переместил все конструкцию вида из init и в loadView, и запустил fetchedResultsController в viewDidLoad.
приложение по-прежнему падает в том же месте:
self.tableView.tableHeaderView = searchBar
с той же ошибкой, как указано выше.
Спасибо!
Прежде всего, я обожаю любой вопрос, который начинается с «Так что я думаю, что схожу с ума». Попробуйте поместить эту строку кода до строки «CGRect roo ...»: NSLog (@ "правильно установлен?% @", ([Self.view isMemberOfClass: [UIView class]]) @ @ YES: @ "НЕТ"); Извините, это не ответ, и я не могу отформатировать код в комментарии. – NJones
Причиной аварии является, по-видимому, следующее: «[__NSArrayM insertObject: atIndex:]: объект не может быть nil», но вы не дали нам никакого кода, который использует insertObject: atIndex :, поэтому мы не можем видеть, что такое объект nil. Кстати, если вы не используете какие-либо файлы NIB и не вызываете супер initWithNibName :, зачем использовать initWithNibName, а не только init? – Aberrant
@Aberrant, у меня нет кода, который делает это. Если бы я сделал, я бы согласился с вашей оценкой.Возможно, внутренний код, созданный яблоком, который я не вижу, но это не кодовый код, который я использовал для использования ножей, но избавился от них. Вы заметите, что когда я вызываю [super init], я просто вызываю init. – Chris