【问题标题】:Why is my relation-object reinitialized each time it is accessed?为什么每次访问我的关系对象时都会重新初始化它?
【发布时间】:2015-11-07 18:43:25
【问题描述】:

我使用 Realm Swift 0.95.3。在我的项目中,我正在处理一个联系人(不是联系人地址簿),其中包含有关姓名、姓氏、中间名、电子邮件……和照片的信息。

我创建了一个名为 Contact 的 Object 子类。我了解图像或任何其他二进制数据不应存储在领域中。特别是因为我的图像可能足够大〜5 Mb。

无论如何,我想将图像存储在文件系统中,而 Realm 只存储指向该图像的链接。我认为将来我可能需要将其他文件(音频、PDF 等)附加到 Object 的子类中。所以我决定创建一个单独的类File,它继承自Object。整个结构看起来像。

class File: Object {
  dynamic var objectID = NSUUID().UUIDString

  private var filePath: String {
    let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
    let documentsDirectory = paths[0] as NSString
    return documentsDirectory.stringByAppendingPathComponent(objectID)
  }

  lazy var fileData: NSData? = {
    return self.readFile()
  }()

  override static func primaryKey() -> String? {
    return "objectID"
  }

  override static func ignoredProperties() -> [String] {
    return ["fileData"]
  }

  override func copy() -> AnyObject {
    let result = File(value: self)
    result.objectID = NSUUID().UUIDString
    result.fileData = fileData?.copy() as? NSData
    return result
  }
}

extension File {
  //MARK:-
  private func readFile() -> NSData? {
    let lFilePath = filePath
    print("Try to read file \(lFilePath)")
    return NSData(contentsOfFile: lFilePath)
  }

  private func writeFileWithFileData() {
    if let lFileData = fileData {
      lFileData.writeToFile(filePath, atomically: true)
      print("File \(filePath) was created")
    } else {
      removeFile()
    }
  }

  private func removeFile() {
    do {
      try NSFileManager.defaultManager().removeItemAtPath(filePath)
      print("File \(filePath) was removed")
    } catch {
      print(error)
    }
  }
}

如您所见,当尝试获取属性fileData 时,会从文件系统接收数据。而且fileData是用关键字lazy声明的,也就是说我希望数据是从磁盘请求到这个属性中缓存的。如果这个属性改变了,File对象在保存到数据库之前,我调用writeFileWithFileData(),磁盘上的数据就被覆盖了。该系统按我的需要工作,我进行实验。然后我创建了一个联系人。

class Contact: Object {
  dynamic var objectID = NSUUID().UUIDString

  dynamic var firstName = ""
  dynamic var lastName = ""
  ...
  private dynamic var avatarFile: File?

  var avatar: UIImage? {
    get {
      guard let imageData = avatarFile?.fileData else { return nil }
      return UIImage(data: imageData)
    }

    set {
      avatarFile = File()
      guard let imageData = newValue else {
        avatarFile?.fileData = nil
        return
      }
      avatarFile?.fileData = UIImagePNGRepresentation(imageData)
    }
  }

  override static func primaryKey() -> String? {
    return "objectID"
  }

  override static func ignoredProperties() -> [String] {
    return ["image"]
  }
}

问题是当我从数据库中选择一个联系人并尝试获取头像时,每次访问此属性时都会访问文件系统。也就是说,属性 fileData 并不像我一开始想的那样懒惰。但是后来我查看了内存地址属性avatarFile,每次收到,地址都变了。由此我可以得出结论,对象 avatarFile 会不断地再次从数据库中请求,并引用此属性。结果,它的所有被忽略的属性都被重置。

  1. 为什么每次访问关系对象都会重新初始化?
  2. 分享您对我的拱门的看法

【问题讨论】:

    标签: ios database swift realm relation


    【解决方案1】:
    1. 应该没问题。领域对象是到其父领域对象的实时链接,而不是静态副本,因此它们的地址会定期更改。这是正常的,并且对象没有被重新分配,所以你不应该在这里看到任何内存问题。据我所知,NSData 本身是惰性的,因此在您明确请求之前不会真正读取数据。

    2. 您的架构看起来不错!您是对的,将文件数据直接存储在 Realm 文件中通常不是最好的形式,但是您在使 Realm Object 像管理外部文件数据一样管理外部文件数据方面做得很好。 :)

    【讨论】:

    • 感谢您的回答。我附上my project。它有 4 个方法 UserCase。您可以确定当我使用类 File(UserCase1 和 UserCase2)时是 fileData == fileData。如果你看看另外两个 UserCase 那里有 fileData! = 文件数据。这很奇怪,因为我指的是同一个对象,至少我是这么认为的。
    猜你喜欢
    • 2018-06-19
    • 2011-02-16
    • 2020-08-08
    • 1970-01-01
    • 1970-01-01
    • 2014-09-10
    • 2012-11-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多