iOS change Integer/NSNumber of parent ViewController

435 Views Asked by At

I have a viewController with a property of NSInteger (or NSNumber), What I want to do is pass the integer to the child ViewController, do some change (maybe add by some number).

But when I use NSNumber as property in the parent and child controller and pass it by set property:

//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];

This cannot change the value of the parent , because NSNumber is readonly and in the child they alloc a new one, without change the value of the parent.

So:

How I can pass a NSInteger or NSNumber to the child ViewController and change the value in it, and when child is pop away, the parent controller get the change?

2

There are 2 best solutions below

7
Amir On BEST ANSWER

You are defining and assigning a new NSNumber in the following line:

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

You can't use this method because NSNumbers are immutable. So self.num will point to another location different from parent's num. To avoid problems like this you can use delegate pattern or simply passing parent's viewController pointer to the child and changing its num value.

For example:

Parent's Header:

@property (nonatomic,strong) NSNumber *num;

Child's Header:

@property (nonatomic,weak) parentViewControllerClass * parentClass;

Code:

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

P.S. You can check out how to define protocols here and here. With that you can implement the delegate pattern.

0
Piotrek Wilczyński On

Maybe in other language you could pass pointer to pointer (I'm not sure if you should), but in Objective-C you can't request address of property.

What you can do is:

  1. Use mentioned delegate pattern - what it means:
    1. Create protocol that specifies method like setNumber:
    2. Implement this protocol in your parent controller (just implement setNumber: function)
    3. Set parent controller as property of child, but as instance of this protocol, not instance of it's class - to keep encapsulation.
    4. Call setNumber: from child controller
  2. Create mutable object that is shared between parent and child controller. For example:

    @interface Counter : NSObject
    @property (nonatomic) NSInteger value;
    @end
    
  3. You could post notification about number change from child controller and observe it in parent:

    // 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"];
        // ...
    }