iOS изменить Integer/NSNumber родительского ViewController

У меня есть viewController со свойством NSInteger (или NSNumber). Я хочу передать целое число дочернему ViewController, внести некоторые изменения (возможно, добавить на какое-то число).

Но когда я использую NSNumber как свойство в родительском и дочернем контроллере и передаю его по заданному свойству:

//parent and child property.    
@property (nonatomic,strong) NSNumber *num;

//pass to the child
child.num = self.num;

//do some change in child
self.num = [NSNumber numberWithInteger:[self.num integerValue] + 1];

Это не может изменить значение родителя, т.к. NSNumber доступен только для чтения и в дочернем выделяют новый, без изменения значения родителя.

So:

Как я могу передать NSInteger или NSNumber дочернему ViewController и изменить в нем значение, а когда дочерний элемент исчезнет, ​​родительский контроллер получит изменение?


person FisherMartyn    schedule 14.12.2015    source источник
comment
Для этого вы используете шаблон делегата.   -  person trojanfoe    schedule 14.12.2015
comment
можете ли вы показать мне какой-нибудь код шаблона делегата для этого?   -  person FisherMartyn    schedule 14.12.2015


Ответы (2)


Вы определяете и назначаете новый NSNumber в следующей строке:

self.num = [NSNumber numberWithInteger:[self.num integerValue] + 1];

Вы не можете использовать этот метод, потому что NSNumbers неизменяемы. Таким образом, self.num будет указывать на другое местоположение, отличное от родительского num. Чтобы избежать подобных проблем, вы можете использовать шаблон делегата или просто передать родительский указатель viewController дочернему элементу и изменить его значение num.

Например:

Родительский заголовок:

@property (nonatomic,strong) NSNumber *num;

Заголовок ребенка:

@property (nonatomic,weak) parentViewControllerClass * parentClass;

Код:

self.parentClass.num = [NSNumber numberWithInteger:[self.parentClass.num integerValue] + 1];

P.S. Вы можете узнать, как определить протоколы здесь и здесь . С этим вы можете реализовать шаблон делегата.

person Amir    schedule 14.12.2015
comment
Это ужасно. Более нормально иметь метод делегата, такой как setSomeNumber:(NSUInteger)number;, а не создавать свойства извне, подобные этому. - person trojanfoe; 14.12.2015
comment
@trojanfoe полностью согласен, но я заявил, что он может использовать шаблон делегата, прежде чем выражать этот пример. Я добавлю немного кода, чтобы показать, как использовать делегат. - person Amir; 14.12.2015
comment
Ничего ужасного в этом не вижу. Это даже не делегат; это просто простая манипуляция со свойствами, которую ребенок делает с родителем. - person NRitH; 14.12.2015
comment
@NRitH Итак, выделение свойств извне не ужасно? - person trojanfoe; 14.12.2015
comment
@trojanfoe, вы можете просто использовать int, чтобы не выделять свойство. - person Amir; 14.12.2015
comment
Верно; но вы должны предоставить протокол, разрешающий повторное использование и отделение от родителя. Затем родитель становится делегатом дочернего элемента. - person trojanfoe; 14.12.2015
comment
Это не имеет абсолютно никакого смысла для чего-то столь же простого, как свойство Int. Делегаты предназначены для более сложного поведения, что обычно означает методы. Тем не менее, не все методы должны быть в делегате; безусловно, можно нормально вызывать методы. - person NRitH; 14.12.2015

Возможно, в другом языке вы могли передавать указатель за указателем (я не уверен, что вы должны), но в Objective-C вы не можете запросить адрес свойства.

Что вы можете сделать, так это:

  1. Use mentioned delegate pattern - what it means:
    1. Create protocol that specifies method like setNumber:
    2. Реализуйте этот протокол в своем родительском контроллере (просто реализуйте функцию setNumber:)
    3. Установите родительский контроллер как свойство дочернего, но как экземпляр этого протокола, а не экземпляр его класса, чтобы сохранить инкапсуляцию.
    4. Вызов setNumber: из дочернего контроллера
  2. Создайте объект mutable, который используется родительским и дочерним контроллерами. Например:

    @interface Counter : NSObject
    @property (nonatomic) NSInteger value;
    @end
    
  3. Вы можете опубликовать уведомление об изменении номера с дочернего контроллера и наблюдать за ним в родительском:

    // post notification in child
    NSNumber *num = [NSNumber numberWithInteger:1];
    [[NSNotificationCenter defaultCenter] postNotificationName:@"numberChangedNotification" 
        object:self 
        userInfo:@{@"number": num}];
    // observe notifications in parent
    // first register observer in viewDidLoad
    [[NSNotificationCenter defaultCenter] addObserver:self 
         selector:@selector(changeNumber:) 
         name:@"numberChangedNotification" 
         object:child];
    // and implement updateNumber
    - changeNumber: (NSNotification *)notification {
        NSNumber *num = notification.userInfo[@"number"];
        // ...
    }
    
person Piotrek Wilczyński    schedule 14.12.2015