views:

486

answers:

2

This is a weird issue. I have created a view controller with a nib file for my modal view. On that view there is a label, number and text view. When I create the view from the source view, I tried to set the label, but it shows that the label is null (0x0). Kinda weird... Any suggestions? Now lets look at the code (I put all of the code here because that shows more than I can just explain):

The modal view controller - in IB the label is connected to the UILabel object:

    @implementation ModalViewController

@synthesize delegate;
@synthesize goalLabel, goalText, goalNumber;

// Done button clicked
- (void)dismissView:(id)sender {

    // Call the delegate to dismiss the modal view
    if ([delegate respondsToSelector:@selector(didDismissModalView: newText:)]) {

        NSNumber *tmpNum = goalNumber;
        NSString *tmpString = [[NSString alloc] initWithString:[goalText text]];
        [delegate didDismissModalView:tmpNum newText:tmpString];

        [tmpNum release];
        [tmpString release];
    }
}

- (void)cancelView:(id)sender {

    // Call the delegate to dismiss the modal view
    if ([delegate respondsToSelector:@selector(didCancelModalView)])
        [delegate didCancelModalView];
}

-(void) setLabelText:(NSString *)text {
    [goalLabel setText:text];
}

/*
 // The designated initializer.  Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
        // Custom initialization
    }
    return self;
}
*/

-(void) viewWillAppear:(BOOL)animated {

    [super viewWillAppear:animated];

    // bring up the keyboard....
    [goalText becomeFirstResponder];
}


// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    [super viewDidLoad];

    // set the current goal number to -1 so we know none was set
    goalNumber = [NSNumber numberWithInt: -1];

    // Override the right button to show a Done button
    // which is used to dismiss the modal view
    self.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc]
                                               initWithBarButtonSystemItem:UIBarButtonSystemItemDone
                                               target:self
                                               action:@selector(dismissView:)] autorelease];

    // and now for the cancel button
    self.navigationItem.leftBarButtonItem = [[[UIBarButtonItem alloc]
                                               initWithBarButtonSystemItem:UIBarButtonSystemItemCancel
                                               target:self
                                              action:@selector(cancelView:)] autorelease];

    self.navigationItem.title = @"Add/Update Goals";
}



- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Overriden to allow any orientation.
    return YES;
}


- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Release any cached data, images, etc that aren't in use.
}


- (void)viewDidUnload {
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}


- (void)dealloc {
    [super dealloc];
}


@end

And here is where the view controller is created, variables set, and displayed:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

    // put a checkmark....
    UITableViewCell *tmpCell = [tableView cellForRowAtIndexPath:indexPath];
    [tmpCell setAccessoryType:UITableViewCellAccessoryCheckmark];

    // this is where the popup is gonna popup!
    // ===> HEre We Go!

    // Create the modal view controller
    ModalViewController *mdvc = [[ModalViewController alloc] initWithNibName:@"ModalDetailView" bundle:nil];

    // We are the delegate responsible for dismissing the modal view 
    [mdvc setDelegate:self];

    // Create a Navigation controller
    UINavigationController *navController = [[UINavigationController alloc]
                                             initWithRootViewController:mdvc];

    // set the modal view type
    navController.modalPresentationStyle = UIModalPresentationFormSheet;

    // set the label for all of the goals....
    if (indexPath.section == 0 && indexPath.row == 0) {
        [mdvc setLabelText:[[[NSString alloc] initWithString:@"Long Term Goal 1:"] autorelease]];
        [mdvc setGoalNumber:[NSNumber numberWithInt:1]];
    }

    if (indexPath.section == 0 && indexPath.row == 1) {
        [mdvc setLabelText:[[[NSString alloc] initWithString:@"Long Term Goal 2:"] autorelease]];
        [mdvc setGoalNumber:[NSNumber numberWithInt:2]];
    }

    if (indexPath.section == 0 && indexPath.row == 2) {
        [mdvc setLabelText:[[[NSString alloc] initWithString:@"Long Term Goal 3:"] autorelease]];
        [mdvc setGoalNumber:[NSNumber numberWithInt:3]];
    }

    if (indexPath.section == 0 && indexPath.row == 3) {
        [mdvc setLabelText:[[[NSString alloc] initWithString:@"Long Term Goal 4:"] autorelease]];
        [mdvc setGoalNumber:[NSNumber numberWithInt:4]];
    }


    if (indexPath.section == 1 && indexPath.row == 0) {
        [mdvc setLabelText:[[[NSString alloc] initWithString:@"Short Term Goal 1:"] autorelease]];
        [mdvc setGoalNumber:[NSNumber numberWithInt:5]];
    }

    if (indexPath.section == 1 && indexPath.row == 1) {
        [mdvc setLabelText:[[[NSString alloc] initWithString:@"Short Term Goal 2:"] autorelease]];
        [mdvc setGoalNumber:[NSNumber numberWithInt:6]];
    }

    if (indexPath.section == 1 && indexPath.row == 2) {
        [mdvc setLabelText:[[[NSString alloc] initWithString:@"Short Term Goal 3:"] autorelease]];
        [mdvc setGoalNumber:[NSNumber numberWithInt:7]];
    }

    if (indexPath.section == 1 && indexPath.row == 3) {
        [mdvc setLabelText:[[[NSString alloc] initWithString:@"Short Term Goal 4:"] autorelease]];
        [mdvc setGoalNumber:[NSNumber numberWithInt:8]];
    }

    // show the navigation controller modally
    [self presentModalViewController:navController animated:YES];

    // Clean up resources
    [navController release];
    [mdvc release];

    // ==> Ah... we are done...
}
+1  A: 

The answer was staring me in the face!

Here is what I did:

Added a new function to the delegate

@protocol ModalViewControllerDelegate <NSObject>
@required
    - (void)didDismissModalView:(NSNumber *)goalNbr newText:(NSString *)textToSave;
    - (void)didCancelModalView;
    - (void)willShow:(id)theView;
@end

In the viewWillAppear function, I added the following:

if ([delegate respondsToSelector:@selector(willShow:)])
    [delegate willShow:self];

This allows full access to the modal view that is going to show, so we are able to change the label, text box and variables within the active modal view.

- (void)willShow:(ModalViewController *)theView {

    [theView.goalLabel setText:labelText];
    [theView setGoalNumber:goalNumber];
    [theView.goalText setText:goalText];
}
iPhone Guy
A: 

For completeness' sake, in the event anyone else stumbles on this (it helped me)...

The modal view controller's interface needs to define a variable to hold the delegate:

@protocol ReminderPhotoViewDelegate <NSObject>
@required
- (void)willShow:(id)theView;
@end
@interface ReminderPhotoViewController : UIViewController {
    id<ReminderPhotoViewDelegate> delegate;
    UIImageView *reminderImage;
    UILabel *reminderLabel;
}
@property (assign) id<ReminderPhotoViewDelegate> delegate;
@property (nonatomic, retain) IBOutlet UIImageView *reminderImage;
@property (nonatomic, retain) IBOutlet UILabel *reminderLabel;
@end

Within the implementation of the modal controller, be sure to synthesize those properties:

@implementation ReminderPhotoViewController
@synthesize reminderImage, reminderLabel;
@synthesize delegate;

Whatever your "calling" controller is must declare support for this protocol in its own implementation:

#import "ReminderPhotoViewController.h"
@interface ReminderViewController : UIViewController <ReminderPhotoViewDelegate> {
}

Finally, when you create the instance of your modal controller, you need to set the calling class to be its delegate:

ReminderPhotoViewController *photo = [[ReminderPhotoViewController alloc] init];
[photo setDelegate:self];

That's a more complete set of declarations and code - it's exactly what the answer shows, just with more of the supporting code.

Then, as noted above, your calling controller adds the method from the protocol:

- (void)willShow:(ReminderPhotoViewController *)theView {
    theView.reminderImage.image = selectedImage;
    theView.reminderLabel.text = selectedText;
}
Don Jones