1

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?

FisherMartyn
  • 826
  • 1
  • 8
  • 17

2 Answers2

3

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.

Amir
  • 820
  • 9
  • 30
  • That's horrible. More normal is to have a delegate method like `setSomeNumber:(NSUInteger)number;` rather than creating properties externally like that. – trojanfoe Dec 14 '15 at 15:49
  • @trojanfoe completely agree but I've stated that he can uses delegate pattern before expressing this example. I'll add some code to show how to use delegate. – Amir Dec 14 '15 at 15:50
  • I don't see anything horrible about this. It's not even a delegate; it's just a simple property manipulation that the child makes on the parent. – NRitH Dec 14 '15 at 16:56
  • @NRitH So allocating properties externally is not horrible? – trojanfoe Dec 14 '15 at 17:22
  • @trojanfoe you can simply use int so not to allocate a property. – Amir Dec 14 '15 at 17:23
  • Indeed; but you should provide a protocol to allow reuse and separation from the parent. The parent then becomes the delegate of the child. – trojanfoe Dec 14 '15 at 17:24
  • That makes absolutely no sense for something as simple as an Int property. Delegates are for more complex behavior, which usually means methods. Even so, not all methods need to be in a delegate; it's certainly legit to call methods normally. – NRitH Dec 14 '15 at 17:36
0

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