当按下注销按钮时,我试图让我的 iPhone 应用程序以编程方式重新启动。
有人有代码示例可以分享吗?我读过可以通过修改 main.m 文件来实现,但我找不到任何与此相关的代码。
任何帮助,将不胜感激。
当按下注销按钮时,我试图让我的 iPhone 应用程序以编程方式重新启动。
有人有代码示例可以分享吗?我读过可以通过修改 main.m 文件来实现,但我找不到任何与此相关的代码。
任何帮助,将不胜感激。
笔记:
尽管这已被回答为“不可能”,但我认为对于新的 iOS 开发人员来说,这是一个有效的问题,他们可以做的事情可能正是他们想要的。
有一种方法可以从用户的角度“重新启动”您的应用程序,这在技术上不是重新启动或退出 iOS 应用程序。正如其他答案所指出的那样,iOS App 永远不应明确退出,因为这在 iOS 上是不允许的。
我的答案:
如果您希望您的应用程序回到它在启动时所处的状态,这不是 100% 可能的,但我将解释一种方法来获得大部分的方式,这应该足以满足所有有效目的。
首先要做的是重新创建你的根视图控制器。我建议从应用程序委托中的方法执行此操作,如下所示:
- (void)resetAppToFirstController
{
self.window.rootViewController = [[MyMainViewController alloc] initWithNibName:nil bundle:nil];
}
在许多情况下,这已经足够了,但是您拥有的任何应用程序状态也应该在此方法中重置。例如,注销用户,重置任何非持久状态,并尽可能取消(释放)所有对象。此方法也可用于最初从application:didFinishLaunchingWithOptions
.
框架类和单例:
您将无法完全重置任何框架单例或每个应用程序实例的状态,例如:
[UIApplication sharedApplication];
[NSNotificationCenter defaultCenter];
[NSUserDefaults standardUserDefaults];
[UIScreen screens];
// etc...
这可能很好,因为无论如何您都不应该在这些中存储任何非持久状态(除了NSNotificationCenter
,但是在释放对象时应该删除所有已注册的观察者)。如果您确实想要初始化或重置任何框架状态,您可以使用相同的resetAppToFirstController
方法进行操作。无论如何,应该没有必要重新创建这些或window
对象。
如果您有任何自己的单例,您可以通过将它们存储在单例持有者类中来重新创建它们(这本身就是一个真正的单例)。从概念上讲,这是一个简单的单例类,其中包含每个其他单例的属性和一个reset
方法来取消和释放它们。您的其他单例应使用此类(而不是静态或全局变量)来存储单例实例。如果您使用任何第三方库,请小心,因为它们也可能使用单例,您需要确保它们也使用您的单例持有者,以便您可以根据需要重置它们。无论如何,我认为这种技术是一种很好的做法,因为在某些情况下(例如单元测试),您确实希望通常是单例的对象消失并重新初始化为原始状态。但是,您不想将单例实现与单例持有者耦合,因此实现此目的的一个好方法是使用 anNSMutableDictionary
作为关联对象[UIApplication sharedApplication]
以单例类名作为键。但是,我有点偏离主题,因为这是超出此问题范围的更先进的技术。
就用户而言,上述内容应该足以“重置”您的应用程序。如果你想作为你的第一个视图控制器,你甚至可以再次显示启动画面。
首先,虽然可以强制杀死你的应用程序,但这是苹果不允许的,会被拒绝。即使它没有被拒绝,一旦它被杀死,也没有办法重新启动你的应用程序。如前所述,您只需要找到某种方法通过您的代码重置您的应用程序Jason Coco
。这可能需要更多的工作,但不被 Apple 拒绝是值得的。
试试这个,它对我有用。
-(void)restart
{
MyAppDelegate *appDelegate = (MyAppDelegate *)([UIApplication sharedApplication].delegate);
[appDelegate.navigationController popToRootViewControllerAnimated:NO];
UIViewController *topViewController = appDelegate.navigationController.topViewController;
Class class = [topViewController class];
NSString *nibName = topViewController.nibName;
UIViewController *rootViewcontroller = (UIViewController *)([[class alloc] initWithNibName:nibName bundle:nil]);
[appDelegate.navigationController.view removeFromSuperview];
appDelegate.navigationController.viewControllers = [NSArray arrayWithObject:rootViewcontroller];
[appDelegate.window addSubview:appDelegate.navigationController.view];
[appDelegate.window makeKeyAndVisible];
}
以下是使用私有 API 在模拟器上执行此操作的方法:
NSURL *URL = [NSURL URLWithString:[NSString stringWithFormat:@"%@://%@", scheme, endpointString]];
Class pClass = NSClassFromString(@"BKSSystemService");
id service = [[pClass alloc] init];
SEL pSelector = NSSelectorFromString(@"openURL:application:options:clientPort:withResult:");
NSMethodSignature *signature = [service methodSignatureForSelector:pSelector];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
invocation.target = service;
NSString *app = @"com.apple.mobilesafari";
[invocation setSelector:pSelector];
[invocation setArgument:&URL atIndex:2];
[invocation setArgument:&app atIndex:3];
unsigned int i = [service performSelector:NSSelectorFromString(@"createClientPort")];
[invocation setArgument:&i atIndex:5];
[invocation invoke];
exit(0);
这也应该适用于具有适当权利的越狱应用程序。
对于其他应用程序,可以使用简单的 html 页面:
NSString *format = @"https://dl.dropboxusercontent.com/s/rawt1ov4nbqh4yd/launchApp.html?scheme=%@&URL=%@";
NSURL *URL = [NSURL URLWithString:[NSString stringWithFormat:format, scheme, endpointString]];
[[UIApplication sharedApplication] openURL:URL];
exit(0);
不幸的是,在这种情况下需要互联网连接。
我在-applicationWillResignActive期间退出:如果应用程序在开始屏幕上并且 Apple 已经接受了多年。对用户来说,它看起来不像是崩溃。下次用户从图标启动应用程序时。在某些情况下,如果应用程序今天启动,则不会退出应用程序的附加检查可能对用户体验有用。
- (void)applicationWillResignActive:(UIApplication *)application
{
// called if phone-call comes in!
if([gameController isGameFinished])
exit(0);
}
把它放在 UIAlertAction 中,询问用户“保存并退出”。它将为 exit(0) 设置动画,因此至少看起来是计划好的。
- (void)saveAndQuit
{
[UIView animateWithDuration:0.8 animations:^{
self.window.alpha = 0.0; // fade out...
// ... while pinching to a point
self.window.transform = CGAffineTransformScale(
CGAffineTransformMakeTranslation( 0, 0 ), 0.1, 0.1 );
} completion:^(BOOL finished) {
exit(0);
}];
}