Как UISearchDisplayController может автовыпустить катастрофический отказ причины в контроллере другого представления?

У меня есть два контроллера A представления и B. От A я перешел для просмотра контроллера B следующим образом:

// in View Controller A 
// navigateToB method

-(void) navigateToB {

BViewController *bViewController = 
[[BViewController alloc] initWithNibName: @"BView" bundle:nil];

bViewController.bProperty1 = SOME_STRING_CONSTANT;
bViewController.title = @"A TITLE OF A VC's CHOOSING"; 
[self.navigationController pushViewController: bViewController animated:YES];
[bViewController release]; //<----- releasing 0x406c1e0

}

В BViewController свойство bPropery1 определяется с копией как ниже (примечание, B также содержит UITableView и другие свойства):

@property (nonatomic, copy) NSString *bProperty1;

Все, казалось, хорошо работало при навигации назад и вперед между A и B. Это - пока я не добавил UISearchDisplayController к табличному представлению, содержавшемуся в BViewController. Теперь, когда я перешел из B, назад к A, сбоям приложения.

Отслеживание стека показывает то, что смотрит поисковый контроллер отображения, автовыпускаемый во время катастрофического отказа:

#0 0x009663a7 in ___forwarding___
#1 0x009426c2 in __forwarding_prep_0___
#2 0x018c8539 in -[UISearchDisplayController _destroyManagedTableView]
#3 0x018c8ea4 in -[UISearchDisplayController dealloc]
#4 0x00285ce5 in NSPopAutoreleasePool

Шоу NSZombies:

-[BViewController respondsToSelector:]: message sent to deallocated instance 0x406c1e0

И история malloc на этом указывает на bViewController, уже выпущенный в методе A navigateToB выше:

    Call [2] [arg=132]: thread_a065e720 |start  ... <snip> 
..._sendActionsForEvents:withEvent:] | -[UIControl sendAction:to:forEvent:] | -
[UIApplication sendAction:to:from:forEvent:] | -[**AViewController navigateToB**] | 
+[NSObject alloc] | +[NSObject allocWithZone:] | _internal_class_createInstance | 
_internal_class_createInstanceFromZone | calloc | malloc_zone_calloc 

Кто-то может дать мне какие-либо идеи о том, что происходит здесь? В navigateToB методе, когда-то bViewController выпущен (после pushViewController), это, должно быть это для bViewController. Ничто иное даже не знает об этом, поскольку это локально для navigateToB блока метода, и это было выпущено.

При навигации от B назад к A, ничто не вызывается в viewDidLoad, viewWillAppear и т.д., который повторно введет navigateToB.

Похоже так или иначе, что поисковый контроллер отображения имеет ссылку на что-то в моем AViewController и поэтому поскольку это автовыпущено, это берет этому "что-то" вниз с ним, но я не могу понять, как это возможно, тем более, что я использую копию для передачи данных между A и B.

Я иду горшочек по этому. Я уверен, что это - моя ошибка где-нибудь и таким образом, я обращаюсь к Вам, легендам Stack Overflow для любых слов мудрости или совета относительно того, как разрешить это.

Большое спасибо.

11
задан Tofrizer 3 May 2010 в 14:04
поделиться

2 ответа

Когда вы надвигаете контроллер представления на контроллер навигации, контроллер навигации сохраняет контроллер представления. А когда этот контроллер представления разворачивается, контроллер навигации освобождает его.

Похоже, что UISearchDisplayController пытается проверить, реагирует ли ваш контроллер представления на селектор, и поскольку он вызывается из _destroyManagedTableView, я предполагаю, что селектором является searchDisplayController:willUnloadSearchResultsTableView: (ваш контроллер представления является делегатом контроллера отображения поиска, правильно?).

@robert - этот пример, должно быть, неправильный, потому что pushViewController действительно сохраняет свой аргумент. Все остальные примеры на странице либо автоотпускаются сразу после init, либо отпускаются после push.

5
ответ дан 3 December 2019 в 01:29
поделиться

Я решил аналогичную проблему, добавив эти строки в метод dealloc моего UITableViewController, который был делегатом UISearchDisplayController:

self.searchDisplayController.delegate = nil;
self.searchDisplayController.searchResultsDelegate = nil;
self.searchDisplayController.searchResultsDataSource = nil;

Меня немного смутило предложение, что для решения этой проблемы контроллер поискового дисплея должен быть освобожден в dealloc - то, что вам нужно сделать, это удалить указатели, которые контроллер поискового дисплея имеет на ваш контроллер представления таблицы, поскольку ваш контроллер представления таблицы теперь исчезает и не должен вызываться, когда ваш контроллер поискового дисплея позже будет освобожден. Это просто как любая другая ссылка на делегат, которую вы хотите уничтожить в dealloc.

32
ответ дан 3 December 2019 в 01:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: