iPad issue with a modal view: modal view label null after view controller is created
This is a weird issue. I have creat开发者_如何学JAVAed 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...
}
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];
}
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;
}
精彩评论