Swift2 iOS - 注销当前用户并创建新用户,为新用户保留旧用户的默认值

Swift2 iOS -Logging a current user out and creating a new user keeps the old user's defaults for the new user

我正在为我的项目使用模拟器。当用户登录时,我使用 NSUserDefaults 来确定他们将进入哪个级别。即

杰克下载了我的应用程序,创建了一个帐户,从第 1 级开始,购买了一些魔法,由于他购买了魔法,他现在可以跳过第 1 级。杰克现在处于第 2 级并退出游戏。 Jack 注销并重新登录后,他现在将降落在第 2 层。

在 LevelOneVC 中有一个 buyMagic 按钮用于魔法 purchase/level 跳过。

在 SignInVC 中,我使用 NSUserDefaults.standardUserDefaults().boolForKey 来确定是否购买了该魔法,在本例中为 true,这将确定将 Jack 发送到哪个级别。该 bool 值在 signInButton 中访问。

Jill 是 Jack 的朋友,她借用了他的 phone,创建了一个帐户,她一登录就进入了 2 级。她应该进入 1 级,因为她是不同的用户并且很明显Firebase uid 与 Jack 不同(我打印它们以确保)。

我使用 Firebase 作为后端,它成功地让用户登录和注销,他们都变得不同 uid's。但是,由于我使用的是模拟器,因此似乎正在记录 NSUserDefault 值,无论哪个用户登录,他们都将获得以前的用户值。

我还尝试在 SignUpVC 中将 bool 改回 false,但所做的一切只是在 Jill 注销并且 Jack 重新登录后他再次从级别 1 开始。

仅供参考,我在 NSUserdefaults 中节省的唯一价值是他们是否购买了魔法,而不是他们的电子邮件或购买信息等。

我想这些问题适用于任何其他设备特定信息,例如用户可以为我的应用程序指定的特定背景颜色或字体。我不认为那会是 server side data,而是将它们保存在 NSUserDefaults.

我是否应该在 NSUserDefaults 或我的 Firebase 后端中保存他们是否购买了魔法的信息?我哪里错了?

Jill 降落在 2 层是因为她使用的是完全相同的设备吗?

除了使用后端之外,如果多个用户使用同一设备并且一旦 1 个注销并且之前值中的其他日志将不会被保存,我怎样才能得到它

顺便说一句,我也尝试过将 singleton classglobal bool variable 一起使用,但出现了同样的问题。我没有包含它

AppDelegate:

class AppDelegate: UIResponder, UIApplicationDelegate {
      //this is initially a false value
      NSUserDefaults.standardUserDefaults().boolForKey("wasMagicBought")
}

SignInVC

SignInController: UIViewController{

let magicPurchased = NSUserDefaults.standardUserDefaults().boolForKey("wasMagicBought")

@IBAction func signIn(sender: UIButton){
   //firebase method to sign user in and handler with async_brings them inside based off of the NSUserDefaults value
   dispatch_async(dispatch_get_main_queue()){
     if magicPurchased{
       //function to bring them to level 2
    }else{
      //function to bring them to level 1
      //If it's their first time making an account or if they made an account but never made it pass level 1 without buying magic this should always run i.e. Jill.
    }
   }
  }
}

LevelOneVC

LevelOneController: UIViewController{

@IBAction func buyMagic(sender: UIButton){
     self.skipLevelOne()
   }

   func skipLevelOne(){
    self.buyMagic()
    //since they bought the magic I now log it in NSUserDefaults as true
    NSUserDefaults.standardUserDefaults().setBool(true, forKey: "wasMagicBought") 
   }

 func buyMagic(){
    //code for the user to purchase the magic allows them to skip to level 2
   }
}

注册VC 注册控制器:UIViewController{

@IBAction func signUp(sender: UIButton){
     //code to sign user up
     NSUserDefaults.standardUserDefaults().setBool(false, forKey: "wasMagicBought")
   }

}

注册用户的游戏到达等级应该更新到后端API。您永远不应该依赖于在应用程序本身中维护它们。

if let gameLevel = user["gameLevel"] as? Int {  // user is a payload received from API
    // if gameLevel is 2, user should be moved to 2nd level
    // and similarly check if magicBought is true
}

在 Swift 3 中,当用户注销时,您可以从 NSUserDefaults 中删除该值或将其更改为 false

UserDefaults.standard.set(false, forKey: "wasMagicBought")
UserDefaults.standard.synchronize() // use this to save the updates immediately

UserDefaults.standard.removeObject(forKey: "MyKey")
UserDefaults.standard.synchronize()

实际上我认为这种类型的数据(购买)应该由您的后端保存。出于多种原因将它们存储在本地并不安全:其中之一是您需要在新用户登录时随时删除此密钥,这意味着您将丢失前一个的所有数据。

按照马特说的做,如果Jack会再次登录,会从1级重新开始。

您可以决定是将此数据保留在 Firebase 上,还是可以构建更复杂的数据来存储,例如以用户 ID 为键的字典

purchaseDictionary: [String: Bool] = [
    jackId: true,
    jillId: false
]

如果您决定 NSUserDefaults 方式,您应该考虑到,如果 Jack 将卸载应用程序或更改 iPhone,他将丢失任何数据。

对于遇到此问题的任何其他人 不要使用 NSUserDefaults 来保存游戏关卡。 Matt 和 Luca D'Alberti 说的都是对的。

@马特 注册用户的游戏到达等级应该更新到后端API。您永远不应该依赖于在应用程序本身中维护它们。

@Luca D'Alberti 实际上我认为这种类型的数据(购买)应该由您的后端保存。出于多种原因将它们存储在本地并不安全:其中之一是您需要在新用户登录时随时删除此密钥,这意味着您将丢失前一个的所有数据。

为其中之一投赞成票。