When to call selectRow: on a UIPickerView that has just loaded? - iphone

I am trying to learn iPhone/iOS programming. I have an UIPickerView that should dispay its selected row as soon as it becomes visible (it is contained on a flippSideView).
Unfortunately, the flipSideViewController's awakeFromNib is not called. It is somewhat too late to do it in viewDidLoad.
So, how can I make the pickerView display the selected row as soon it becomes visible?
Update:
Here is how I show the flipside view
- (IBAction)showInfo:(id)sender {
FlipsideViewController *controller = [[FlipsideViewController alloc] initWithNibName:#"FlipsideView" bundle:nil];
controller.delegate = self;
controller.uData = userData;
controller.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:controller animated:YES];
controller.pickerView.delegate = userData;
controller.pickerView.dataSource = userData;
[controller release];
}// showInfo
In the flipside controller there is a method mySelect (to help me trace trace the calls)
-(void) mySelect:(NSString*) strMethod{
int row = [uData getCurrentUserRow];
[pickerView selectRow:row inComponent:0 animated:NO];
NSLog(#"selectRow %d called from %# (pickerView=%d uData=%d)", row, strMethod, (int)pickerView, (int)uData); }
and when the program runs it generates the log
selectRow 3 called from viewDidLoad (pickerView=87412720 uData=89267696)
selectRow 3 called from viewWillAppear (pickerView=87412720 uData=89267696)
selectRow 3 called from viewDidAppear (pickerView=87412720 uData=89267696)

It seems you're having the problem i had a couple days ago, i really don't think it's a bug I think the problem is when everything is called (could be wrong). Correct me if I'm wrong but you want your PickerView to display a certain value when it's first shown onscreen correct? Are you creating the PickerView in code or from a nib?
In my app, the below code snippet is right at the bottom of my viewDidLoad method
[pickerView selectRow: 100 inComponent:0 animated:YES];
This works as intended. Please post a snippet of your code so we can better understand your problem.
PS: When developing for iOS i would stay away from awakeFromNib and just use ViewDidLoad:

There apparently is a bug in some versions of iOS that means your view is not loaded until you call [super viewWillAppear:animated] or force it to load by calling [self view].

Related

Can I change the ViewController that calls presentViewController?

I have a ViewController, VC1a, that presents VC2:
VC1a -> presentViewController: VC2
Is it possible to change VC1a into VC1b so that when dissmissViewControllerAnimated is called, it animates to VC1b instead of VC1a?
The reason I ask is because I want to return to a different screen without it animating back to VC1a. This relates to portrait/landscape changes.
Warning. This is potentially a bad/confusing UI choice for your users. But if you must...
You may be able to put VC1a inside a UINavigationController and modify the navigation stack while VC2 is in the foreground. Something like:
// in VC1a.m
[self presentViewController:VC2 animated:YES completion:^{
NSMutableArray *navigationStack = [[NSMutableArray alloc] init];
for (UIViewController *viewController in self.navigationController.viewControllers)
{
if (viewController != self.navigationController.viewControllers.lastItem)
{
[navigationStack addObject:viewController];
}
else
{
VC1b *viewControllerToSwapIn = [[VC1b alloc] init];
// probably some more initialization here
[navigationStack addObject:viewControllerToSwapIn];
}
}
self.navigationController.viewControllers = navigationStack;
}];
or possibly a better idea:
// in VC1a.m
[self presentViewController:VC2 animated:YES completion:^{
VC1b *viewControllerToSwapIn = [[VC1b alloc] init];
// probably some more initialization here
[navigationStack addObject:viewControllerToSwapIn];
[self.navigationController popViewControllerAnimated:NO];
[self.navigationController pushViewController:viewControllerToSwapIn animated:NO];
}];
OK, I implemented a Container view controller with two children - one for portrait, one for landscape and this took care of my problem.
I have spent days trying to figure out how to handle rotation correctly within iOS6 and I didn't realise there was a bug in rotating UITableViewController when pushed from a UINavigationController.
Thanks for the response #paulrehkugler - I was getting pretty desperate when I asked this question. There just doesn't seem to be any good examples of how to handle orientation changes while UINav/TableViewControllers are presented from a main view. I certainly wasn't wanting to implement such a hack.

efficient way of making a multiview app?

The app I'm making utilizes multiple views. such as a disclaimer view, a view to display answer so on and so forth.Up until now this is the code that I've been using to switch from one view to another
-(IBAction)swichtogain:(id)sender{
gainview *second = [[gainview alloc]initWithNibName:nil bundle:nil];
[self presentModalViewController:second animated:YES];
[second release];
}
I found this method in a tutorial, I was wondering, is this the best way to do it ? I use the same code to switch back n forth from one view to another for eg.
-(IBAction)swichtoview1:(id)sender{
view1 *view = [[gainview alloc]initWithNibName:nil bundle:nil];
[self presentModalViewController:view animated:YES];
[view release];
}
and when in view1 if the user hits the back button the following code gets executed
-(IBAction)swichtomainview:(id)sender{
mainview *view = [[gainview alloc]initWithNibName:nil bundle:nil];
[self presentModalViewController:view animated:YES];
[view release];
}
I haven't edited anything in the appdelegate files and this is a view based app. Does this method cause it to use more memory ? During the activity monitor test using the instruments , I noticed the memory usage gets higher every time I go from the main menu to another view and back to the main menu !. Is there a better way than this ?. Also one of the view is a calculator so when the user hits the calculate button it switches to the next view while changing the textfield to the answer, below is the code for that !
-(IBAction)calculate{
MyClass *setnum = [[MyClass alloc]init];
setnum.grade_num = grade;
setnum.stage_num = stage;
setnum.ex_lym = ex_ly;
setnum.pos_lym = pos_ly;
setnum.er_num = er;
setnum.noderatio = pos_ly/ex_ly;
if(text1.text.length <=0 ||text2.text.length <=0||text3.text.length<=0||text4.text.length<=0||text5.text.length <=0){
UIActionSheet *action = [[UIActionSheet alloc]initWithTitle:#"Incomplete Values" delegate:self cancelButtonTitle:#"Ok" destructiveButtonTitle:nil otherButtonTitles:nil];
[action showInView:self.view];
[action release];
}else{
answer *ans =[[answer alloc]initWithNibName:nil bundle:nil];
[self presentModalViewController:ans animated:YES];
float i = calc_gain(setnum.grade_num, setnum.noderatio, setnum.stage_num, setnum.er_num);
NSString *result = [NSString stringWithFormat:#"%f",i];
ans.answer1.text = result;
ans.bar.hidden = NO;
[ans release];
}
[setnum release];
}
You should consider using one of the provided container view controllers (UITabBarController, UINavigationBarController or UISplitViewController on the iPad and so on).
The way you use presentModalViewController is most likely the wrong way. For one, calling presentModalViewController will retain your views. Keeping allocating new controllers and displaying their views via presentModalView is therefore increasing your memory footprint with each navigation step.
In general, a viewcontroller which shows another modal viewcontroller is also responsible for dismissing it again. The way to dismiss a modal view controller is therefore to let the presented controller inform its parent through delegation and ask the parent to dismiss (often on tapping a 'done' button).
I'm not even sure whether stacking modalViewControllers is a supported scenario, but at least didn't find anything stated otherwise in the documentation.
Asked here yesterday:
Switching views for iphone application - is this the right way?
I think another good way to go about this is to do this and add a univanigationcontroller:
[self.navigationController pushViewController:second animated:YES];

viewWillAppear not invoked when presenting the viewController modally (iOS)

I have an issue, viewWillAppear method in the UIViewController which is added to the screen by presentModalViewController method does not "go into" viewWillAppear method. Only time this method is invoked is together with the viewDidLoad, the first time.
- (IBAction)openModal:(id)sender {
if (self.nvc == nil) {
ModalViewController *vc = [[ModalViewController alloc] init];
self.nvc = vc;
[vc release];
}
self.nvc.segmentedIndex = [[self.navigationController.viewControllers objectAtIndex:0] index];
[self presentModalViewController:self.nvc animated:YES];
}
The property is of type retain.
Thanks in advance.
right, it works different and it now goes into viewWillAppear only once. So if you want to change the appearance of your view after dismissing a modal view you should do it using a modal delegate pattern. See the link:
http://useyourloaf.com/blog/2010/5/3/ipad-modal-view-controllers.html
Though it's for iPad, but you can get the idea. In the latest iOS versions it works the same.
Hope it helps

EKEventViewDelegate didCompleteWithAction not getting called

I don't get a call to my eventViewController:didCompleteWithAction: when the EKEventViewController finishes edting an event.
Here's how I set it up:
- (void)showCalendar:(id)sender {
EKEventViewController *eventViewController = [[EKEventViewController alloc] init];
eventViewController.delegate = self;
eventViewController.event = self.event;
// Allow event editing.
eventViewController.allowsEditing = YES;
[self.navigationController pushViewController:eventViewController animated:YES];
[eventViewController release];
}
I do have the protocol on my class and the method was implements by copy and pasting the definition from the docs. It just doesn't get called.
If I use the EKEventEditViewController and its corresponding delegate, then that does get called when the event is saved.
I was able to reproduce the problem in the SimpleEKDemo code same as well. Does anyone know what might be wrong?
I could just drop the view functionality and go straight to the EKEventEditViewController, but I'd rather not.
Might be a bit late to be helpful, but I had this problem as well.
To get around it I subclassed EKEventViewController, then in the subclass' viewDidLoad I replaced the standard edit button with one of my own:
- (void)viewDidLoad {
[super viewDidLoad];
UIBarButtonItem *editItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemEdit target:self.delegate action:#selector(editCalEvent)];
self.navigationItem.rightBarButtonItem = editItem;
}
That way when you want to edit an event, you can set up your own EKEventEditViewController and specify its delegate in order to respond to changes:
- (void)editCalEvent {
EKEventEditViewController *editController = [[EKEventEditViewController alloc] init];
editController.event = editingEvent;
editController.eventStore = self.eventStore;
editController.editViewDelegate = self;
[self presentModalViewController:editController animated:YES];
[editController release];
}
Hope that helps.
I had the similar problem when I use "pushViewController", the result is that it will go to
- (void)navigationController:(UINavigationController *)navigationController
willShowViewController:(UIViewController *)viewController animated:(BOOL)animated{}
But after I changed to presentModalViewController, it will go to eventViewController:didCompleteWithAction: when Done/Cancel/Delete are pressed.
in this .m file you need to import the EventKit/EventKit.h and EventKitUI/EventKitUI.h
and in the .h file you need to implement the 'EKEventViewDelegate' delegates.
hope it helps you
This does seem to be a fairly obvious omission in the library. My workaround: I'm presenting the EKEventViewController in a UINavigationController. I detect completion in the viewWillAppear method of the controller than pushed the EKEventViewController onto the view stack. Use a boolean variable in this view controller to track and differentiate between initial appearance and re-appearance due to the EKEventViewController being popped. There is a risk that your code will get called at other times, but if you are just refreshing tableviews, etc, then this should be sufficient.

iPhone - Display smoothly 2 successive modal view controller

I'm searching a way to be able to display one modal view controller after another one, and make the second appear while the first is disapearing.
The problem is that the dismiss call that is done inside the first modalviewcontroller applies to both and SecondController is never shown.
Putting the first dismiss before or after the parent call does not change anything.
If first dismiss is set wih animate= NO, everything works fine. But I need the animation.
I planned to do that this way, but the problem is that the dismiss call that is done inside the first modalviewcontroller applies to both and SecondController is never shown.
I don't understand why because each modal view has its own navigationcontrollers, so they shouldn't collide.
I tried another way by showing the second modal view with a NSTimer after 0.5 sec, but it's not satisfying : the second appears when the first has completely disapeared. Not smooth at all... If I set the delay less than 0.5 sec, the second modal view never shows up. And using such a timer to make this does not seem to be a good way of coding.
Main.m
- (void) entry {
FirstController *nextWindow = [[FirstController alloc] initWithNibName:#"theNIB" bundle:nil];
nextWindow.caller = self;
UINavigationController* navController = [[UINavigationController alloc] initWithRootViewController:nextWindow];
[self.navigationController presentModalViewController:navController animated:YES];
[nextWindow release];
[navController release];
}
- (void) thingsDoneInFirstModalController:(OBJECT)returnValue retval2:(OBJECT2)returnValue2 {
[self display2ndController];
}
- (void) display2ndController {
SecondController *nextWindow;
nextWindow = [[SecondController alloc] initWithNibName:#"NIB2" bundle:nil];
UINavigationController* navController = [[UINavigationController alloc] initWithRootViewController:nextWindow];
[self.navigationController presentModalViewController:navController animated:YES];
[navController release];
[nextWindow release];
}
1st ModalViewController.m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self.navigationController dismissModalViewControllerAnimated:YES];
[self.caller thingsDoneInFirstModalController:theResult retval2:someMoreResult];
}
Do you know a way to make this possible (make the second view appears while the first one is disappearing), with some code for example ?
Thank you.
Try creating some dummy ViewController, and present your second one using it.