当前位置: 首页 > 知识库问答 >
问题:

正在保存对象以便在任何地方都可以访问

曾河
2023-03-14

这里我有一个条件,假设一个用户通过调用API登录。并且响应包含用户的详细信息。我们是否可以将用户的详细信息保存为一个对象,并且可以全局访问?下面是我如何使用ObjectMapper调用模型类的api:

import ObjectMapper

class User: Mappable {

var id: Int?
var userId: Int?
var orgId: Int?
var type: Int?
var email: String?
var lang: String?
var nickname: String?
var status: Int?
var token: String?

required init(map: Map) {
    mapping(map: map)
}

func mapping(map: Map) {
    id <- map["id"]
    userId <- map["userId"]
    orgId <- map["orgId"]
    type <- map["type"]
    failedAttempt <- map["failedAttempt"]
    email <- map["email"]
    lang <- map["lang"]
    nickname <- map["nickname"]
    status <- map["status"]
    token <- map["token"]
}

}

从我的社交档案来看,

    func postLogin(params: [String: Any], controller: UIViewController, completion: @escaping (User) -> Void) {
    alamofire("/login", method: .post, token: false, params: params, controller: controller) { result in
        if let userDetails = Mapper<User>().map(JSON: result as! [String: Any]) {
            DispatchQueue.main.async {
                completion(userDetails)
            }
        }
    }
}

有些解决方案可能使用UserDefaults,但是使用9个UserDefaults来保存我们从这个响应中得到的9个键是不实际的。有什么建议的方法,我们可以这样做,当用户登录,我们保存这些细节作为一个对象全局,甚至当关闭应用程序后,细节没有重新设置?谢谢大家

共有2个答案

沈枫涟
2023-03-14

你必须问问自己,你想如何从应用程序中的不同地方使用编译器自动完成来访问这个对象。其次,物体的寿命是多少?在登录/注销、应用程序会话或应用程序生命周期期间,对象应该是可访问的?

让我们从对象寿命开始。

  • 登录/注销,对象可以存储在内存中
  • 应用程序会话,对象可以存储在内存中
  • 应用程序安装/删除时,对象应存储在UserDefaults、数据库或文件中。

自动完成驱动的开发也称为添加:

决定在何处存储userDetails对象以及如何访问它

假设您在视图控制器中有一个逻辑,它在ViewDidLoad中定义的初始配置中隐藏或取消隐藏视图。编写一些原型代码来决定您希望如何从应用程序的不同位置访问“用户详细信息”对象。

func viewDidLoad() {
   super.viewDidLoad()

   if userDetails.status {
     //userDetails is a global instance of a user object
   }

   if session.userDetails.status {
     //session is a global instance of a Session object which has a property which stores a User instance in userDetails
   }

   if Session.current.userDetails.status {
     // Session is a type and 'current' is a singleton of that type which has a userDetails property which stores an instance of User type
   }

   if User.userDetails.status {
     // User is your type which can have a static property 'userDetails' which stores a User instance
   }

}
司英彦
2023-03-14

我同意在userdefaults中保存9个单独的键是不实际的。但是为什么不将整个代码编码为JSON并保存生成的数据呢?

extension User: Codable { }

// Assuming user is an instance of User
guard let userJSON = try? JSONEncoder().encode(user) else {
    // handle encoding failure
}

let userDefaultsKeyForUser = "com.yourdomain.snazzyapp.userInfo"

UserDefaults.standard.set(userJSON, forKey: userDefaultsKeyForUser)

我认为Swift会自动为您的user类合成codable一致性,但您可能需要使其成为final。或者显式实现codable

取回它

guard let userJSON = UserDefaults.standard.data(forKey: userDefaultsKeyForUser) else {
    // Handle missing data (first run maybe?)
}

guard let user = try? JSONDecoder().decode(User.self, from: userJSON) else {
   // Handle decoding failure
} 

