草庐IT

swift - CoreData 创建并保存具有 nil 属性的额外实体

coder 2023-07-17 原文

我有一个联系人表和位置表,每个联系人都有很多位置

我创建一个联系人保存,然后创建一个位置并保存,然后将保存的位置分配给联系人。代码如下:

 @IBAction func saveLocation(_ sender: AnyObject) {
    let processName = ProcessInfo.processInfo.globallyUniqueString

    let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
    let location = Location(context: context)

    do {

        let fetchRequest: NSFetchRequest<Contact> = Contact.fetchRequest()
        fetchRequest.predicate = NSPredicate(format: "uniqueId == %@", contactIdentifierString)
        let fetchedResults = try context.fetch(fetchRequest)
        if let aContact = fetchedResults.first {

            // set location data
            location.uniqueId = processName
            location.locationName = locationNameTextField.text
            location.city = self.city
            location.state = self.state
            location.street = self.street
            location.zip = self.zip
            location.country = self.country


            // save data
            (UIApplication.shared.delegate as! AppDelegate).saveContext()
            location.contact = aContact
            myDelegate?.userSelectedContact(contactIdentifier: contactIdentifierString, locationIdentifier: processName)

        }
    }
    catch {
        print ("fetch task failed", error)
    }




    // Check results
    do {

        let fetchRequest: NSFetchRequest<Location> = Location.fetchRequest()
        fetchRequest.predicate = NSPredicate(format: "uniqueId == %@", processName)
        let fetchedResults = try context.fetch(fetchRequest)
        if let aLocation = fetchedResults.first {
            print("+++++==========++++++++++")
            print("Location.Contact:  \(aLocation.contact)")
            print("+++++==========++++++++++")
        }
    }
    catch {
        print ("location fetch failed")
    }

    self.navigationController!.popViewController(animated: true)
}

我只添加了一个位置,但是当我打印联系人实体时,我看到分配了两个位置,如下所示。

  Location.Contact:  Optional(<rg2nrg.Contact: 0x6000002c73f0> (entity: Contact; id: 0xd000000000240000 <x-coredata://7D46FA65-2590-409D-89E7-995F64F07483/Contact/p9> ; data: {
email = vmail;
firstName = vr;
imageName = <89504e47 0d0a1a0a 0000000d 49484452 0000012c 0000012c 08060000 00797d8e 75000000 01735247 4200aece 1ce90000 0009>;
lastName = r;
locations =     (
    "0xd000000001780002 <x-coredata://7D46FA65-2590-409D-89E7-995F64F07483/Location/p94>",
    "0xd000000001740002 <x-coredata://7D46FA65-2590-409D-89E7-995F64F07483/Location/p93>"
);
phone = 22;
providerName = tara;
screenName = vr;
uniqueId = "7B17C228-50A6-4309-BD0D-CBCD8E8FAEA1-1106-00000128477D4DB1";
userType = Household;
  }))

此外,其中一个位置实体具有正确的分配属性值,而另一个位置实体具有所有 nil 值。

这弄乱了我的程序。当我循环检查位置实体属性以删除它们时,我现在看到三个位置实体

 func deleteLocations() {
    var fetchedResults: [Location] = []

    let contextLocation = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
    do {

        fetchedResults = try contextLocation.fetch(Location.fetchRequest())
        print("number of locations to be deleted:: \(fetchedResults.count) ")

        if fetchedResults.count > 0 {

            for location in fetchedResults{
                print(location.locationName)
                contextLocation.delete(location)
                try contextLocation.save()

                print(location.locationName)
            }
        }
    } catch {
        print ("fetch contact failed")
    }

}

输出: 要删除的位置数::3

在我的代码的后面部分,当我尝试检索值时它崩溃了,因为两个额外 Location 实体的所有属性都是 nil。

我的问题: 因为我只添加了一个 Location 实体,所以应该只有一个 Location 实体,并且应该是唯一一个链接到 Contact 的实体。它显示了分配给联系人的两个位置,然后当我计数时我有三个位置。看起来带有 nil 属性的 Location 实体不断被自己添加。

我很困惑。有人可以帮忙吗?

最佳答案

您很可能在某些情况下调用了 saveLocation,其中获取失败或没有结果与谓词匹配,而 saveLocation 无法正确处理这些情况。

初始化(上下文:)

NSManagedObject 上的这个初始化程序不仅会在您调用 Location(context: context) 时在内存中创建一个空的 Location 对象,而且还会将该对象插入到您传递的托管对象上下文中。一旦 saveContext() 被调用,该 Location 对象(如果不进一步编辑,它将是空的)将被持久化。

同时 init(context:)没有很好的记录,Apple 似乎已经表明它的工作原理与 init(entity:insertInto:) 相同除了实体是自动计算出来的。

