Многопоточность iOS, второй поток не может видеть переменные?

#ios #multithreading

#iOS #многопоточность

Вопрос:

Я попытаюсь объяснить это, не показывая никакого кода, потому что я не думаю, что мне это нужно…

У меня есть созданный мной объект, который содержит данные и несколько методов доступа к данным с веб-сервера, и в этом случае он затем заполняет указанные данные для последующего извлечения.

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

Моя проблема в том, что я не могу найти лучший способ перенести это в другой поток. Выполнение простого performSelectorInBackground, похоже, не работает, потому что объект, который я инициализировал при инициализации представления, недоступен. Второй поток не может видеть это по какой-либо причине. Теоретически я могу инициализировать объект и запустить методы, которые мне нужны для запуска во втором потоке. Затем передайте объект обратно в основной поток… Я рассматриваю возможность выполнения performSelectorOnMainThread и передачи объекта обратно таким образом. Это сработает?

В идеале было бы неплохо иметь что-то, что позволит мне:

  1. Запустите некоторый код в другом потоке…
  2. Дождитесь завершения указанного кода…
  3. Продолжайте с остальной частью программы.

К сожалению, не похоже, что это так просто. Буду признателен за любую помощь, которая укажет мне правильное направление. Или, по крайней мере, подтвердите, что моей теории о передаче объекта обратно будет достаточно.

РЕДАКТИРОВАТЬ: Как я могу прочитать и изменить переменную экземпляра, которую я определил в своем заголовочном файле для моего контроллера представления? Когда я ставлю точку останова в методе, который выполняется во втором потоке, это похоже на то, что переменная не была инициализирована.

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) Для этого:

Запустите некоторый код в другом потоке…

Дождитесь завершения указанного кода…

Продолжайте с остальной частью программы.

Вы можете использовать одно из следующих:

  1. Семейство методов performSelector …, точно так же, как вы их использовали.

  2. семейство функций dispatch_async — посмотрите, и вы найдете много примеров.

  3. Используйте NSInvocationOperation / NSBlockOperation с блоком завершения, который передает управление обратно основному потоку.

  4. Специально для HTTP-запросов вы можете использовать ASIHTTPRequest (также использует внутреннюю NSOperation, но предоставляет множество дополнительных функций и обратных вызовов для выполнения запроса).

Комментарии:

1. Ну, что-то здесь не работает… По-видимому, это не связано с потоковой обработкой, потому что кажется, что мои ивары освобождаются после загрузки представления. Мне нужно будет изучить это дальше. Я собираюсь полностью переписать это представление и перепроверить все. Спасибо за вашу помощь.