虽然符合codable是实现这一目标的首选方法,但这有时会给类带来问题,特别是在涉及继承的情况下。特别是codableencodabledecodable的组合。decodable有时是类的一个问题。这个问题与必需的init(from Decoder:Decoder)throws必须在类中直接声明而不是在扩展中声明有关,然后您可能会在对超级进行编码时遇到麻烦。如果您的类是基本的class,这应该不是问题。这主要是您从AppKit/UIKit类继承时的问题。

如果由于某种原因,user不符合codable,则可以改用nscoding。它的工作方式有点不同。

在最坏的情况下,您可以实现手动将每个属性显式编码/解码为数据的方法。您甚至可以将它们存储为二进制,但您可能需要对字符串进行存储字节计数,这样您就可以知道每个字符串的起点和终点,并且您还需要想出一个方案来指示它们在编码中何时为nil。它不像JSON那么灵活,这就是为什么它是最后的手段...虽然我会注意到它要快得多。这对user类没有多大关系,但我编写了一个神经网络库,希望在训练期间在检查点保存模型,这意味着对许多层非常大的矩阵进行编码。数以百万计的参数。使用我自己的二进制编码读写模型比让codable处理它快20倍左右,即使我使用codable将其保存为二进制plist

第三种选择是重新处理user类。或者将其设置为结构,或者在内部使用结构存储其属性,并使用计算属性在中获取和设置它们。类的所有属性都已经符合codable,因此Swift完全可以将structcodable一致性与这些属性综合起来。如果您仍然将结构包装在中,那么您只需要一个初始值设定器,它接受数据并执行与上面所示相同的解码,以设置包装的结构和一个encode方法(甚至是计算的var),它对结构进行编码,并返回数据

我不认为你会需要这些替代的解决方案,但我提到它们只是为了以防万一我错了,并且因为它们对于将来的情况是有用的。

 类似资料:
  • 我正在构建一个java国际象棋游戏,并试图构建它的GUI部分。GUI板是完整的,我可以在板上设置碎片。我不是简单地将图像设置为块,而是希望能够设置一个接受颜色和图像的Rook类的新实例化。我需要JLabel块来完成这一操作,因此在后面的代码中,我可以添加一些方法,使Rook遵守turn-take和move规则。 据我所知,JLabel只能保存图像或文本,因此我认为这可能是不可能的。如有任何帮助,我

  • 问题内容: 在我从事的一个项目中,我有几个不同的过程。我一直在代码编辑器中为该特定过程打开和关闭选项卡(java文件)。每个进程几乎总是使用相同的Java文件。 我想知道是否可以将打开的文件保存为工作集的一部分,以便我可以选择所需的工作集并打开需要使用的所有Java文件。当前,工作集只是将树设置为这些文件,但是我希望它也能打开我需要的文件。 我希望这是有道理的… 问题答案: Mylyn应该是您的答

  • 问题内容: 我的应用程序中有两个表。左表就像一个列表。单击左表将打开一个右表,其中包含基于我单击左表的字段的值。 现在的问题是,如果我在右表中编辑一个单元格,而不按Enter键并单击左表中的新项目,则所有表中的特定单元格都处于可编辑模式。以及所有表格的单元格值。 我该如何解决这个问题? 问题答案: 不能完全肯定,我明白你的感受VS你所期望的,但表的默认行为是有点出乎意料的是,当焦点转到表外的某个地

  • 问题内容: 使用SQL Server,如何分割字符串以便可以访问项x? 取一个字符串“ Hello John Smith”。如何将字符串按空格分割并访问索引1处的项,该项应返回“ John”? 问题答案: 您可能会发现 SQL用户定义函数中解析带分隔符的字符串 的解决方案 很有 用(来自The Code Project)。 您可以使用以下简单逻辑:

  • MainActivity.class MainActivity中的

  • 我安装了android studio,但是当我一启动它,一个错误就出现了 请提供android sdk的路径。 我搜索了它,但一次又一次地被重定向到IDE下载页面,但那里没有sdk。 早期的androidstudio包是在同一个链接中提供的,但现在,这个链接中似乎只有ide 我已经尝试从其他资源获得sdk,但再次,没有运气。