保存位置(:)

在这个函数中,你已经创建了你的 Location 对象......

let location = Location(context: context)

…在检查Contact 是否存在并设置属性之前。

if let aContact = fetchedResults.first

因此,如果碰巧抓取失败或抓取返回​​ 0 个结果,调用初始化程序时创建的空 Location 对象将保留在上下文中,以在下一次持久化任何人调用 saveContext() 的时间。

解决与预防

在这种特殊情况下,您可能会发现移动此行后您的问题将得到解决

let location = Location(context: context)

到下面的 if let block :

if let aContact = fetchedResults.first {

    // create location here, not at beginning of method
    let location = Location(context: context)

    // set location data
    location.uniqueId = processName
    location.locationName = locationNameTextField.text
    location.city = self.city
    location.state = self.state
    location.street = self.street
    location.zip = self.zip
    location.country = self.country

    // save data
    (UIApplication.shared.delegate as! AppDelegate).saveContext()
    location.contact = aContact
    myDelegate?.userSelectedContact(contactIdentifier: contactIdentifierString, locationIdentifier: processName)

}

作为在使用 Core Data 时防止此问题的一般规则,不要在任何 NSManagedObject 子类上使用 init(context:) 除非您首先执行了所有必要的检查并确定您希望立即将项目插入到上下文中。

关于swift - CoreData 创建并保存具有 nil 属性的额外实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42940274/

有关swift - CoreData 创建并保存具有 nil 属性的额外实体的更多相关文章

  1. ruby - 如何在 Ruby 中顺序创建 PI - 2

    出于纯粹的兴趣,我很好奇如何按顺序创建PI,而不是在过程结果之后生成数字,而是让数字在过程本身生成时显示。如果是这种情况,那么数字可以自行产生,我可以对以前看到的数字实现垃圾收集,从而创建一个无限系列。结果只是在Pi系列之后每秒生成一个数字。这是我通过互联网筛选的结果:这是流行的计算机友好算法,类机器算法:defarccot(x,unity)xpow=unity/xn=1sign=1sum=0loopdoterm=xpow/nbreakifterm==0sum+=sign*(xpow/n)xpow/=x*xn+=2sign=-signendsumenddefcalc_pi(digits

  2. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  3. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

  4. ruby - 使用 Vim Rails,您可以创建一个新的迁移文件并一次性打开它吗? - 2

    使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta

  5. ruby-on-rails - 如果为空或不验证数值,则使属性默认为 0 - 2

    我希望我的UserPrice模型的属性在它们为空或不验证数值时默认为0。这些属性是tax_rate、shipping_cost和price。classCreateUserPrices8,:scale=>2t.decimal:tax_rate,:precision=>8,:scale=>2t.decimal:shipping_cost,:precision=>8,:scale=>2endendend起初,我将所有3列的:default=>0放在表格中,但我不想要这样,因为它已经填充了字段,我想使用占位符。这是我的UserPrice模型:classUserPrice回答before_val

  6. ruby-on-rails - 无法使用 Rails 3.2 创建插件? - 2

    我对最新版本的Rails有疑问。我创建了一个新应用程序(railsnewMyProject),但我没有脚本/生成,只有脚本/rails,当我输入ruby./script/railsgeneratepluginmy_plugin"Couldnotfindgeneratorplugin.".你知道如何生成插件模板吗?没有这个命令可以创建插件吗?PS:我正在使用Rails3.2.1和ruby​​1.8.7[universal-darwin11.0] 最佳答案 随着Rails3.2.0的发布,插件生成器已经被移除。查看变更日志here.现在

  7. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  8. ruby - 如何使用 RSpec::Core::RakeTask 创建 RSpec Rake 任务? - 2

    如何使用RSpec::Core::RakeTask初始化RSpecRake任务?require'rspec/core/rake_task'RSpec::Core::RakeTask.newdo|t|#whatdoIputinhere?endInitialize函数记录在http://rubydoc.info/github/rspec/rspec-core/RSpec/Core/RakeTask#initialize-instance_method没有很好的记录;它只是说:-(RakeTask)initialize(*args,&task_block)AnewinstanceofRake

  9. ruby - 多个属性的 update_column 方法 - 2

    我有一个具有一些属性的模型:attr1、attr2和attr3。我需要在不执行回调和验证的情况下更新此属性。我找到了update_column方法,但我想同时更新三个属性。我需要这样的东西:update_columns({attr1:val1,attr2:val2,attr3:val3})代替update_column(attr1,val1)update_column(attr2,val2)update_column(attr3,val3) 最佳答案 您可以使用update_columns(attr1:val1,attr2:val2

  10. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

随机推荐