views:

420

answers:

2

I am having difficulty with numbers when programming my iphone app. I want to pass a number (and possibly eventually an array) from one view controller to another. I have managed to do this will strings but I just can't figure it out with numbers. This is what I have..

PrimaryViewController.h

     @interface PrimaryTimerViewController : UIViewController {
        IBOutlet UITextField *name;
        int *number;
}
    -(IBAction)submit;
    @end

PrimaryViewController.m

 -(void)submit{
    SecondaryTimerViewController *Second  = [SecondaryTimerViewController alloc];
    Second.name = name.text;
    Second.number = 5; //causes an error
    [self.view addSubview:Second.view];
}

SecondaryViewController.h

@interface SecondaryTimerViewController : UIViewController {
    IBOutlet UILabel *secondaryLabel;
    NSString *name;
    int *number;
}

@property (nonatomic, retain) NSString *name;
@property (nonatomic) int number;

@end

SecondaryViewController.m

- (void)viewDidLoad {
     secondaryLabel.text = name;
    int num = number; //gives a cast warning
    [super viewDidLoad];
}

If anyone could shed some light on this that would be fantastic. I am new to this and have been googling it for hours :-(

+1  A: 

It is standard practice in Objective-C to have an init method (or overload) that initializes these things, instead of directly setting these facilities upon the object after an alloc call. In fact, UIViewController needs to be initialized before calling many methods on it. Most, if not all, Cocoa classes (and ones you implement!) need to be initialized before they can/should be used.

Are you creating your view (in SecondaryViewController) programatically (in loadView) or in a NIB? In either case, create a new overload in SecondaryViewController.h:

-(id)initWithName:(NSString*)name number:(int)num;

Then in your .m file:

-(id)initWithName:(NSString*)name number:(int)num
{
    if (self = [super init]) // or [super initWithNib:...] if you are using a NIB.
    {
        self.name = name;
        self.number = num;
    }
    return self;
}

Then in PrimaryViewController:

SecondaryTimerViewController *Second = [[SecondaryTimerViewController alloc] initWithName:name.text number:5];
[self.view addSubview:Second.view];

Your other issue is that you have an ivar typed incorrectly in SecondaryViewController.h:

int* number;

Should read:

int number;
Jason
Thanks Jason, that works a treat :-D I have a series of numbers to pass (6 in total) do you think it is better to pass them individually in this way or as an array? If it's an array how do I go about it?
rr299
If they all have separate meanings, they should be declared separately in your initializer. If they are conceptually a group of integers, pass them all at once, like -(id)initWithName:(NSString*)name numbers:(int*)pInts;
Jason
A: 

You can go off of Jason's method, or you can use a singleton. I like using the singleton because I have access to it everywhere and it's memory efficient.

If you want to get started with a singleton you can use the following .h and .m:

#import <Foundation/Foundation.h>

@interface Board : NSObject {
    NSInteger number;
}

@property (nonatomic) NSInteger number;

+ (Board *) instance;

@end

And the implementation:

#import "Board.h"

@implementation Board

@synthesize number;

static Board *sharedBoard = nil;

+ (Board *) instance {
    @synchronized(self) {
     if(sharedBoard == nil)
      sharedBoard = [[self alloc] init];
    }

    return sharedBoard;
}

+ (id)allocWithZone:(NSZone *)zone {
    @synchronized(self) {
     if(sharedBoard == nil) {
      sharedBoard = [super allocWithZone:zone];

      return sharedBoard;
     }
    }

    return nil;
}

- (id) copyWithZone:(NSZone *)zone {
    return self;
}

- (id) retain {
    return self;
}

- (unsigned) retainCount {
    return UINT_MAX;
}

- (void) release {
    [contents release];
}

- (id) autorelease {
    return self;
}

@end

This allows you to include the Board.h into any implementation file and access it by the following:

- (void) viewDidLoad {
    Board *board = [Board instance];
    board.number = 15;
}

Another way is to include it into your header, and set it as a variable so it's available inside all of your methods. What is nice about this approach is you can access this same instance without creating a new one inside your delegate as well.

Garrett
Thanks Garrett, I am pretty new to all this and I'm afraid your method has gone a little over my head :-s I think I need a little more experience before I attempt that. Thanks for the response though.
rr299