JSON و Core Data على iPhone



4 Answers

أردت فقط أن أشير إلى خطأ مطبعي صغير ، تسبب في تعطل الشفرة ، ونأمل أن يؤدي ذلك إلى توفير بعض الدقائق.

- (NSArray*)dataStructuresFromManagedObjects:(NSArray*)managedObjects {

    NSMutableArray *dataArray = [[NSArray alloc] init];
    for (NSManagedObject *managedObject in managedObjects) {
        [dataArray addObject:[self dataStructureFromManagedObject:managedObject]];
    }
    return [dataArray autorelease];
}

NSMutableArray *dataArray = [[NSArray alloc] init]; // This should be NSMutableArray NSMutableArray *dataArray = [[NSArray alloc] init]; // This should be NSMutableArray

يجب أن يكون NSMutableArray *dataArray = [[NSMutableArray alloc] init];

هذا كل شيء.

شكرا

iphone objective-c json core-data

لدي رسم بياني أساسي لبيانات البيانات (يتكون من كيانين مرتبطين بعلاقة متعددة الأطراف).

لقد كنت فضولياً ، كمطور مطور لجهاز iPhone لا يمتلك الخبرة الكافية ، وما إذا كان أي شخص يمكنه التوصية بنهج ، وتطبيق JSON مناسب لجهاز iPhone ، مما يسمح لي بما يلي:

  1. تحويل سجلات البيانات الأساسية إلى سلسلة JSON (مع الحفاظ على العلاقة بين الكيانات) ؛ و

  2. تحويل سلسلة JSON مرة أخرى إلى كائنات البيانات الأساسية (مرة أخرى الحفاظ على العلاقة بين الكيانات).

لقد بحثت ، دون جدوى ، عن عينة تعليمي / رمز على هذه النقطة حتى أي مساعدة سيتم تلقي بامتنان.




إذا كان لديك NSDate في الكائن المُدار ، كما هو مذكور أعلاه في أحد التعليقات ، فستواجه مشكلات في تسلسل الكائن الذي يحتوي على NSDate . إصلاح بسيط هو إضافة أسلوب JSONDataRepresentation إلى JSONDataRepresentation باستخدام الفئات JSONDataRepresentation -c.

أضف هذين الملفين إلى مشروعك:

NSdate.h:

#import <Foundation/Foundation.h>

@interface NSDate (jsondatarepresentation) 

- (NSData*) JSONDataRepresentation;

@end

NSDate.m:

#import "NSDate.h"

@implementation NSDate (jsondatarepresentation)

- (NSData*) JSONDataRepresentation {
    return [[[NSNumber numberWithDouble:[self timeIntervalSince1970]] stringValue] dataUsingEncoding:NSUTF8StringEncoding];
}

@end



جئت عبر هذا المنصب الذي يعمل بشكل جيد للغاية.

http://touchalicious.com/blog/2009/10/25/turn-core-data-models-into-json.html

وبما أن هذا الأمر تعاودي ، فستستمر العلاقات بين أطراف كثيرة في التكرار من خلال نفسها. لتجنب ذلك ، أضفت مفتاح "قابل للتقييم" إلى قاموس معلومات المستخدم للعلاقات في نموذج البيانات الأساسية. يمكنك بعد ذلك التحقق من هذا المفتاح واختيار عدم التكرار عبر العلاقات بدونه.

if ([property isKindOfClass:[NSRelationshipDescription class]])
    {
        NSRelationshipDescription *relationshipDescription = (NSRelationshipDescription *)property;

        if ([[[relationshipDescription userInfo] objectForKey:@"isExportable"] boolValue] == YES)
        {
            NSString *name = [relationshipDescription name];

            if ([relationshipDescription isToMany])
            {
                NSMutableArray *arr = [properties valueForKey:name];
                if (!arr)
                {
                    arr = [[NSMutableArray alloc] init];
                    [properties setValue:arr forKey:name];
                }

                for (NSManagedObject *o in [self mutableSetValueForKey:name])
                {
                    [arr addObject:[o propertiesDictionary]];
                }
            }
            else
            {
                NSManagedObject *o = [self valueForKey:name];
                [properties setValue:[o propertiesDictionary] forKey:name];
            }
        }
    }
}



لقد ألهمني ماركوس إس. زاررا لإحضار الفكرة المتكررة إلى نسخة عمل. في هذا الإصدار لا تحتاج إلى تعيين مفتاح في CoreData ويمكنك قصه ولصقه في مشروعك :-)

// MARK: - encoding and decoding CoreData entity to dictionary

