سؤال

أحاول تحليل XML الذي أحصل عليه من خدمة ويب مع NSXMLParserDelegate. ال NSObject أريد وضع البيانات في (سأسميها فقط MyObject) لديها @propertyS التي ليست NSStringS (هناك بعض NSDateق ، بعض NSNumberS ، وربما في مرحلة ما في المستقبل بعض البدائيات).

نظرًا لأن XML عبارة [myObject setValue:currentElementValue forKey:elementName]; في parser:didEndElement:..., ، وهو ما يعمل بشكل جيد - متى key هو NSString). لم أكن أتوقع حقًا أن يعمل هذا ، لكنني اعتقدت أن الأمر يستحق اللقطة.

أسهل شيء يجب فعله هو مجرد ترميز كل ذلك ، لذلك إذا كان لدي "property (nonatomic ، قوي) nsnumber *age ؛" على كائني ، عندما أجد <age>25</age> جزء من XML الخاص بي ، أفعل MyObject.age = [NSNumber numberWithInt:[currentElementValue intValue]];. المشكلة في هذا هي أنها جامدة للغاية - أود أن يكون هذا الرمز أكثر ديناميكية من ذلك. لا أريد أن أعرف ما هي جميع خصائص كائني في وقت مبكر.

لقد حاولت أيضًا التحقق من ما class من الممتلكات ، ثم القيام ببعض التحويل قبل إدخال قيمة (لذلك شيء مثل [myObject setValue:[NSNumber numberWithInt:[currentElementValue intValue] forKey:elementName]; إذا كان العقار isKindOfClass:[NSNumber class]]. المشكلة في ذلك هي أن هذه هي المرة الأولى التي يتم فيها استخدام الخاصية ، لذلك هي كذلك nil, ، وبالتالي ليس لديه فئة. لذلك هذا النهج لا يعمل حقا أيضا.

هل أفعل هذا خطأً تمامًا؟ يبدو أنه يجب أن يكون نموذجيًا إلى حد ما للحصول على بيانات من XML ووضعها في غيرNSString المتغيرات ، لكن لا يبدو لي أن نجعلها تعمل.

إذا احتاج أي شخص إلى رؤية المزيد من التعليمات البرمجية للحصول على فهم أفضل لكيفية إعداد هذا أو ما جربته بالفعل ، فأخبرني بذلك.


تحرير: لقد توصلت إلى مثال سريع على ما أحاول القيام به. افترض أن لدي XML التالي:

<Object>
    <ITEM_NUMBER>4</ITEM_NUMBER>
    <IS_AWESOME>YES</IS_AWESOME>
    <AWESOMENESS>9000.1</AWESOMENESS>
</Object>

أنني أريد التحليل في حالة من MyObjectNSObject فئة فرعية)

@interface MyObject: NSObject

@property (nonatomic, assign) int ITEM_NUMBER;
@property (nonatomic, assign) BOOL IS_AWESOME;
@property (nonatomic, assign) float AWESOMENESS;

@end

و XML ثانية

<OtherObject>
    <PRICE>4.99</PRICE>
    <QUANTITY>5</QUANTITY>
    <FOR_RESALE>NO</FOR_RESALE>
</OtherObject>

سوف يذهب إلى مثال OtherObject (ايضا NSObject فئة فرعية)

@interface OtherObject: NSObject

@property (nonatomic, assign) int QUANTITY;
@property (nonatomic, assign) BOOL FOR_RESALE;
@property (nonatomic, assign) float PRICE;

@end

أريد إنشاء محلل "قالب" (الذي لديه @property (nonatomic, strong) NSObject *instance; وثم NSMutableString *currentElementValue كإيفار)

...
- (void) parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
    [currentElementValue setString:string];
}

- (void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
    if ([[self.instance valueForKey:elementName] isKindOfClass:int])
    {
        [self.instance setValue:[currentElementValue intValue] forKey:elementName];
    }
    else if ([[self.instance valueForKey:elementName] isKindOfClass:float])
    {
        [self.instance setValue:[currentElementValue floatValue] forKey:elementName];
    }
    else if ([[self.instance valueForKey:elementName] isKindOfClass:BOOL])
    {
        [self.instance setValue:[currentElementValue boolValue] forKey:elementName];
    }
    else if ...
}
...

ثم ، أنا فقط فئة فرعية محلل "القالب" لكل من XMLs المختلفة والكتابة فوق init الطريقة بحيث

self.instance = [[MyObject alloc] init];

أو

self.instance = [[OtherObject alloc] init];

حسب الاقتضاء. لدي الكثير من خدمات الويب التي أدعوها والتي سأحصل عليها منظمة XML منظمة بشكل مشابه ، لذلك فقط الاضطرار إلى تغيير سطر واحد في محلات كل من كل شيء مرغوب فيه للغاية. إن وجود كل رمز المحلل في فئة "قالب" واحد سيجعل الحفاظ على الكود والقراءة وتصحيح الأخطاء أسهل بكثير.

من الواضح أن المشكلة التي أواجهها isKindOfClass لا يقبل int, float, ، أو BOOL كما المدخلات. هل هناك أي شيء مشابه يمكنني استخدامه بدلاً من ذلك؟

هل كانت مفيدة؟

المحلول

المشكلة في ذلك هي أن هذه هي المرة الأولى التي يتم فيها استخدام الخاصية ، لذلك فهي لا تحتوي على فئة.

الهدف-C يسمح بذلك خصائص فئة الاستعلام في وقت التشغيل, ، لذا فإن إدخال نوع الخاصية واستخدام الشكل المناسب هو طريقة واحدة للذهاب.

يمكنك قراءة المزيد عن وقت التشغيل في مدونة مايك آش أو انظر الهدف C الاستبطان/الانعكاس.

لكن، واجهت هذه المشكلة المحددة من قبل العديد من الأشخاص الآخرين, ، لذلك هناك عدد غير قليل من الحلول: كما قيل في iOS معظم مكتبة خدمة الراحة الناضجة Restkit هو أحد الأمثلة الجيدة على مثل هذه المكتبة ؛ MagicRecord هو آخر.

يمكنك بسهولة العثور على مزيد من المكتبات للتحقق منها قبل أن تقرر تنفيذ الحل الخاص بك.

نصائح أخرى

بالطبع يمكنني فقط تجاوز init طريقة MyObject لتخصيص جميع خصائصي لتفريغ القيم ، والتي يجب أن تحل nil المشكلة التي أشرت إليها في OP الخاص بي ، لكن هذا يشعر بالاختراق حقًا. قد يكون الخيار الوحيد رغم ذلك.


تحرير: هذا النهج ينهار تمامًا مع المثال في التحرير في البروتوكول الاختياري. سوف KVC يتحول intس، floatرمل BOOLكل شيء ل NSNumberS ، دون أي طريقة لمعرفة ما هم في الأصل أين. مما يعني أنني لن أتمكن من الاتصال [currentElementValue intValue], [currentElementValue floatValue], ، أو [currentElementValue boolValue] حسب الاقتضاء.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top