使用 Restkit 通过外键连接一对多
Connect one-to-many by foreign key using Restkit
我有这些型号:
extension Notification {
@NSManaged var pk: NSNumber?
@NSManaged var subtitle: String?
@NSManaged var title: String?
@NSManaged var user: User?
}
extension User {
// here's some attributes
@NSManaged var pk: NSNumber?
@NSManaged var notifications: NSSet?
// and here's really some more..
}
列出用户通知的响应可能如下所示:
[
{
"pk": 2,
"title": "Hi mate",
"subtitle": "O hoy",
"user": 2
}
]
"user": 2
表示属于pk=2的用户。
如何正确地将此通知映射到用户?我的尝试是:
let mapping = RKEntityMapping(forEntityForName: String(Notification), inManagedObjectStore: RKObjectManager.sharedManager().managedObjectStore)
mapping.identificationAttributes = [ "pk" ]
mapping.addAttributeMappingsFromDictionary([
"pk": "pk",
"title": "title",
"subtitle": "subtitle",
])
mapping.addConnectionForRelationship("user", connectedBy: [
"user.pk": "pk"
])
我能做到
mapping.addConnectionForRelationship("user", connectedBy: [
"pk"
])
但随后它将其连接到与 Notification
.
具有相同 pk 的用户
我得到的错误是:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Cannot connect relationship: invalid attributes given for source entity 'Notification': user.pk'
我怎样才能做到这一点?
我是否被迫在通知中添加临时 属性 用户,然后将 userPk 映射到 pk?
编辑:
我现在已经使用瞬态属性让它工作了,这是唯一的方法吗?
mapping.identificationAttributes = [ "pk" ]
mapping.addAttributeMappingsFromDictionary([
"pk": "pk",
"title": "title",
"subtitle": "subtitle",
"user": "userPk"
])
mapping.addConnectionForRelationship("user", connectedBy: [
"userPk": "pk"
])
userPk 现在是 Notification
上的 属性 瞬态
只要你只得到用户的ID,是的,你需要使用方法addConnectionForRelationship
和一个瞬态属性。但是,如果您的后端将为您提供用户对象而不是 ID,您可以在 RKEntityMapping
上使用 addPropertyMapping
方法。然后我会建议一个类似于这样的模式:
import Foundation
import CoreData
import RestKit
protocol Mappable {
static var entityName: String {get}
static var identityAttribute: String? {get}
static func mapping(managedObjectStore: RKManagedObjectStore) -> RKEntityMapping
static func identificationAttributes() -> [String]?
static func createPropertyMappings(managedObjectStore: RKManagedObjectStore, objectMapping: RKObjectMapping) -> [RKRelationshipMapping]?
static func attributesDictionary() -> Dictionary<String, String>?
static func requestDescriptor(managedObjectStore: RKManagedObjectStore) -> RKRequestDescriptor
}
class ManagedObject: NSManagedObject, Mappable {
//MARK: - ManagedObjectProtocol Methods
class func mapping(managedObjectStore: RKManagedObjectStore) -> RKEntityMapping {
let mapping = RKEntityMapping(
forEntityForName: entityName,
inManagedObjectStore: managedObjectStore
)
if let identityAttribute = identityAttribute {
mapping.identificationAttributes = [identityAttribute]
}
if let attributeMapping = attributes {
mapping.addAttributeMappingsFromDictionary(attributeMapping)
}
if let propertyMappings = createPropertyMappings(managedObjectStore, objectMapping: mapping) {
for propertyMapping in propertyMappings {
mapping.addPropertyMapping(propertyMapping)
}
}
return mapping
}
class var entityName: String {
fatalError("must override")
}
class var identityAttribute: String? {
//override me
return nil
}
class func attributesDictionary() -> Dictionary<String, String>? {
//override me
return nil
}
class func createPropertyMappings(managedObjectStore: RKManagedObjectStore, objectMapping: RKObjectMapping) -> [RKRelationshipMapping]? {
//override me if needed
return nil
}
class func requestDescriptor(managedObjectStore: RKManagedObjectStore) -> RKRequestDescriptor {
let inversedMapping = mapping(managedObjectStore).inverseMapping()
let descriptor = RKRequestDescriptor(mapping: inversedMapping, objectClass: self, rootKeyPath: nil, method: RKRequestMethod.Any)
return descriptor
}
}
class Notification: ManagedObject {
//MARK: - ManagedObjectProtocol Methods
class var entityName: String {
return "Notification"
}
override class func attributesDictionary() -> Dictionary<String, String>? {
let dictionary = [
"pk": "pk",
"title": "title",
"subtitle": "subtitle"
]
return dictionary
}
override class func createPropertyMappings(managedObjectStore: RKManagedObjectStore, objectMapping: RKObjectMapping) -> [RKRelationshipMapping]? {
let bookmarksPropertyMapping = RKRelationshipMapping(
fromKeyPath: "user",
toKeyPath: "user",
withMapping: User.mapping(managedObjectStore)
)
return [bookmarksPropertyMapping]
}
}
class User: ManagedObject {
//MARK: - ManagedObjectProtocol Methods
class var entityName: String {
return "User"
}
override class func attributesDictionary() -> Dictionary<String, String>? {
let dictionary = [
"pk": "pk"
]
return dictionary
}
}
我有这些型号:
extension Notification {
@NSManaged var pk: NSNumber?
@NSManaged var subtitle: String?
@NSManaged var title: String?
@NSManaged var user: User?
}
extension User {
// here's some attributes
@NSManaged var pk: NSNumber?
@NSManaged var notifications: NSSet?
// and here's really some more..
}
列出用户通知的响应可能如下所示:
[
{
"pk": 2,
"title": "Hi mate",
"subtitle": "O hoy",
"user": 2
}
]
"user": 2
表示属于pk=2的用户。
如何正确地将此通知映射到用户?我的尝试是:
let mapping = RKEntityMapping(forEntityForName: String(Notification), inManagedObjectStore: RKObjectManager.sharedManager().managedObjectStore)
mapping.identificationAttributes = [ "pk" ]
mapping.addAttributeMappingsFromDictionary([
"pk": "pk",
"title": "title",
"subtitle": "subtitle",
])
mapping.addConnectionForRelationship("user", connectedBy: [
"user.pk": "pk"
])
我能做到
mapping.addConnectionForRelationship("user", connectedBy: [
"pk"
])
但随后它将其连接到与 Notification
.
我得到的错误是:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Cannot connect relationship: invalid attributes given for source entity 'Notification': user.pk'
我怎样才能做到这一点?
我是否被迫在通知中添加临时 属性 用户,然后将 userPk 映射到 pk?
编辑: 我现在已经使用瞬态属性让它工作了,这是唯一的方法吗?
mapping.identificationAttributes = [ "pk" ]
mapping.addAttributeMappingsFromDictionary([
"pk": "pk",
"title": "title",
"subtitle": "subtitle",
"user": "userPk"
])
mapping.addConnectionForRelationship("user", connectedBy: [
"userPk": "pk"
])
userPk 现在是 Notification
只要你只得到用户的ID,是的,你需要使用方法addConnectionForRelationship
和一个瞬态属性。但是,如果您的后端将为您提供用户对象而不是 ID,您可以在 RKEntityMapping
上使用 addPropertyMapping
方法。然后我会建议一个类似于这样的模式:
import Foundation
import CoreData
import RestKit
protocol Mappable {
static var entityName: String {get}
static var identityAttribute: String? {get}
static func mapping(managedObjectStore: RKManagedObjectStore) -> RKEntityMapping
static func identificationAttributes() -> [String]?
static func createPropertyMappings(managedObjectStore: RKManagedObjectStore, objectMapping: RKObjectMapping) -> [RKRelationshipMapping]?
static func attributesDictionary() -> Dictionary<String, String>?
static func requestDescriptor(managedObjectStore: RKManagedObjectStore) -> RKRequestDescriptor
}
class ManagedObject: NSManagedObject, Mappable {
//MARK: - ManagedObjectProtocol Methods
class func mapping(managedObjectStore: RKManagedObjectStore) -> RKEntityMapping {
let mapping = RKEntityMapping(
forEntityForName: entityName,
inManagedObjectStore: managedObjectStore
)
if let identityAttribute = identityAttribute {
mapping.identificationAttributes = [identityAttribute]
}
if let attributeMapping = attributes {
mapping.addAttributeMappingsFromDictionary(attributeMapping)
}
if let propertyMappings = createPropertyMappings(managedObjectStore, objectMapping: mapping) {
for propertyMapping in propertyMappings {
mapping.addPropertyMapping(propertyMapping)
}
}
return mapping
}
class var entityName: String {
fatalError("must override")
}
class var identityAttribute: String? {
//override me
return nil
}
class func attributesDictionary() -> Dictionary<String, String>? {
//override me
return nil
}
class func createPropertyMappings(managedObjectStore: RKManagedObjectStore, objectMapping: RKObjectMapping) -> [RKRelationshipMapping]? {
//override me if needed
return nil
}
class func requestDescriptor(managedObjectStore: RKManagedObjectStore) -> RKRequestDescriptor {
let inversedMapping = mapping(managedObjectStore).inverseMapping()
let descriptor = RKRequestDescriptor(mapping: inversedMapping, objectClass: self, rootKeyPath: nil, method: RKRequestMethod.Any)
return descriptor
}
}
class Notification: ManagedObject {
//MARK: - ManagedObjectProtocol Methods
class var entityName: String {
return "Notification"
}
override class func attributesDictionary() -> Dictionary<String, String>? {
let dictionary = [
"pk": "pk",
"title": "title",
"subtitle": "subtitle"
]
return dictionary
}
override class func createPropertyMappings(managedObjectStore: RKManagedObjectStore, objectMapping: RKObjectMapping) -> [RKRelationshipMapping]? {
let bookmarksPropertyMapping = RKRelationshipMapping(
fromKeyPath: "user",
toKeyPath: "user",
withMapping: User.mapping(managedObjectStore)
)
return [bookmarksPropertyMapping]
}
}
class User: ManagedObject {
//MARK: - ManagedObjectProtocol Methods
class var entityName: String {
return "User"
}
override class func attributesDictionary() -> Dictionary<String, String>? {
let dictionary = [
"pk": "pk"
]
return dictionary
}
}