解雇ModalViewControllerAnimated:(和解雇ViewControllerAnimated)在iOS 5中崩溃

发布于 2024-12-10 21:30:42 字数 2677 浏览 0 评论 0原文

我找不到任何合乎逻辑的解释,但事实仍然是,在iOS 5(xCode 4.2)中,如果我presentModalView:*animated:YES,我可以调用dismissModalViewAnimated:*很好,但是如果我调用presentModalView:*animated:NO ,然后调用解雇方法会崩溃。 (如果我使用新的presentViewController:animated:completion:+missViewControllerAnimated:效果相同)。我现在打算尝试解决这个问题(我不想让演示文稿动画化)并向苹果报告错误,但我已经为此苦恼了一段时间。欢迎任何和所有建议。 iOS 5 上的内容不多,所以请尽可能提供帮助。在 iOS 4 或 iOS 5 中不会崩溃的示例代码:

LoginController *loginController = [[LoginController alloc] initWithNibName:@"LoginControllerGG" bundle:nil];
[self presentModalViewController:loginController animated:YES];
[loginController release];
...
[self dismissModalViewControllerAnimated:YES];

这将在 iOS 5 中崩溃,并在解雇调用时显示 EXC_BAD_ACCESS:

LoginController *loginController = [[LoginController alloc]    initWithNibName:@"LoginControllerGG" bundle:nil];
[self presentModalViewController:loginController animated:NO];
[loginController release];
...
[self dismissModalViewControllerAnimated:YES]; //crashes with EXC_BAD _ACCESS

一个注释:我在 viewDidLoad 上的 loginController 中有一个动画。看看去掉它是否会改变什么,但我想把它拿出来,因为我需要尽快找到解决方案。


[编辑]完整的代码流程...在AppDelegate中,application:didFinishLaunchingWithOptions:

if (!loggedIn)  [myViewController showLoginPanel];

在myViewController中:

- (void)showLoginPanel {    
    LoginController *loginController = [[LoginController alloc] initWithNibName:@"LoginControllerGG" bundle:nil];
    if ([self respondsToSelector:@selector(presentViewController:animated:completion:)]) {
        [self presentViewController:loginController animated:NO completion:nil];
    } else {
        [self presentModalViewController:loginController animated:NO]; //iOS 4 works fine with or without animation   
    } 
    [loginController release];  
}

在loginController中:

- (IBAction)closeLoginWindow {
    [[NSNotificationCenter defaultCenter] postNotificationName:@"CloseLoginWindow" object:nil];
}   //doing it this way because calling on the self.parentViewController doesn't work

回到myViewController:

- (void) viewDidLoad
    ...
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(closeLoginWindow) name:@"CloseLoginWindow" object:nil];
    ...

- (void)closeLoginWindow {
    if ([self respondsToSelector:@selector(dismissViewControllerAnimated:completion:)]) {
        [self dismissViewControllerAnimated:YES completion:nil];    //iOS 5 crashes only if presentation was not animated
    } else [self dismissModalViewControllerAnimated:YES];    //deleting the previous condition, iOS 5 still crashes if presentation was not animated
}    

I can't find any logical explanation, but the fact remains that, in iOS 5 (xCode 4.2), if I presentModalView:* animated:YES, I can call dismissModalViewAnimated:* fine, but if I call presentModalView:* animated:NO, then calling the dismiss method crashes. (This works the same if I use the new presentViewController:animated:completion: + dismissViewControllerAnimated:). I am going TRY to work around this for now (I don't want the presentation animated) and report a bug to Apple, but I have been beating my head on this for a while. Any and all suggestions are welcome. Not much out there on iOS 5, so please help if you can. Sample code that does not crash in iOS 4 or iOS 5:

LoginController *loginController = [[LoginController alloc] initWithNibName:@"LoginControllerGG" bundle:nil];
[self presentModalViewController:loginController animated:YES];
[loginController release];
...
[self dismissModalViewControllerAnimated:YES];

This will crash in iOS 5 with EXC_BAD_ACCESS on the dismiss call:

LoginController *loginController = [[LoginController alloc]    initWithNibName:@"LoginControllerGG" bundle:nil];
[self presentModalViewController:loginController animated:NO];
[loginController release];
...
[self dismissModalViewControllerAnimated:YES]; //crashes with EXC_BAD _ACCESS

One note: I have an animation within the loginController that happens on viewDidLoad. Going to see if taking that out changes anything, but I wanted to get this out there since I need a solution asap.


[Edit] Full code flow... In AppDelegate, application:didFinishLaunchingWithOptions:

if (!loggedIn)  [myViewController showLoginPanel];

In myViewController:

