![]() |
|
![]() ![]() ![]() |
|
cosamia |
|
|||
Бывалый ![]() Профиль Группа: Участник Сообщений: 231 Регистрация: 11.5.2005 Репутация: нет Всего: нет |
Попытка получить список из БД оканчивается неудачно
У вьюконтроллера в методе viewDidLoad пишу: self.clients = [self.service getClients]; NSLog сколько клиентов получили Вот код Service: -(NSMutableArray*)getClients { NSMutableArray *array = [[NSMutableArray alloc] init]; if(![[NSFileManager defaultManager] fileExistsAtPath:[self.database.fileURL path]]) { return array; } else if (self.database.documentState ==UIDocumentStateClosed) { [self.database openWithCompletionHandler:^(BOOL success){ __block array = [self fetchDatabaseToGetData:self.database]; }]; return array; } else if (self.database.documentState ==UIDocumentStateNormal) { return [self fetchDatabaseToGetData:self.database]; } } -(NSMutableArray*)fetchDatabaseToGetData:(UIManagedDocument *)document { ... } Если бы этот код я написал под windows то под виндой он бы работал так: 1) как только выполняем операцию присвоения, идем в getClientsList 2) вызываем fetchDatabaseToGetData которая возвращает данные в getClientsList которые возвращают данные в self.clients Почему-то под эпл это работает по-другому, а именно: 1) первая строка дебагером вроде как пропускается потому что внутрь указанных методов я не попадаю но получаю NSLog сколько клиентов получили - а это уже строка 2 2) после этой чудесной логики я каким то чудом почему-то все-таки оказываюсь в getClientsList которая вызывает fetchDatabaseToGetData И возвращает правильный набор данных …но куда? self.clients уже содержат 0 клиентов потому как строка прошла, уже в прошлом Может быть знающие люди подскажут как работает логика эпл? Добавлено через 8 минут и 44 секунды Уточню логику эпл: После строки self.clients = [self.service getClients]; идет в getClients на линию [self.database openWithCompletionHandler:^(BOOL success){ __block array = [self fetchDatabaseToGetData:self.database]; }]; return array; Однако в fetchDatabaseToGetData:self.database не заходит и после чего возвращается в ViewController и пишет NSLog что 0 клиентов доходт до конца метода viewDidLoad после чего снова оказывается в getClients на линии [self.database openWithCompletionHandler:^(BOOL success){ __block array = [self fetchDatabaseToGetData:self.database]; }]; return array; после этого попадает в fetchDatabaseToGetData:self.database клиенты закидываются в локальный массив после чего завершает ViewController В результате ViewController содержит 0 полученных клиентов Это сообщение отредактировал(а) cosamia - 3.12.2012, 02:19 |
|||
|
||||
Bitter |
|
|||
![]() Опытный лентяй ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1209 Регистрация: 15.8.2004 Где: Харьков, Ukraine Репутация: 10 Всего: 27 |
это потому, что CompletionHandler выполняется в асинхронном режиме, то есть в параллельном потоке. А это значит, что после вызова openWithCompletionHandler метод завершается (судя по вашему коду) и возвращает массив на текущий момент. CompletionHandler выполнится тогда, когда до него дойдет очередь
|
|||
|
||||
cosamia |
|
|||
Бывалый ![]() Профиль Группа: Участник Сообщений: 231 Регистрация: 11.5.2005 Репутация: нет Всего: нет |
Это я уже догадался. Но как с этим работать тогда?
|
|||
|
||||
Bitter |
|
|||
![]() Опытный лентяй ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1209 Регистрация: 15.8.2004 Где: Харьков, Ukraine Репутация: 10 Всего: 27 |
||||
|
||||
cosamia |
|
|||
Бывалый ![]() Профиль Группа: Участник Сообщений: 231 Регистрация: 11.5.2005 Репутация: нет Всего: нет |
||||
|
||||
Bitter |
|
|||
![]() Опытный лентяй ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1209 Регистрация: 15.8.2004 Где: Харьков, Ukraine Репутация: 10 Всего: 27 |
Что тут сложного? Передавайте в ваш метод блок и выполняйте его в CompletionHandler
|
|||
|
||||
cosamia |
|
|||
Бывалый ![]() Профиль Группа: Участник Сообщений: 231 Регистрация: 11.5.2005 Репутация: нет Всего: нет |
Подробнее можно что и куда передавать? У меня есть Service класс который содержит метод -(NSMutableArray*)getClients; который в свою очередь вызывает другой метод этого же класса -(NSMutableArray*)fetchDatabaseToGetData:(UIManagedDocument *)document Таким образом класс Service представлен в виде DAL Теперь в контроллере мне надо вызвать этот метод что я и делаю путем self.array = [self getClient]; |
|||
|
||||
Bitter |
|
|||
![]() Опытный лентяй ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1209 Регистрация: 15.8.2004 Где: Харьков, Ukraine Репутация: 10 Всего: 27 |
Если ваш метод возвращает результаты в асинхронном режиме, то и обрабатывать их нужно в асинхронном режиме. Лучше всего для этого подходят блоки (читать про блоки тут). В блоке описываете обработку массива и передаете его (блок) в свой метод getClient.
|
|||
|
||||
cosamia |
|
|||
Бывалый ![]() Профиль Группа: Участник Сообщений: 231 Регистрация: 11.5.2005 Репутация: нет Всего: нет |
У меня нет обработки массива, я вывожу весь массив в таблицу в стандартном - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath А перед тем как его вывести просто вызываю self.service getClientsList где self.serivice - инстэнс класса Service Каким образом - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath или viewDidLoad предлагается и зачем передавать в Service.getClient?? |
|||
|
||||
Bitter |
|
|||
![]() Опытный лентяй ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1209 Регистрация: 15.8.2004 Где: Харьков, Ukraine Репутация: 10 Всего: 27 |
я говорю что в метод ваш вы должны передать блок. А в блоке написать то, что вам нужно. Например [myTable reloadData];
Вы можете написать например так (добавив в ваш метод блок в качестве параметра): [self.service getClientsWithCompletionHandler:^(id result) { self.clients = result; [myTable reloadData]; }]; блок вызываете в методе getClientsWithCompletionHandler там, где нужно (например вместо return array) |
|||
|
||||
cosamia |
|
|||
Бывалый ![]() Профиль Группа: Участник Сообщений: 231 Регистрация: 11.5.2005 Репутация: нет Всего: нет |
Я пытался сделать так(до прочтения этого ответа):
[self.service ^(id result) { self.clients = result; [myTable reloadData]; }]; В результате ничего не сработало. Не знаю это идентично предложенному или нет.. В результате проблема была решена через делегаты |
|||
|
||||
Bitter |
|
|||
![]() Опытный лентяй ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1209 Регистрация: 15.8.2004 Где: Харьков, Ukraine Репутация: 10 Всего: 27 |
кусок кода, который вы написали - полная ерунда. Учите блоки
|
|||
|
||||
cosamia |
|
|||
Бывалый ![]() Профиль Группа: Участник Сообщений: 231 Регистрация: 11.5.2005 Репутация: нет Всего: нет |
Я точно не помню что было написано, возможно что было написано так: self.clients= ^(something){[self.service getClients]}]; Помню что компилировалось но вылетало в рантайме |
|||
|
||||
Bitter |
|
||||
![]() Опытный лентяй ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1209 Регистрация: 15.8.2004 Где: Харьков, Ukraine Репутация: 10 Всего: 27 |
ну в любом случае, вы написали что-то вроде: присвоить блок переменной self.clients. но поскольку переменная не типа "блок", то краш.
Ну смотрите, можно было сделать так: 1. первым делом объявить тип вашего блока: typedef void (^MyCompletionHandler)(NSArray* result); 2. Метод getClient дополнить входящим параметром - блоком:
3. вызвать getClients передав в него блок:
|
||||
|
|||||
bales |
|
|||
Новичок Профиль Группа: Участник Сообщений: 6 Регистрация: 19.12.2012 Репутация: нет Всего: нет |
Ah I forgot, you can sign up for the newsletter here: http://mupromo.com The emails you'll get will be exactly what AppChest's hot deals feature does. Maybe that helps!
|
|||
|
||||
![]() ![]() ![]() |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | iOS | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |