iPhoneアプリにプログラムで再起動するように強制します
-
10-10-2019 - |
質問
ログアウトボタンが押されたときにプログラムで再起動するようにiPhoneアプリを取得しようとしています。
共有するコードサンプルを持っている人はいますか? main.mファイルを変更することで可能であるが、これに関連するコードを見つけることができなかったことを読みました。
どんな助けも感謝します。
解決
まず第一に、アプリを殺すことは可能ですが、これはAppleによって許可されておらず、拒否されます。拒否されていなくても、アプリが殺されたら再起動する方法はありません。コードを介してアプリをリセットする方法を見つける必要があります。 Jason Coco
言った。それはもっと仕事かもしれませんが、Appleに拒否されないことは価値があります。
他のヒント
ノート:
これは「不可能」として答えられていますが、新しい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
それらをすべて無効にしてリリースする方法。他のシングルトンは、このクラスを(静的またはグローバル変数の代わりに)使用して、Singletonインスタンスを保存する必要があります。サードパーティのライブラリを使用する場合は、シングルトンも使用する可能性があり、必要に応じてリセットできるようにシングルトンホルダーを使用する必要があるため、注意してください。とにかく、この手法は良い練習だと思います。なぜなら、場合によっては(単位テストなど)、通常、シングルトンであるオブジェクトがなくなって、手付かずの状態に再編成するオブジェクトを望んでいるからです。ただし、Singletonの実装をSingleton-Holderと結合したくないので、これを実装する良い方法は、 NSMutableDictionary
関連するオブジェクトとして [UIApplication sharedApplication]
シングルトンのクラス名をキーとして。しかし、これはこの質問の範囲を超えたより高度な手法であるため、私はトピックを少し離れています。
上記は、ユーザーに関する限り、アプリケーションを「リセット」するのに十分でなければなりません。最初のビューコントローラーとして必要に応じて、スプラッシュ画面を再度表示することもできます。
これを試してみてください、それは私のために働きます。
-(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);
残念ながら、この場合、インターネット接続が必要です。
私は中に終了します -ApplicationWillResiblicive: アプリがスタート画面にあり、Appleが何年もそれを受け入れている場合。ユーザーにとっては、クラッシュのようには見えません。次回、ユーザーはアイコンからアプリを起動します。今日起動された場合にアプリを終了しない追加のチェックは、場合によってはユーザーの経験に役立つ可能性があります。
- (void)applicationWillResignActive:(UIApplication *)application
{
// called if phone-call comes in!
if([gameController isGameFinished])
exit(0);
}
これをユーザーに「保存して終了する」と尋ねるuialertactionに入れます。出口(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);
}];
}