...または他の方法で通知を投稿しますか?
はい。通知をトリガーするバックグラウンド (起動) デーモンを使用して、これを機能させることができます (必ずしもではありませんUILocalNotification
)。通知がユーザーに警告を表示すると、デーモンは通常の UI アプリケーションを開くかどうかを決定できます。
起動デーモンを構築します。
これは私が見つけた最高のチュートリアルです。起動デーモンは、電話機の起動時に開始され、非グラフィカル バックグラウンド プロセスとして常に実行されます。そこから、更新のチェックをスケジュールできます。(メソッドHelloDaemon
ですべての作業を行うクラスがありますrun:
):
int main(int argc, char *argv[]) {
@autoreleasepool {
HelloDaemon* daemon = [[HelloDaemon alloc] init];
// start a timer so that the process does not exit.
NSTimer* timer = [[NSTimer alloc] initWithFireDate: [NSDate date]
interval: 1.0
target: daemon
selector: @selector(run:)
userInfo: nil
repeats: NO];
NSRunLoop* runLoop = [NSRunLoop currentRunLoop];
[runLoop addTimer: timer forMode: NSDefaultRunLoopMode];
[runLoop run];
}
return 0;
}
デーモンはNSTimer
通常どおり使用できるため、別のタイマー ( 内run:
) をスケジュールして、必要なときにいつでもダウンロードする更新を確認します。
デーモンからユーザーに通知
デーモンがユーザーに通知する必要があると判断した場合は、次のいずれかを実行できます。
1)完全な UI アプリケーションを開きます。
#include <dlfcn.h>
#define SBSERVPATH "/System/Library/PrivateFrameworks/SpringBoardServices.framework/SpringBoardServices"
-(void) openApp {
// the SpringboardServices.framework private framework can launch apps,
// so we open it dynamically and find SBSLaunchApplicationWithIdentifier()
void* sbServices = dlopen(SBSERVPATH, RTLD_LAZY);
int (*SBSLaunchApplicationWithIdentifier)(CFStringRef identifier, Boolean suspended) = dlsym(sbServices, "SBSLaunchApplicationWithIdentifier");
int result = SBSLaunchApplicationWithIdentifier(CFSTR("com.mycompany.AppName"), false);
dlclose(sbServices);
}
このコードcom.apple.springboard.launchapplications
を正常に使用するには、デーモンの資格が必要です。 エンタイトルメントの追加については、こちらを参照してください。次のように、デーモン実行可能ファイルには entitlements.xml ファイルが必要です。
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.springboard.launchapplications</key>
<true/>
</dict>
</plist>
2)デーモンから単純なアラート ウィンドウを表示し、ユーザーにイベントを通知し、UI アプリを開くように促します。
#include "CFUserNotification.h"
-(void) showAlert {
NSMutableDictionary* dict = [NSMutableDictionary dictionary];
[dict setObject: @"Alert!" forKey: (__bridge NSString*)kCFUserNotificationAlertHeaderKey];
[dict setObject: @"Updates Ready!" forKey: (__bridge NSString*)kCFUserNotificationAlertMessageKey];
[dict setObject: @"View" forKey:(__bridge NSString*)kCFUserNotificationDefaultButtonTitleKey];
[dict setObject: @"Cancel" forKey:(__bridge NSString*)kCFUserNotificationAlternateButtonTitleKey];
SInt32 error = 0;
CFUserNotificationRef alert =
CFUserNotificationCreate(NULL, 0, kCFUserNotificationPlainAlertLevel, &error, (__bridge CFDictionaryRef)dict);
CFOptionFlags response;
// we block, waiting for a response, for up to 10 seconds
if((error) || (CFUserNotificationReceiveResponse(alert, 10, &response))) {
NSLog(@"alert error or no user response after 10 seconds");
} else if((response & 0x3) == kCFUserNotificationAlternateResponse) {
// user clicked on Cancel ... just do nothing
NSLog(@"cancel");
} else if((response & 0x3) == kCFUserNotificationDefaultResponse) {
// user clicked on View ... so, open the UI App
NSLog(@"view");
[self openApp];
}
CFRelease(alert);
}
CFUserNotification.h
上記の方法でコードを使用するには、ヘッダーが必要です。グーグルで検索するか、こちらを参照してください。この古い wiki ドキュメントCFUserNotification
には、iOS アプリから使用するための優れた情報も示されています。
上記のKennyTM からリンクした回答は、デバイスがロックされている場合でもアラート ポップアップを表示する方法も示しています。