前提・実現したいこと
xcode11でswiftを使ってアプリがバックグラウンドでも処理をするプログラムを作りたい
発生している問題・エラーメッセージ
シミュレーターを起動し、アプリが起動してホーム画面へと遷移させてアプリをバックグラウンドにしてもバックグラウンド状態になった時に始まるはず処理が始まらない
該当のソースコード
ViewController.swift
import UIKit import Foundation import UserNotifications class ViewController: UIViewController { var alertController: UIAlertController! func alert(title:String, message:String) { alertController = UIAlertController(title: title,message:message,preferredStyle: .alert) alertController.addAction(UIAlertAction(title: "OK",style:.default,handler: nil)) present(alertController, animated: true) } func htmlprint(URLstr: UITextField!,Findstr: UITextField!){ // プログラムの開始 var myURL = "" myURL = URLstr.text! var myFind = "" myFind = Findstr.text! let targetURL = URL(string: myURL)! do { // 入力したURLのページから、HTMLのソースを取得する。 let sourceHTML = try String(contentsOf: targetURL, encoding: String.Encoding.utf8); //print("取得したHTMLのソースは以下です。↓\n" + sourceHTML); if sourceHTML.contains(myFind){ //alert(title:"HtmlWatcher",message:"文字列が見つかりました。") //通知処理 let seconds = Int(1) let content = UNMutableNotificationContent() content.title = "HtmlWatcher" content.subtitle = "確認" content.body = "確認しました。" content.sound = UNNotificationSound.default let trigger = UNTimeIntervalNotificationTrigger(timeInterval:Double(seconds), repeats: false) let request = UNNotificationRequest(identifier: "TIMER(seconds)", content: content,trigger: trigger) let center = UNUserNotificationCenter.current() center.add(request) { (error) in if let error = error { print(error.localizedDescription) } } }else{ alert(title:"HtmlWatcher",message:"文字列が見つかりませんでした。") } } catch { print("エラーが発生しました。"); } } @IBAction func OutputDialog(_ sender: Any) { alert(title: "サンプル",message: "メッセージ表示") } @IBOutlet weak var URLtext: UITextField! @IBOutlet weak var FindString: UITextField! var timer: Timer? var count: Int = 0 @IBAction func GetSource(_ sender: Any) { if URLtext.text == "" || FindString.text == ""{ alert(title:"HtmlWatcher",message:"入力してください") return; } timer?.invalidate() timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true, block: { (timer) in self.count += 1 print("(self.count)秒") if self.count%30 == 0 { self.htmlprint(URLstr: self.URLtext,Findstr: self.FindString); } }) } //バックグラウンドで始まるはずの処理 **override func viewDidLoad() { super.viewDidLoad(); NotificationCenter.default.addObserver( self, selector: #selector(ViewController.viewDidEnterBackground(notification:)), name: .AppDidEnterBackground, object: nil) } @objc func viewDidEnterBackground (notification: NSNotification?) { var ttimer = Timer() ttimer.invalidate() ttimer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true, block: { (timer) in self.count += 1 print("(self.count)秒") }) }** }
AppDelegate.swift
import UIKit import UserNotifications extension Notification.Name { static let AppDidEnterBackground = Notification.Name("applicationDidEnterBackground") } func applicationDidEnterBackground(_ application: UIApplication) { // 特定のnameで通知を発信 NotificationCenter.default.post( name: .AppDidEnterBackground, object: nil, userInfo: ["test": 123]) } @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { let center = UNUserNotificationCenter.current() center.requestAuthorization(options: [.alert, .badge, .sound]) { (granted, error) in if granted { print("Allowed") } else { print("Didn't allowed") } } return true } return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) } func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) { } }
試したこと
エラーメッセージが出ておらず原因が不明なため対処できないのでなし
補足情報(FW/ツールのバージョンなど)
アプリをフォアグラウンドに戻しても特にエラーや問題は発生しない
swiftでプログラミングを始めて1週間程度の初心者のため難しい説明をされても理解できないかもしれないのでお手柔らかにお願い致します。
コードの殆どはネット上からコピペしたもので、機能は理解できても仕組みまでは理解できていないものばかりです。
iOS 13 では SceneDelaget の sceneDidEnterBackground を使う必要があるようです。
あと、バックグラウンド動作とかは闇が深い部分なので、「swiftでプログラミングを始めて1週間程度」「コードの殆どはネット上からコピペした」「機能は理解できても仕組みまでは理解できていない」という方にはお勧めできません。コピペしたコードの意味をひとつひとつ理解されることをお勧めします。
ご回答ありがとうございます。
SceneDelagetのsceneDidEnterBackgroundを使ってバックグラウンドで処理できることが確認できました。
しかしtimerは動いてくれないようですね。
長時間バックグラウンドで処理させることに情報搾取などの危険性があるためアップルが規制しているのでしょうか?
調べたところtimerを動かす方法として無音を再生し続けるという方法を見つけました。
この方法だとストアに公開することはできないようですが知人のために作っているアプリのため問題ないです。
順番が逆ですが知人に急かされているため、まずはこのアプリを完成させてから基礎を学ぶつもりです。
あなたの回答
tips
プレビュー