- (void)showLoginPanel {    
    LoginController *loginController = [[LoginController alloc] initWithNibName:@"LoginControllerGG" bundle:nil];
    if ([self respondsToSelector:@selector(presentViewController:animated:completion:)]) {
        [self presentViewController:loginController animated:NO completion:nil];
    } else {
        [self presentModalViewController:loginController animated:NO]; //iOS 4 works fine with or without animation   
    } 
    [loginController release];  
}

In loginController:

- (IBAction)closeLoginWindow {
    [[NSNotificationCenter defaultCenter] postNotificationName:@"CloseLoginWindow" object:nil];
}   //doing it this way because calling on the self.parentViewController doesn't work

Back in myViewController:

- (void) viewDidLoad
    ...
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(closeLoginWindow) name:@"CloseLoginWindow" object:nil];
    ...

- (void)closeLoginWindow {
    if ([self respondsToSelector:@selector(dismissViewControllerAnimated:completion:)]) {
        [self dismissViewControllerAnimated:YES completion:nil];    //iOS 5 crashes only if presentation was not animated
    } else [self dismissModalViewControllerAnimated:YES];    //deleting the previous condition, iOS 5 still crashes if presentation was not animated
}    

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

和我恋爱吧 2024-12-17 21:30:42

在 iOS5 中,生命周期的管理发生了某种变化,我无法详细解释这个问题。无论如何,修复方法是将工作流程从 applicationDidFinishLaunchingWithOptions 推迟到 applicationDidBecomeActive。似乎有些东西没有在调用 applicationDidFinishLaunchingWithOptions 时正确初始化。

- (void)applicationDidFinishLaunchingWithOptions:... {    
    // in order to do this only at launching, but not on every activation 
    // Declaration as property for example
    applicationDidLaunch = YES;
}

- (void) applicationDidBecomeActive:(UIApplication *)application {
    if (applicationDidLaunch) {
        applicationDidLaunch = NO;
        [Start your login Workflow with modal view presenting here]
    }
}

很好奇你的反馈:)....

In iOS5 the managing of the lifecyle somehow changed and I cannot explain that issue in detail. Anyway, the fix is to postpone that workflow from applicationDidFinishLaunchingWithOptions to applicationDidBecomeActive. It seems that something isn't initialized right at the call of applicationDidFinishLaunchingWithOptions.

- (void)applicationDidFinishLaunchingWithOptions:... {    
    // in order to do this only at launching, but not on every activation 
    // Declaration as property for example
    applicationDidLaunch = YES;
}

- (void) applicationDidBecomeActive:(UIApplication *)application {
    if (applicationDidLaunch) {
        applicationDidLaunch = NO;
        [Start your login Workflow with modal view presenting here]
    }
}

Curious to ur feedback :)....

泼猴你往哪里跑 2024-12-17 21:30:42

我要添加我的 2 美分:我有 ImagePickerController,并且仅当我没有手动释放选择器(IOS 5 SDK)时才使其解除工作。

所以。对于你的情况我可以提供这样的解决方法:
1.删​​除行-[loginControllerrelease];
2.为了防止内存泄漏,将loginController作为属性添加到当前控制器中,并仅在当前控制器的dealloc()中释放它:

@interface myViewController : UIViewController 

@property (nonatomic, retain) LoginController *loginController;

@end

...

@implementation myViewController

- (void)showLoginPanel {    
    self.loginController = [[LoginController alloc] initWithNibName:@"LoginControllerGG" bundle:nil];
     // ... something goes here  
}

-(IBAction)loginClose() 
{
    // this should close all windows as far as you call it from current (main) controller
    [self dismissModalViewControllerAnimated:YES]; 
    // ... then anything you want EXCEPT [loginController release];
}

-(void)dealloc() 
{
    [loginController release];
}

@end

祝你好运:)

PS我刚刚写了这篇文章,所以这只是一个如何欺骗它的想法。 Somebosy 可能会纠正我......尽管无论如何它对我有用。

I will add my 2 cents : i had ImagePickerController and got its dismissing working only when i did not release the picker manually (IOS 5 SDK).

So. for your case i could offer such workaround :
1. remove line - [loginController release];
2. to prevent memory leaks add loginController as a property to your current controller and release it only in dealloc() of current controller :

@interface myViewController : UIViewController 

@property (nonatomic, retain) LoginController *loginController;

@end

...

@implementation myViewController

- (void)showLoginPanel {    
    self.loginController = [[LoginController alloc] initWithNibName:@"LoginControllerGG" bundle:nil];
     // ... something goes here  
}

-(IBAction)loginClose() 
{
    // this should close all windows as far as you call it from current (main) controller
    [self dismissModalViewControllerAnimated:YES]; 
    // ... then anything you want EXCEPT [loginController release];
}

-(void)dealloc() 
{
    [loginController release];
}

@end

Good luck :)

P.S. I have just written this so it is just an idea how to cheat it. Somebosy may correct me ... though anyway it worked for me.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文