【问题标题】:Realm write transaction freezes the screen swift领域写入事务迅速冻结屏幕
【发布时间】:2020-07-17 07:58:07
【问题描述】:

我正在开发一个应用程序,我必须在本地保存图像,并且为此使用领域,该应用程序一次从图库中获取 10 到 40 张图像,然后开始将图像写入领域本地数据库并冻结写入过程中的屏幕,请如何修改我的代码,以便我的应用程序不会在写入事务期间冻结,我陷入这种情况,任何帮助将不胜感激,谢谢

let imagesAdd = refObject.1
let imageobjectArray = modelObject as! [FacilitiesImagesModel]
do{
    for imageObject in imageobjectArray{
         try realmObj.write {
              imagesAdd?.facilitiesImages.append(imageObject)
             }
     }

     completionHandler(true, "")

 }catch let err{
      realmObj.cancelWrite()
      completionHandler(false, err.localizedDescription)
 }

这是我的完整方法,我删除了不属于我的问题的额外代码

struct RealmCRUD {

private let realmObj = try! Realm()

func create<T>(modelObject: T, modelObjectType: ModelType, refObject: (PropertyModel?, FacilitiesModel?), completionHandler: @escaping ((Bool, String) -> Void)){

    switch modelObjectType {



    case .FacilitiesImagesModel:
        let imagesAdd = refObject.1
        let imageobjectArray = modelObject as! [FacilitiesImagesModel]
        do{
            for imageObject in imageobjectArray{
                try realmObj.write {
                    imagesAdd?.facilitiesImages.append(imageObject)
                    }
            }

            completionHandler(true, "")

        }catch let err{
            realmObj.cancelWrite()
            completionHandler(false, err.localizedDescription)
        }
        break
    }

    default:
    break
}

我正在像这样从其他类调用此方法:

func dismissComplete() {

    var arrayOfFacilitiesImagesModelObj = [FacilitiesImagesModel]()

    for photos in self.selectedAssets{

        if let photo = photos.fullResolutionImage{
            let facilitiesImagesModelObj = FacilitiesImagesModel()
            facilitiesImagesModelObj.facilityPhoto = photo.jpegData(compressionQuality: 0.5)!
            arrayOfFacilitiesImagesModelObj.append(facilitiesImagesModelObj)
        }else{
            print("Unable to select facility photos")
        }

    }

    self.realmCrudObj.create(modelObject: arrayOfFacilitiesImagesModelObj, modelObjectType: .FacilitiesImagesModel, refObject: (nil,self.realmFacilitiesResults), completionHandler: { (success, error)  in

        self.collectionViewReference?.reloadData()

        ProgressHUD.dismiss()

        if !success{
            self.showAlert(title: "Error", description: error)
        }
        })
}

我正在将选定的属性数据传递给此类中的此变量

    var realmFacilitiesResults: FacilitiesModel?

这是我的设施模型

class FacilitiesModel: Object {

@objc dynamic var facilityName = ""

let facilitiesImages = List<FacilitiesImagesModel>()

let parentProperty = LinkingObjects(fromType: PropertyModel.self, property: "facilities")

}

【问题讨论】:

  • 如果您要共享更多代码会很有帮助。您应该显示足够的代码,以便我们知道您的所有变量和属性是什么。也许也分享您的模型对象定义。什么是模型对象?什么是 refObject?等等。
  • 在我们抛出一些随机解决方案之前,需要更多信息。您的问题指出,在编写 10 张图像时 UI 会冻结 - 这些图像有多大(Gb 明智)?此外,正如@Rob 提到的,我们需要查看您的 Realm 模型以准确了解您的代码在做什么。
  • 我已经编辑了我的问题,请检查
  • @Jay 没有从相机拍摄的正常图像
  • 这很模糊。 “正常图像”?我有一个 2 兆像素的相机,而你有一个 20 兆像素的相机——哪一个是“正常的”?我问这些图像的大小可以在您如何写入数据以及如何写入数据方面发挥重要作用。

标签: swift iphone xcode ipad realm


【解决方案1】:

您的部分问题是您正在执行多个领域写入。您应该为所有对象执行一个领域写入。

do {
    let realm = try Realm()
    try realm.write {
        imagesAdd?.facilitiesImages.append(objectsIn: imageobjectArray)
        completionHandler(true, "")
    } catch {
        print("realm write error: \(error)")
        completionHandler(false, "")
    }
}

如果这仍然不能为您加快速度,那么您应该在后台线程中将您的对象添加到领域。但是因为您将在一个新线程中操作,所以您必须获得线程安全的引用。

let imageObjectsRefArray = imageObjectsArray.map { ThreadSafeReference(to: $0) }
let imagesAddRef = ThreadSafeReference(to: imagesAdd)
let queue = DispatchQueue(label: "realm.image.add")
queue.async {
    do {
        let realm = try Realm()
        guard let imagesAdd = realm.resolve(imagesAddRef) else {
            completionHandler(false, "")
            return
        }
        let imageObjectsArray = imageObjectsRefArray.compactMap { realm.resolve($0) }
        try realm.write {
            imagesAdd.facilitiesImages.append(objectsIn: imageObjectsArray)
        }
        completionHandler(true, "")
    } catch {
        print("realm write error: \(error)")
        completionHandler(false, "")
    }
}

【讨论】:

  • 感谢您的回答,现在它说:Argument type 'FacilitiesModel?'不符合预期的类型“ThreadConfined”。这是我的模型: class FacilitiesModel: Object { @objc dynamic var facilityName = "" let facilityImages = List() let parentProperty = LinkingObjects(fromType: PropertyModel.self, property: "facilities") } 我正在创建变量像这样:var realmFacilitiesResults: FacilitiesModel?
  • @UmairKhan 嗯,它可能在抱怨您的参考是可选的。
  • 兄弟崩溃错误:由于未捕获异常'RLMException'而终止应用程序,原因:'无法构造对非托管对象的引用,可以直接跨线程传递'
  • @UmairKhan 啊!我假设您的对象已经存储在领域中,并且您只是在建立关系。如果您的对象未存储在领域中,那么您不需要线程安全引用。您可以跨不同的线程访问它们。
  • 哪些对象没有被管理?当我有更多信息时,我会更新我的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多