#ios #multithreading
#iOS #многопоточность
Вопрос:
Я попытаюсь объяснить это, не показывая никакого кода, потому что я не думаю, что мне это нужно…
У меня есть созданный мной объект, который содержит данные и несколько методов доступа к данным с веб-сервера, и в этом случае он затем заполняет указанные данные для последующего извлечения.
В основном потоке, когда представление инициализируется, я инициализирую этот объект URL-адресом, необходимым для доступа к данным. Это все, что он делает при инициализации… Затем, как только представление загружается, я вызываю один из методов объекта, который затем получает данные с веб-сервера. Это может занять несколько секунд или дольше, углубляясь в то, какие данные извлекаются. После этого я могу вызывать другие методы для получения различных типов данных, которые мне нужны.
Моя проблема в том, что я не могу найти лучший способ перенести это в другой поток. Выполнение простого performSelectorInBackground, похоже, не работает, потому что объект, который я инициализировал при инициализации представления, недоступен. Второй поток не может видеть это по какой-либо причине. Теоретически я могу инициализировать объект и запустить методы, которые мне нужны для запуска во втором потоке. Затем передайте объект обратно в основной поток… Я рассматриваю возможность выполнения performSelectorOnMainThread и передачи объекта обратно таким образом. Это сработает?
В идеале было бы неплохо иметь что-то, что позволит мне:
- Запустите некоторый код в другом потоке…
- Дождитесь завершения указанного кода…
- Продолжайте с остальной частью программы.
К сожалению, не похоже, что это так просто. Буду признателен за любую помощь, которая укажет мне правильное направление. Или, по крайней мере, подтвердите, что моей теории о передаче объекта обратно будет достаточно.
РЕДАКТИРОВАТЬ: Как я могу прочитать и изменить переменную экземпляра, которую я определил в своем заголовочном файле для моего контроллера представления? Когда я ставлю точку останова в методе, который выполняется во втором потоке, это похоже на то, что переменная не была инициализирована.
EDITx2:
- (id)initWithText:(NSString *)strURL{
if (self) {
// Custom initialization
osSearch = [[orgSearch alloc] initWithurl:strURL];
}
return self;
}
- (void)viewDidLoad{
[self loadSearches];
[super viewDidLoad];
}
- (void)loadSearches{
[self performSelectorInBackground:@selector(workerThread) withObject:nil];
}
-(void) workerThread{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[osSearch go];
[self performSelectorOnMainThread:@selector(returnToMain) withObject:nil waitUntilDone:FALSE];
[pool release];
}
-(void)returnToMain{
UITableView* tblView = tableView;
tblView.frame = CGRectMake(0,28,320,387);
[tblView release];
}
Поиск — это объект, к которому я пытаюсь получить доступ, но похоже, что все мои ивары освобождаются. если я поставлю точку в performSelectorInBackground, я увижу, что поиск был инициализирован правильно. Как только я вхожу в WorkerThread, это похоже на то, чего никогда не было. Я могу прокомментировать вызов «go» и просто вернуться к основному потоку, и он все равно будет выглядеть так, как будто он никогда не был инициализирован.
Просто в качестве теста я создал новый проект, используя тот же метод и объект threading, я смог создать новый поток и получить доступ к ivars представления и ivars объектов просто отлично. Я не понимаю, что здесь происходит. Я только предполагаю, что сборщик мусора мне не нравится, но это только предположение. Опять же, любая помощь была бы отличной.
Комментарии:
1. Когда вы просто сидите и ждете завершения потока, зачем вообще запускать его в потоке?
2. Поскольку я не единственный, кто собирается использовать это, и если кажется, что он зависает из-за отсутствия индикатора загрузки, пользователь предположит, что что-то не работает.
Ответ №1:
1) В iOS нет сборки мусора. Поведение управления памятью всегда будет согласованным, вплоть до недетерминированного поведения вашего собственного кода (например, условия гонки).
Если один и тот же код работает в новом проекте, то либо это не совсем тот же код, либо он работает случайно (доступ к освобожденному объекту может работать время от времени, хотя это просто сбой, ожидающий своего появления), либо в вашем коде есть некоторые недетерминированные условия, которые освобождают объект.
2) Для этого:
Запустите некоторый код в другом потоке…
Дождитесь завершения указанного кода…
Продолжайте с остальной частью программы.
Вы можете использовать одно из следующих:
-
Семейство методов performSelector …, точно так же, как вы их использовали.
-
семейство функций dispatch_async — посмотрите, и вы найдете много примеров.
-
Используйте NSInvocationOperation / NSBlockOperation с блоком завершения, который передает управление обратно основному потоку.
-
Специально для HTTP-запросов вы можете использовать ASIHTTPRequest (также использует внутреннюю NSOperation, но предоставляет множество дополнительных функций и обратных вызовов для выполнения запроса).
Комментарии:
1. Ну, что-то здесь не работает… По-видимому, это не связано с потоковой обработкой, потому что кажется, что мои ивары освобождаются после загрузки представления. Мне нужно будет изучить это дальше. Я собираюсь полностью переписать это представление и перепроверить все. Спасибо за вашу помощь.