核心数据获得相关实体

时间:2015-11-18 14:26:51

标签: ios swift core-data

我有实体ApplicationProcess,一个应用程序可以有多个进程,但一个进程只能有一个应用程序。我得到一个特定的应用程序实体:

    let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
    let managedContext = appDelegate.managedObjectContext
    let appfetchRequest = NSFetchRequest(entityName: "Application")
    //appfetchRequest.returnsObjectsAsFaults = false
    do{
        let results = try managedContext.executeFetchRequest(appfetchRequest)
        applications.addObjectsFromArray(results as! [NSMutableArray])

    }catch let error as NSError{
        print("Jakis blad z applications entity: \(error)")
    }

    let predicate:NSPredicate = NSPredicate(format: "name == %@", appTitle)

    let application:NSArray = applications.filteredArrayUsingPredicate(predicate)

并在此我有关系(名为applicationprocesses)。 我尝试以多种方式获取这些实体的数组,但没有人工作。 实际上,我有:

    let processes = application.valueForKey("applicationprocesses").allObjects.first

    print(processes?.valueForKey("applicationprocesses"))

这给了我:

Optional({(
<NSManagedObject: 0x7f945871b7a0> (entity: Application; id: 0xd000000000080002 <x-coredata://00C2FE4A-143B-436E-B39B-A0A32C300B68/Application/p2> ; data: {
appcolor = "#3F3F3F";
appicon = bed;
applabel = Proces;
applabelplural = Procesy;
applicationprocesses =     (
    "0xd000000000140004 <x-coredata://00C2FE4A-143B-436E-B39B-A0A32C300B68/Process/p5>",
    "0xd000000000100004 <x-coredata://00C2FE4A-143B-436E-B39B-A0A32C300B68/Process/p4>",
    "0xd000000000180004 <x-coredata://00C2FE4A-143B-436E-B39B-A0A32C300B68/Process/p6>",
    "0xd0000000001c0004 <x-coredata://00C2FE4A-143B-436E-B39B-A0A32C300B68/Process/p7>",
    "0xd0000000000c0004 <x-coredata://00C2FE4A-143B-436E-B39B-A0A32C300B68/Process/p3>"
);
companyid = 392;
id = 1261;
name = "aplikacja 1";
processescount = 5;
})
)})

我需要在UITablewView中显示这些进程,所以我需要一个数组。 我将不胜感激任何帮助。

2 个答案:

答案 0 :(得分:1)

您遇到的问题不是某处代码行不好的结果。它实际上正如它应该的那样工作。但是,您可以更轻松地使用NSManagedObject

从您的数据库中获取任何内容都会产生[AnyObject]。如果你保持原样,你就不得不使用键值编码,这很痛苦,很容易搞砸。

但是,从CD实体创建类并向下转换获取结果非常简单。这是CoreData的一个很棒的功能,遗憾的是它不够紧张。

link to gist

您的相关实体可能如下所示:

enter image description here

转到菜单 - &gt;编辑 - &gt;创建....

enter image description here

选择要为其创建子类的实体。

新文件将显示在您的项目中:

enter image description here

现在你可以使用这样的代码:

插入对象

注意.... as? Company这是向下倾斜。 它允许您从CD实体访问属性,就像访问Struct或Class中的任何属性一样。

func createACompany() {
    // no appDel here. appDel and managedContext are best declared in the class scope. See gist for entire ViewController
    guard let moc = managedContext else { return }

    guard let company = NSEntityDescription.insertNewObjectForEntityForName("Company", inManagedObjectContext: moc) as? Company else {
        return // guard is handy to "abort"
    }
    company.name = "Apple"

    guard let bob = NSEntityDescription.insertNewObjectForEntityForName("Employee", inManagedObjectContext: moc) as? Employee else {
        return
    }
    bob.name = "Bob"
    bob.company = company

    do {
        try moc.save()
    } catch {
        print("core data save error : \(error)")
    }

    moc.refreshAllObjects()

}

获取对象

func fetchCompanies() -> [Company] {

    guard let moc = managedContext else { return [] }
    let request = NSFetchRequest(entityName: "Company")
    request.returnsObjectsAsFaults = true

    do {
        let results = try moc.executeFetchRequest(request)

        guard let companies = results as? [Company] else {
            return []
        }

        return companies

    }catch let error as NSError{
        print("core data fetch error: \(error)")
        return []
    }

}

获取相关对象

仔细查看guard声明。

  • let employeeSet = company.employees - &gt;解开可选的NSSet
  • let employees = employeeSet.allObjects - &gt;获取NSSet
  • 中的所有对象
  • as? [Employee] - &gt;将allObjects的结果向下转换为Array Employee
func getEmployees(forCompany company : Company) -> [Employee] {

    guard let employeeSet = company.employees, let employees = employeeSet.allObjects as? [Employee] else {
        return []
    }

    return employees

}

旁注:

如果你改变了对班级命名的看法,你就会在任何地方改变它。别忘了在这里更新它:

必须更新字段。

enter image description here

与InterfaceBuilder类似。如果您更改了班级名称,将无法再找到它。

答案 1 :(得分:0)

我相信您希望让所有托管对象(进程)与您已经拥有的应用程序对象相关。我们通常使用&#34;实体&#34;与数据库中的表格相同的词语。

对不起,我没有为这行代码提供快速版本。我不确定我的快速技能

  

NSArray * processes = [[application fristObject] objectIDsForRelationshipNamed:@&#34; applicationprocesses&#34;]

然后使用API​​将objectID转换为ManagedObject

  
      
  • (__ kindof NSManagedObject *)objectWithID:(NSManagedObjectID *)objectID;
  •   

唯一的问题是这个API,(NSArray *)objectIDsForRelationshipNamed:(NSString *)密钥,仅从版本8.3支持