web-dev-qa-db-ja.com

iPhoneアプリを強制的にプログラムで再起動する

ログアウトボタンが押されたときに、プログラムでiPhoneアプリを再起動しようとしています。

誰かが共有するコードサンプルを持っていますか? main.mファイルを変更することで可能ですが、これに関連するコードは見つかりませんでした。

任意の助けをいただければ幸いです。

44
manospro

まず、アプリを強制的に強制終了することは可能ですが、これはAppleによって許可されておらず、拒否されます。拒否されなかったとしても、アプリを一度再起動する方法はありませんJason Cocoが言ったように、コードを介してアプリをリセットする方法を見つける必要があるだけです。もっと手間がかかるかもしれませんが、Appleに拒否されないことは価値があります。

18
sudo rm -rf

注:

これは「不可能」と回答されていますが、新しいiOS開発者が尋ねるのは妥当な質問だと思います。

ユーザーの観点からアプリを「再起動」する方法はありますが、これは技術的にiOSアプリを再起動または終了することではありません。他の回答で指摘されているように、iOSアプリはiOSで許可されていないため、明示的に終了しないでください。

私の答え:

アプリを起動時の状態に戻したい場合、これは100%可能というわけではありませんが、すべての有効な目的に十分な方法でほとんどの方法を取得する方法を説明します。

最初に行うことは、ルートView Controllerを再作成することです。次のようなアプリデリゲートのメソッドからこれを行うことをお勧めします。

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

多くの場合これで十分ですが、このメソッドでアプリの状態もリセットする必要があります。たとえば、ユーザーをログアウトし、非永続状態をリセットし、可能なすべてのオブジェクトを無効化(解放)します。このメソッドは、最初にapplication:didFinishLaunchingWithOptionsから最初のView Controllerを作成するためにも使用できます。

フレームワーククラスとシングルトン:

次のようなフレームワークシングルトンまたはアプリごとのインスタンスの状態を完全にリセットすることはできません。

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

とにかくこれらの非永続状態を保存するべきではないので、おそらくそれで問題ありません(NSNotificationCenterを除くが、登録されたすべてのオブザーバーはオブジェクトが解放されたときに削除されるはずです)フレームワークの状態を初期化またはリセットする場合は、同じresetAppToFirstControllerメソッドで行うことができます。とにかく、これらまたはwindowオブジェクトを再作成する必要はありません。

独自のシングルトンがある場合は、シングルトンホルダークラス(それ自体が実際のシングルトン)に格納することで、これらを再作成できます。概念的には、これは他の各シングルトンのプロパティと、それらすべてを無効にしてリリースするresetメソッドを持つシンプルなシングルトンクラスです。他のシングルトンは、(静的またはグローバル変数の代わりに)このクラスを使用して、シングルトンインスタンスを格納する必要があります。サードパーティライブラリもシングルトンを使用する可能性があるため、サードパーティライブラリを使用する場合は注意してください。必要に応じてリセットできるように、シングルトンホルダーも使用する必要があります。とにかく、この手法は良いプラクティスだと思います。なぜなら、場合によっては(たとえば単体テスト)、通常シングルトンであるオブジェクトを削除して、初期状態に再初期化する必要があるからです。ただし、シングルトン実装をシングルトンホルダーと結合したくないので、これを実装する良い方法は、[UIApplication sharedApplication]の関連オブジェクトとしてシングルトンクラス名でNSMutableDictionaryを使用することです。キーとして。ただし、これはこの質問の範囲を超えたより高度な技術であるため、少し話題を外します。


上記の説明は、ユーザーに関する限り、アプリケーションを「リセット」するのに十分なはずです。最初のView Controllerとして使用したい場合は、スプラッシュ画面を再度表示することもできます。

65
jhabbott

これを試して、それは私のために働く。

-(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];
}
15
roberto.buratti

Objective-C:

exit(0);

迅速:

exit(0)

私はこれを2つのライブアプリで使用していますが、拒否されていません。私のアプリの1つは、アプリのホームページの機能としてこのコード行さえ持っています。 TwitterのTweetボタンがある右上隅にあります。したがって、予期しないクラッシュのように見えない限り、Appleが拒否されることを心配しないでください。

enter image description here

9
Esqarrouth

プライベート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);

残念ながら、この場合はインターネット接続が必要です。

5
Bohdan Orlov

-applicationWillResignActive:の間に終了します。アプリがスタート画面にあり、Appleは何年もそれを受け入れています。ユーザーにとってはクラッシュのようには見えません。ユーザーがアイコンからアプリを起動する時間アプリが今日起動された場合にアプリを終了しない追加チェックは、場合によってはユーザーの経験に役立つ可能性があります。

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

これを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);
    }];
}
0
Jeff