Swift从CoreData取字符串给UILabel赋值报实例成员错误如何解决
错误原因
你遇到的报错是由两个特性共同导致的:
- 你当前用
let定义的nameLabel属于存储型属性,它的初始化闭包会在类实例完成初始化前执行,此时实例的其他属性(比如test1)还没有完成初始化,无法被直接访问,所以触发了编译错误。 - 哪怕你解决了编译问题,这个初始化时机也有逻辑问题:你是在
viewWillAppear中才从CoreData拉取数据给test1赋值,nameLabel初始化的时候test1还是空字符串,根本拿不到拉取到的用户名。
解决方案
方案1:懒加载属性+拉取数据后手动更新(最推荐)
- 把
nameLabel从普通存储属性改成懒加载属性,懒加载属性会在第一次被访问时才初始化,此时类实例已经创建完成,可以正常访问其他实例属性:
// 把原来的let修改为lazy var lazy var nameLabel: UILabel = { let label = UILabel() label.textAlignment = .center label.font = UIFont.boldSystemFont(ofSize: 26) label.textColor = .white return label }()
- 在
viewWillAppear中拿到CoreData的用户名数据后,直接给label的text属性赋值,同时不要忘记调用父类的viewWillAppear方法:
override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Users") request.returnsObjectsAsFaults = false do { let result = try context.fetch(request) for data in result as! [NSManagedObject] { test1 = data.value(forKey: "username") as! String } // 拿到数据后直接更新label文本 nameLabel.text = test1 } catch { print("Failed") } }
方案2:给test1添加属性观察器自动同步
如果你需要test1的值每次变化时都自动更新到label上,可以使用属性观察器实现自动同步:
// 给test1添加didSet观察器 var test1 = String() { didSet { nameLabel.text = test1 } } // nameLabel同样修改为懒加载属性 lazy var nameLabel: UILabel = { let label = UILabel() label.textAlignment = .center label.font = UIFont.boldSystemFont(ofSize: 26) label.textColor = .white return label }()
优化提示:如果你本地的Users表只会存储当前登录用户的单条数据,不需要循环遍历result,直接取
result.first取值即可,避免多条数据时test1被最后一条数据覆盖。
内容的提问来源于stack exchange,提问作者Billy
相关产品推荐
相关产品推荐

