0

Что я пытался сделать, так это реализовать шаблон наблюдения за ключом.может объяснить это поведение «dispatch_async» в этом примере ..?

У меня есть MasterViewController, DetailViewController и случайный класс под названием Animal, который имеет только одно свойство, называемое "имя". (Кстати, этот проект был построен из Master-View шаблона контроллера)

// Animal.h 
#import <Foundation/Foundation.h> 

@interface Animal : NSObject 
@property NSString *name; 
@end 

В detailViewController есть только один ярлык, отображающий свойство name из класса животных с помощью segue. И, также, у меня есть Observer, добавленный к животному Obj.

//detailViewController.h 
#import <UIKit/UIKit.h> 

@interface DetailViewController : UIViewController 

@property (strong, nonatomic) id detailItem; 
@property (weak, nonatomic) IBOutlet UILabel *detailDescriptionLabel; 

@end 


//implementation 
@implementation DetailViewController 

- (void)setDetailItem:(id)newDetailItem 
{ 
    if (_detailItem != newDetailItem) { 
     _detailItem = newDetailItem; 

     [newDetailItem addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:nil]; 

     // Update the view. 
     [self configureView]; 

    } 
} 

-(void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 
{ 
    [self configureView]; 
} 

- (void)configureView 
{ 
    // Update the user interface for the detail item. 
    if (self.detailItem) { 
     self.detailDescriptionLabel.text = [self.detailItem name]; 
    } 
} 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
// Do any additional setup after loading the view, typically from a nib. 
    [self configureView]; 
} 

В MasterViewController, который является tableViewController всякий раз, когда нажатие кнопки бар «+», это установит детали ячейки с именем из класса Animal. И, в это время в этом методе (insertNewObject :) я имитирую загрузку чего-то, просто положив его спать (5); И тогда он назначит случайное число для свойства name от животного. Когда вы меняете свойство name, так как я уже добавляю Observer в Animal, он собирается уведомить меня и «Обновить» мою метку !. Итак, Синаррио будет так, что как только вы нажмете кнопку «+», вы щелкните ячейку, которая только что вставлена, и дождитесь изменения оригинальной метки.

- (void)insertNewObject:(id)sender 
{ 
    if (!_objects) { 
     _objects = [[NSMutableArray alloc] init]; 
    } 

    Animal *animal = [[Animal alloc]init]; 
    animal.name = [NSString stringWithFormat:@"animal number %d", _objects.count+1 ]; 
    [_objects insertObject: animal atIndex:0]; 

    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0]; 
    [self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; 

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 

     sleep(5);// simulating downloading. 

     NSLog(@"3"); 
     NSLog(@"4"); 
     // assign random number. 
     animal.name = [NSString stringWithFormat:@"animal number %d", rand()]; 

     dispatch_async(dispatch_get_main_queue(), ^{ 
      NSLog(@"7"); 
      [self.tableView reloadData]; // **it got called after excuting NSLog(@"8") why..?** 
      NSLog(@"8"); 
     }); 
     NSLog(@"5"); 
     NSLog(@"6"); 
    }); 

    NSLog(@"2"); 
} 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath]; 
    NSLog(@"1"); 
    Animal *animal = _objects[indexPath.row]; 
    cell.textLabel.text = [animal name]; 

    return cell; 
} 

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
{ 
    if ([[segue identifier] isEqualToString:@"showDetail"]) { 
     NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow]; 
     Animal *animal = _objects[indexPath.row]; 
     [[segue destinationViewController] setDetailItem:animal]; 
    } 
} 

Итак, вот что у меня есть проводное поведение. Что касается других потоков отправки, я напечатал номер, но некоторое время он имеет другой порядок. Но я не могу понять, когда я получил этот заказ: Я думал, что внутри одного исполнения нити, его не следует перепрыгивать, особенно 7 8 1 часть заказа.

И еще вопрос в том, что после 3 и 4, так как он меняет свойство имени, мой метод настройки вызывается сразу. BUT он ничего не обновлял и не обновлял до тех пор, пока на самом деле не на некоторое время 5 6 7 8 напечатано

Наконец, После нажатия кнопки «+» и вернуться назад и вперед от подробно освоить вид Тогда вы получили эту ошибку и ВГА y ..? enter image description here

PS: когда KVO называет Мой метод настройки после того, как имя свойства изменилось, когда я отладки, свойство имя было изменено, но он не обновлялся ..

+2

Включите зомби в свою схему и посмотрите, есть ли у вас более полезное сообщение об ошибке. Я подозреваю, что «животное» вышло за рамки. –

ответ

0

Прежде всего для вашего первого вопроса вас необходимо понять, как работает диспетчер.

Использование функции dispatch_async в global_queue (т.е. одновременно) порядок нити Казнь в может меняться каждый раз, когда. Не является постоянным. Чтобы лучше понять, прочитать мою статью, написанную здесь, на StackOverflow:

How does the dispatcher work when mixing sync/async with serial/concurrent queue?

Другое дело, что ваш проповедуют @property NSString *name в atomic.Фактически, когда вы ничего не пишете, значение atomic является значением по умолчанию. Я не знаю, если вы сделали это добровольно, но в любом случае, я бы написать:

@property (copy, nonatomic) NSString *name; 

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

+0

Прежде всего, я не могу сказать, насколько я ценю, что вы читаете мой пост сэр. Я перешел на неатомический и снова запустил попытку взад и вперед, но потом я получил то же сообщение об ошибке. Кстати, почему я выбираю неатомическую ситуацию, когда задействовано более одного потока ..? Я думал, что сделаю это синхронизированным .. –

+0

Да, правильно, но вы должны использовать копию;) Дайте мне несколько минут, чтобы прочитать ваш код. –

+0

Без вашего кода в моих руках нелегко найти проблему. Первое, что вы понимаете, как dispatch_async и sync работают. Тогда, вы можете видеть, когда краш, какова ценность имени? кажется освобожденным .. –

0

Похоже, что animal.name неизменно. Множество назначений болит.

Смежные вопросы