func dataStructureFromManagedObject( managedObject:NSManagedObject?, parentEntity: NSEntityDescription? = nil) -> NSMutableDictionary {
    if (managedObject != nil) {
        var attributesByName: NSDictionary = managedObject!.entity.attributesByName
        var relationshipsByName: NSDictionary  = managedObject!.entity.relationshipsByName
        var valuesImmutableDictionary: NSDictionary = managedObject!.dictionaryWithValuesForKeys( attributesByName.allKeys)
        var valuesDictionary: NSMutableDictionary = valuesImmutableDictionary.mutableCopy() as NSMutableDictionary
        valuesDictionary.setObject( managedObject!.entity.name!, forKey: "ManagedObjectName")
        for relationshipNameObject in relationshipsByName.allKeys {
            var relationshipName: NSString = relationshipNameObject as  NSString
            var relationshipDescription: NSRelationshipDescription? = relationshipsByName.objectForKey( relationshipName) as? NSRelationshipDescription
            if !relationshipDescription!.toMany {
                // ono to one
                if parentEntity == nil || (relationshipDescription! as NSRelationshipDescription).destinationEntity != parentEntity! {
                    // no parent or relationship is "downward" -> object for relationship must be added
                    var relationshipObject: NSManagedObject? = managedObject!.valueForKey( relationshipName) as? NSManagedObject
                    var relationshipObjectDictionary: NSMutableDictionary = self.dataStructureFromManagedObject( relationshipObject, parentEntity: managedObject?.entity)
                    valuesDictionary.setObject( relationshipObjectDictionary, forKey: relationshipName)
                } else {
                    // relationship is "upward" -> nothing to do
                }
            } else {
                // one to many -> all objects must be added
                var relationshipObjects: NSSet = managedObject!.mutableSetValueForKey( relationshipName)
                var relationshipArray:NSMutableArray = []
                for relationshipObjectRaw in relationshipObjects {
                    var relationshipObject:NSManagedObject? = relationshipObjectRaw as? NSManagedObject
                    if relationshipObject != nil && !relationshipObject!.entity.isKindOfEntity( managedObject!.entity) {
                        relationshipArray.addObject(self.dataStructureFromManagedObject( relationshipObject, parentEntity: managedObject?.entity))
                    }
                }
                valuesDictionary.setObject( relationshipArray, forKey: relationshipName)
            }
        }
        return valuesDictionary
    } else {
        return NSMutableDictionary()
    }
}

func managedObjectFromStructure( structureDictionary: NSDictionary, moc: NSManagedObjectContext, parentObject: NSManagedObject? = nil) -> NSManagedObject {
    if structureDictionary.count > 0 {
        var objectName:NSString = structureDictionary.objectForKey( "ManagedObjectName") as NSString
        var managedObject:NSManagedObject = NSEntityDescription.insertNewObjectForEntityForName( objectName, inManagedObjectContext: moc) as NSManagedObject
        var relationshipsByName: NSDictionary  = managedObject.entity.relationshipsByName
        var realObjectStructure:NSMutableDictionary = structureDictionary.mutableCopy() as NSMutableDictionary
        realObjectStructure.removeObjectForKey( "ManagedObjectName")
        for key in realObjectStructure.allKeys {
            // search for "ManagedObjectName" relationship entrys and delete them before filling the managedObject from this structure
            for relationshipName in relationshipsByName.allKeys {
                if relationshipName as NSString == key as NSString {
                    realObjectStructure.removeObjectForKey( key)
                }
            }
        }
        managedObject.setValuesForKeysWithDictionary( realObjectStructure)
        // the main object with attributes is created. Now care about the relationships
        for relationshipName in managedObject.entity.relationshipsByName.keys {
            var description:NSRelationshipDescription = relationshipsByName.objectForKey( relationshipName) as NSRelationshipDescription
            if !description.toMany {
                // to one relationship
                if parentObject == nil || description.destinationEntity != parentObject!.entity {
                    // no parent or relationship is "downward" -> recurse structure to add
                    var childStructureDictionary:NSDictionary = structureDictionary.objectForKey( relationshipName) as NSDictionary
                    if childStructureDictionary.count > 0 {
                        // dictionary not empty -> object must be created and added
                        var childObject:NSManagedObject? = self.managedObjectFromStructure( childStructureDictionary, moc: moc, parentObject: managedObject)
                        // validateForUpdate
                        var error:NSError?
                        if !managedObject.validateForUpdate( &error) {
                            println("Error: Object not in valid state for update!!! -> \(error)")
                        } else {
                            managedObject.setValue( childObject, forKey: relationshipName as NSString)
                        }
                    } else {
                        // relationship is "upward" -> nothing to do
                    }
                }
            } else {
                // to many relationship
                var relationshipSet:NSMutableSet = managedObject.mutableSetValueForKey( relationshipName as NSString)
                var relationshipArray:NSArray = structureDictionary.objectForKey( relationshipName as NSString) as NSArray
                for childStructureDictionary in relationshipArray {
                    if childStructureDictionary.count > 0 {
                        // dictionary not empty -> object must be created and added
                        var childObject:NSManagedObject = self.managedObjectFromStructure( childStructureDictionary as NSDictionary, moc: moc, parentObject: managedObject)
                        // validateForUpdate
                        var error:NSError?
                        if !managedObject.validateForUpdate( &error) {
                            println( "Error: Object not in valid state for update!!! -> \(error)")
                        } else {
                            relationshipSet.addObject( childObject)
                        }
                    } else {
                        // no object was behind the relationship -> nothing to do
                    }
                }
                // save set
                managedObject.setValue( relationshipSet, forKey: relationshipName as NSString)
            }
        }
        // final check validateForUpdate
        var error:NSError?
        if !managedObject.validateForUpdate( &error) {
            println( "Error: Object not in valid state for update although all previous check are passed!!! -> \(error)")
        }
        return managedObject
    } else {
        println( "Error: structure for object was empty. this should not happen at this point")
        var objectName:NSString = structureDictionary.objectForKey( "ManagedObjectName") as NSString
        var managedObject:NSManagedObject = NSEntityDescription.insertNewObjectForEntityForName( objectName, inManagedObjectContext: moc) as NSManagedObject
        return managedObject
    }
}

func dataStructuresFromManagedObjects( managedObjects: NSArray) -> NSArray {
    var dataArray:NSMutableArray = []
    for managedObject in managedObjects {
        dataArray.addObject( self.dataStructureFromManagedObject(managedObject as? NSManagedObject))
    }
    return dataArray
}

المفتاح هنا هو تمرير الكيان الرئيسي كحجة للتكرار ، حتى نتمكن من تحديد العلاقة التي يجب أن نملأها بالبيانات. وبالتالي فإن كلا الوظيفتين: dataStructureFromManagedObject و managedObjectFromStructure يمكن ترميز وفك شفرة أي كائن كيان من CoreData إلى قاموس والعودة إلى كائن.






Related