强制 iPhone 应用程序以编程方式重新启动?

发布于 2024-10-07 04:18:54 字数 124 浏览 0 评论 0原文

我试图让我的 iPhone 应用程序在按下“注销”按钮时以编程方式重新启动。

有人有代码示例可以分享吗?我读到可以通过修改 main.m 文件来实现,但我找不到与此相关的任何代码。

任何帮助将不胜感激。

I am trying to get my iPhone app to restart programmatically when the Logout button is pressed.

Has anyone got a code sample to share? I've read that it is possible by modifying the main.m file but I couldn't find any code related to this.

Any help would be appreciated.

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

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

发布评论

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

评论(7

向日葵 2024-10-14 04:18:54

注意:

虽然这已被回答为“不可能”,但我认为对于新的 iOS 开发人员来说这是一个有效的问题,并且他们可以做一些可能是他们想要的事情。

有一种方法可以从用户的角度“重新启动”应用程序,从技术上讲,这不是重新启动或退出 iOS 应用程序。正如其他答案所指出的,iOS 应用程序永远不应该显式退出,因为 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 方法。您的其他单例应该使用此类(而不是静态或全局变量)来存储单例实例。如果您使用任何第三方库,请务必小心,因为它们也可能使用单例,您需要确保它们也使用您的单例持有者,以便您可以根据需要重置它们。我认为这种技术无论如何都是很好的实践,因为在某些情况下(例如单元测试),您确实希望通常是单例的对象消失并重新初始化为原始状态。但是,您不想将单例实现与单例持有者结合起来,因此实现此目的的一个好方法是使用 NSMutableDictionary 作为 [UIApplication sharedApplication]< 上的关联对象/code> 以单例类名作为键。然而,我有点偏离主题,因为这是超出这个问题范围的更先进的技术。


就用户而言,上述内容应该足以“重置”您的应用程序。如果您想作为第一个视图控制器,您甚至可以再次显示启动屏幕。

Note:

Although this has been answered as 'not possible' I think it's a valid question for a new iOS developer to ask and there is something they can do which is probably what they want.

There is a way to 'restart' your app from the user's perspective which is not technically restarting or exiting the iOS App. As pointed out by other answers an iOS App should never explicitly exit because this is not allowed on iOS.

My Answer:

If you want your app to go back to the state it was in at launch this is not 100% possible but I will explain a way to get most of the way there that should be sufficient for all valid purposes.

The first thing to do is to re-create your root view controller. I recommend doing this from a method in the app delegate like this:

- (void)resetAppToFirstController
{
    self.window.rootViewController = [[MyMainViewController alloc] initWithNibName:nil bundle:nil];
}

In many cases this will be enough, but any app-state that you have should also be reset in this method. For example log out a user, reset any non-persistent state, and nullify (release) all objects that you can. This method can also be used to initially create your first view controller from application:didFinishLaunchingWithOptions.

Framework classes and Singletons:

You will not be able to completely reset the state of any framework singletons or per-app instances, such as these:

[UIApplication sharedApplication];
[NSNotificationCenter defaultCenter];
[NSUserDefaults standardUserDefaults];
[UIScreen screens];
// etc...

That is probably fine as you shouldn't be storing any non-persistent state in these anyway (except NSNotificationCenter, but all registered observers should have been removed when the objects were released). If you do want to initialise or reset any framework state you can do it in the same resetAppToFirstController method. Anyway, there should be no need to re-create these, or the window object.

If you have any of your own singletons, you can re-create these by storing them in a singleton-holder class (which is itself a real singleton). Conceptually, this is a simple singleton class with properties for each of your other singletons and a reset method to nullify and release them all. Your other singletons should use this class (instead of a static or global variable) to store singleton instances. Be careful if you use any third party libraries as they may also employ singletons and you will need to ensure these also use your singleton-holder so that you can reset them as needed. I think this technique is good practice anyway, because in some cases (for example unit testing) you do want objects which are usually singletons to go away and reinitialise to a pristine state. However, you don't want to couple the singleton implementations with your singleton-holder, so a good way to implement this is by using an NSMutableDictionary as an associated object on [UIApplication sharedApplication] with the singleton class names as keys. However, I'm going off topic a bit as this is a more advanced technique beyond the scope of this question.


The above should be sufficient to 'reset' your application as far as the user is concerned. You can even show the splash screen again if you want as your first view controller.

始终不够爱げ你 2024-10-14 04:18:54

首先,虽然可以强制杀死你的应用程序,但这是苹果不允许的,会被拒绝。即使它没有被拒绝,一旦应用程序被终止,也无法重新启动它。正如 Jason Coco 所说,您只需要找到某种方法通过代码重置应用程序即可。这可能需要更多的工作,但为了不被苹果拒绝,这是值得的。

First of all, although it is possible to force kill your app, this is not allowed by Apple and will rejected. Even if it wasn't rejected, there is no way to restart your app once it's killed. You just need to find some way to reset your app through your code, as Jason Coco said. It might be more work, but it's worth it to not get rejected by Apple.

手心的温暖 2024-10-14 04:18:54

试试这个,它对我有用。

-(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];
}

try this, it works for me.

-(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];
}
久伴你 2024-10-14 04:18:54

Objective-C:

exit(0);

Swift:

exit(0)

我在 2 个实时应用程序上有这个,它们没有被拒绝。我的一个应用程序甚至将这行代码作为我的应用程序主页中的一项功能。它位于右上角,即 Twitter 上的推文按钮。所以不用担心苹果会拒绝,除非看起来像是意外崩溃。

输入图像描述这里

Objective-C:

exit(0);

Swift:

exit(0)

I have this on 2 live apps and they haven't been rejected. One of my apps even has this line of code as a feature in the home page of my app. Its located at the top right corner, where tweet button is on Twitter. So don't worry about the Apple rejecting unless it looks like an unexpected crash.

enter image description here

梦一生花开无言 2024-10-14 04:18:54

以下是如何使用私有 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);

不幸的是,在这种情况下需要互联网连接。

Here is how you can do this on simulator using private 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);

This also should work on jailbroken apps with appropriate entitlements.

For other apps simple html page can be used:

    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);

Unfortunately, internet connection is needed in this case.

梦幻的心爱 2024-10-14 04:18:54

将其放入 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);
    }];
}

Put this in a UIAlertAction asking the user "Save and Quit". It will animate the exit(0) so at least it looks planned.

- (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);
    }];
}
〃温暖了心ぐ 2024-10-14 04:18:54

如果应用程序位于开始屏幕上并且 Apple 多年来已接受它,我会在 -applicationWillResignActive: 期间退出。对于用户来说,它不会看起来像崩溃。下次用户从该图标启动应用程序。在某些情况下,如果今天启动了应用程序,则不会退出该应用程序的附加检查可能对用户体验很有用。

- (void)applicationWillResignActive:(UIApplication *)application
{
    // called if phone-call comes in!
    if([gameController isGameFinished])
        exit(0);
}

I exit during -applicationWillResignActive: if the app is on the start screen and Apple has accepted it for years. To the user it will not look like a crash. Next time the user starts the app from the icon. An additional check that does not quit the app if it was launched today could be useful for the user-experience in some cases.

- (void)applicationWillResignActive:(UIApplication *)application
{
    // called if phone-call comes in!
    if([gameController isGameFinished])
        exit(0);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文