【问题标题】:Making the app save data when the app terminates让应用程序在应用程序终止时保存数据
【发布时间】:2023-04-03 23:40:01
【问题描述】:

我已经知道如何保存内容,并且可以在打开应用程序时自动加载它们。但我不知道如何在它关闭时保存它们!我现在有一个按钮。我试图只保存一个值,StreakNumber。但是,无论何时尝试,我都会失败。

在应用程序委托中,我尝试说ViewController.AppSave(ViewController)。我收到一个错误:

源文件中的编辑器占位符 表达式解析为未使用的函数

如果我使用ViewController.AppSave() 我收到以下错误:

实例成员“SaveApp”不能用于“ViewController”类型;您的意思是改用这种类型的值吗?

import UIKit
import UserNotifications

class ViewController: UIViewController {
    //TEST PLAY AREA//

    @IBAction func SaveButton(_ sender: Any) {
        SaveApp()
    }

    @IBAction func LoadButton(_ sender: Any) {
        LoadApp()
    }

    ///TEST PLAY AREA ENDS
    public var streakNumber = 0
    public var  streakNumberString = ""

    public var activated = false

    let defaults = UserDefaults.standard
    //Labels
    @IBOutlet var streakNumberLabel: UILabel!

    @IBOutlet var remainingTimeTextLabel: UILabel!

    @IBOutlet var remainingTimeNumberLabel: UILabel!
    //Buttons
    @IBAction func startButton(_ sender: Any) {
        Activate()

    }
    @IBAction func stopButton(_ sender: Any) {
        Deactivate()
        seconds = 59
        minutes = 59
        hours = 47

    }

    //Timer
    var timer = Timer()
    var seconds = 0
    var minutes = 0
    var hours = 0

    // Nitifications
    //END
    override func viewDidLoad() {
        super.viewDidLoad()

        LoadApp()

        // this enables notifications
        UNUserNotificationCenter.current().requestAuthorization(options:[.alert , .sound , .badge], completionHandler:{ didAllow, error in
        })
    }

    func Activate (){
        if activated == false {
            streakNumber += 1

        }
        activated = true
        streakNumberLabel.text = String(streakNumber)
    }

    func Deactivate (){
        if activated == true{
            activated = false
            ActivTimer()

            // Notification
            let content = UNMutableNotificationContent()
            content.title = " 10  secodns are up "
            content.subtitle = " yep time passed"
            content.body = " The 10 seconds are really up!!"
            content.badge = 1
            let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 600, repeats:false)
            let request = UNNotificationRequest(identifier: "timerDone", content: content , trigger: trigger)
            UNUserNotificationCenter.current().add(request,withCompletionHandler:nil)
        }
    }

    @objc func Clock(){
        seconds = seconds-1
        if seconds == -1{
            seconds = 59
            minutes = minutes-1
        }
        if minutes  == -1{
            minutes  = 59
            hours = hours-1
        }
        remainingTimeNumberLabel.text = (String(hours) + ":" + String(minutes) + ":" + String(seconds))
        if seconds == 0 && hours == 0 && minutes == 0 {

            timer.invalidate()

        }
    }

    func ActivTimer(){
        timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(ViewController.Clock), userInfo: nil, repeats: true)
    }//SAVING STUFF DOESNT WORK
    //

    func SaveApp(){
        streakNumberString = String(streakNumber)
        defaults.set(streakNumberString, forKey: "streakNumbers")
        print("Saved" + String(defaults.integer(forKey: "streakNumbers")))

    }

    func LoadApp(){
        streakNumberString =  defaults.string(forKey: "streakNumbers")!
        print (defaults.integer(forKey: "streakNumbers") )
        streakNumber = Int(streakNumberString)!
        streakNumberLabel.text = String(streakNumber)
    }//
}

【问题讨论】:

标签: ios swift delegates


【解决方案1】:

错误说明了一切。您不能在 ViewController 上调用 SaveApp()。您实际上需要一个 ViewController 的实例来调用 SaveApp() 自身。

如果您希望您的ViewController 实例在应用程序终止时保存其数据,您可以从AppDelegateapplicationDidEnterBackground 方法发布通知,该方法在应用程序被最小化时和终止之前调用:

func applicationDidEnterBackground(_ application: UIApplication) {

    NotificationCenter.default.post(Notification(name: Notification.Name("AppAboutToTerminateOrMinimize")))
}

然后您可以在您的ViewControllerviewDidLoad() 中订阅该通知:

NotificationCenter.default.addObserver(self,
                                       selector: #selector(AppSave),
                                       name: Notification.Name("AppAboutToTerminateOrMinimize"),
                                       object: nil)

或者如 cmets 中提到的 rmaddy,您可以将以下代码放入 ViewControllerviewDidLoad() 并跳过 AppDelegate 部分:

NotificationCenter.default.addObserver(self,
                                       selector: #selector(AppSave),
                                       name: Notification(name: UIApplicationDidEnterBackgroundNotification,
                                       object: nil)

这样,当应用程序最小化/终止AppDelegate 将发送通知时,ViewController 实例(如果还活着)将收到它并调用AppSave()

您必须将 AppSave() 方法注释为 @objc

使用 lowerCamelCase 来命名属性和方法 / 即 appSave() 而不是 AppSave() 是一个好习惯

【讨论】:

  • 有一个更好的方法来做到这一点。只需让视图控制器注册UIApplicationDidEnterBackground 通知。无需自定义通知。无需在applicationDidEnterBackground 应用委托方法中发布任何内容。
  • @rmaddy 我该怎么做?
  • 你能发布你编辑的SaveApp()viewDidLoad()方法吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-14
相关资源
最近更新 更多