Change Object in the other view


#1

I dont know, if my question is answered in one of the next chapters. Is it posible to change an object in a view with an action in the other? Example: If there would be a button in HypnosisViewController, how can I change the title of the button in timeViewController.

Sorry for my terrible english & thanks a lot.

Claus


#2

Yes, that’s possible, and there are a couple of ways to do it.

My most favourite one uses notifications because the objects involved don’t have to know about each other, which is good.

One object posts a notification that says, for instance, do something or something has changed. Another object, if interested, can receive notifications and act accordingly. If objects need to exchange data, they can do it by piggy-backing the data on the notification message or by posting it to a global bulletin board.

Here is a simple but complete example (to control a heating unit):

MyNotifications.h

// MyNotifications.h

#ifndef MyNotifications_h
#define MyNotifications_h

extern NSString *kMyNotificationHeating;
extern NSString *kMyNotificationHeatingTurnOn;
extern NSString *kMyNotificationHeatingTurnOff;

#endif

MyNotifications.m

// MyNotifications.m

NSString *kMyNotificationHeating        = @"kMyNotificationHeating";
NSString *kMyNotificationHeatingTurnOn  = @"kMyNotificationHeatingTurnOn";
NSString *kMyNotificationHeatingTurnOff = @"kMyNotificationHeatingTurnOff";

Bar.h

//  Bar.h

#import <Foundation/Foundation.h>

@interface Bar : NSObject

- (void)changeHeating;

@end

Bar.m

//  Bar.m

#import "Bar.h"
#import "Notification.h"

@implementation Bar

- (void)changeHeating
{
    static BOOL on;
    
    if (! on)
    {
        [[NSNotificationCenter defaultCenter] postNotificationName:kMyNotificationHeating object:kMyNotificationHeatingTurnOn];
    }
    else {
        [[NSNotificationCenter defaultCenter] postNotificationName:kMyNotificationHeating object:kMyNotificationHeatingTurnOff];    
    }
    
    // toggle
    on = !on;
}
@end

Foo.h

//  Foo.h

#import <Foundation/Foundation.h>

@interface Foo : NSObject

@end
//  Foo.m

#import "Foo.h"
#import "Notification.h"

#define MY_Log() NSLog (@"%s", __PRETTY_FUNCTION__)

@implementation Foo

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    [super dealloc];
}

- (id)init
{
    if (self = [super init])
    {
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector (heatingNotification:) name:kMyNotificationHeating object:nil];
    }
    return self;
}

- (void)heatingNotification:(NSNotification *)notification
{
    MY_Log ();
    NSString *name = [notification object];
    [self performSelectorOnMainThread:@selector (changeHeatingState:) withObject:name waitUntilDone:NO];
}

- (void)changeHeatingState:(NSString *)name
{
    if (name == kMyNotificationHeatingTurnOn)
    {
        [self turnOnHeating];
    }
    else if (name == kMyNotificationHeatingTurnOff)
    {
        [self turnOffHeating];        
    }
}

- (void)turnOnHeating
{
    MY_Log ();
    // Change the UI
}

- (void)turnOffHeating
{
    MY_Log (); 
    // Change the UI
}

@end

ViewController.h

//  ViewController.h

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController

- (IBAction)actionChangeHeating:(id)sender;

@end

ViewController.m

//  ViewController.m

#import "ViewController.h"
#import "Bar.h"
#import "Foo.h"

@interface ViewController ()

@property (strong) Bar *bar;
@property (strong) Foo *foo;

@end

@implementation ViewController

@synthesize bar;
@synthesize foo;
 // We could put Foo in another view controller
 // But to keep the example simple, we put it here

- (void)dealloc
{
    self.bar = nil;
    self.foo = nil;
    [super dealloc];
}

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

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return YES;
}

- (IBAction)actionChangeHeating:(id)sender
{
    if (!bar)
    {
        self.bar = [[Bar alloc] init];
    }
    
    if (!foo)
    {
        self.foo = [[Foo alloc] init];
    }
    
    [bar changeHeating];
}

@end

If you are familiar with notifications, you will notice that I have used it in a slightly unorthodox way in that I used the object argument to pass more specific information (whether heating should be on or off.)


#3

Thank you for your fast respond.