简体   繁体   中英

Loading xib from UIAlertView from a viewcontroller

In my app I have a xib that has several viewcontrollers and xibs (with more viewcontrollers)off of it.

I can go from xib to xib and load what ever view controllers I want.

My problem is when I go to a view in side one off my viewcontrollers (be it on the main xib or another) I have a navigation bar at the bottom with a single button marked "back". Now when this button is hit before it takes you back It asks if you want something to happen.

When you click yes a UIAlertView will pop up and tell you wants about to happen when you click "ok". I know my button is firing by NSLogging my tag.

However I need a certain xib file to load and it does not.

This is the code that I am trying to use -- now this works If I want to go from xib to xib from a button. So I am not sure why its not working in an alert view.

- (void)alertView:(UIAlertView *)alert clickedButtonAtIndex:(NSInteger)buttonIndex {
// the user clicked one of the OK/Cancel buttons
if(alert.tag==1)
{
    if (buttonIndex==0) {
        ControllPanelViewController *controllpanel = [[ControllPanelViewController alloc] initWithNibName:nil bundle:nil];
        [self presentModalViewController:controllpanel animated:YES];    
        NSLog(@"index 0");
    }
}

} 在此处输入图片说明

Adding pic do to a response: 在此处输入图片说明

您需要指定要打开的XIB:

ControllPanelViewController *controllpanel = [[ControllPanelViewController alloc] initWithNibName:@"XibNameHere" bundle:nil];

I have had similar problems before, not with a UIViewController, but with a UIActionSheet. When I tried to do this, I wanted to present a UIActionSheet depending on the selection of the UIAlertView. When I pressed something in the UIAlertView, the view was dismissed, but my action sheet was not shown. This was my solution; instead of:

if(alert.tag==1) {
    if (buttonIndex==0) {
        ControllPanelViewController *controllpanel = [[ControllPanelViewController alloc] initWithNibName:nil bundle:nil];
        [self presentModalViewController:controllpanel animated:YES];    
        NSLog(@"index 0");
    }
}

try something like:

if(alert.tag==1)
    if (buttonIndex==0)
        [self performSelector:@selector(presentController) withObject:nil afterDelay:.1];

with the method presentController being:

ControllPanelViewController *controllpanel = [[ControllPanelViewController alloc] initWithNibName:nil bundle:nil];
[self presentModalViewController:controllpanel animated:YES];    
NSLog(@"index 0");

The problem seems to be that the UIAlertView takes some time to dismiss itself (very small amount of time) and in that time presenting another view doesn't work.

Also, as Alan Zeino said, if the name of the xib is not the same as the name of the view controller (for example if you have two different xibs- one for ipad and one for iphone), then you do need to specify which to use. If the name of the xib is the same as the view controller, you do not have to specify a name.

Edit:

If you want to use an action sheet and expect the delegate methods to work when their actions are triggered, you'd better set the delegate of the action sheet to self and in your interface file add the protocol.

Since you have indicated that your log statement confirms correctly setting delegate and implementing the methods, the ' UIAlertView locks the screen ' theory seems the only expectable one.

As Rickay has said performSelector:AfterDelay: would likely work, but as he has also said that requires a second method to be created. I would say that this is the perfect time for a block.

Here are a couple of options: Either should be copy and paste solutions.

1) Assuming the current main runloop simply has to finish it's current call stack before the new view controller can be pushed you could use:

-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
    if (alertView.tag == 1) {
        if (buttonIndex == 0) {
            dispatch_async(dispatch_get_main_queue(), ^{
                ControllPanelViewController *controllpanel = [[ControllPanelViewController alloc] initWithNibName:nil bundle:nil];
                [self presentModalViewController:controllpanel animated:YES]; 
            });
        }
    }
}

This will add a block to the main queue that will create and show your ControllPanelViewController as soon as the main run loop becomes available.

If, however, that doesn't work and it is 'just a matter of time', a block will still work. Like So:

-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
    if (alertView.tag == 1) {
        if (buttonIndex == 0) {
            double delayInSeconds = 0.1;
            dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
            dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
                ControllPanelViewController *controllpanel = [[ControllPanelViewController alloc] initWithNibName:nil bundle:nil];
                [self presentModalViewController:controllpanel animated:YES]; 
            });
        }
    }
}

This will create a block that will 'fire' in the number of seconds specified. Here set to 0.1 seconds.

Again the first one is a cleaner, arguably better, and much easier to read option.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM