Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Finished parsing code with YAJL: status, message, user and misc resul…

…t sets are now instantiated as arrays of dictionaries.
  • Loading branch information...
commit ff9733ac39f2a210815c32a355e8ef3cd5c1624f 1 parent a40780d
Craig Hockenberry authored
View
1  MGTwitterEngine.m
@@ -882,6 +882,7 @@ - (NSString *)getRateLimitStatus
}
+// TODO: this API is deprecated, change to account/update_profile
- (NSString *)setLocation:(NSString *)location
{
if (!location) {
View
9 MGTwitterEngineGlobalHeader.h
@@ -18,13 +18,20 @@
#endif
/*
- Set this if the YAJL JSON parser is available. More information about this parser here:
+ Set YAJL_AVAILABLE to 1 if the YAJL JSON parser is available and you'd like MGTwitterEngine to use it.
+
+ More information about this parser here:
http://lloydforge.org/projects/yajl/
There are some speed advantages to using JSON instead of XML. Also, the Twitter Search API
uses JSON, so adding this library to your project makes additional methods available to your
application.
+
+ Be aware, however, that the data types in the dictionaries returned by JSON may be different
+ than the ones returned by XML. There is more type information in a JSON stream, so you may find
+ that you get an NSNumber value instead of an NSString value for some keys in the dictionary.
+ Make sure to test the new result sets in your application after switching from XML to JSON.
*/
#define YAJL_AVAILABLE 0
View
4 MGTwitterMessagesYAJLParser.h
@@ -12,6 +12,10 @@
@interface MGTwitterMessagesYAJLParser : MGTwitterYAJLParser {
+ NSMutableDictionary *_status;
+ NSMutableDictionary *_sender;
+ NSMutableDictionary *_recipient;
+
}
@end
View
169 MGTwitterMessagesYAJLParser.m
@@ -8,110 +8,99 @@
#import "MGTwitterMessagesYAJLParser.h"
+#define DEBUG_PARSING 0
@implementation MGTwitterMessagesYAJLParser
-/*
-- (NSDictionary *)_directMessageDictionaryForNodeWithName:(const xmlChar *)parentNodeName {
- if (xmlTextReaderIsEmptyElement(_reader))
- return nil;
- NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
-
- int readerResult = xmlTextReaderRead(_reader);
- if (readerResult != 1)
- return nil;
- int nodeType = xmlTextReaderNodeType(_reader);
- const xmlChar *name = xmlTextReaderConstName(_reader);
- while (! (nodeType == XML_READER_TYPE_END_ELEMENT && xmlStrEqual(parentNodeName, name)))
+- (void)addValue:(id)value forKey:(NSString *)key
+{
+ if (_sender)
{
- if (nodeType == XML_READER_TYPE_ELEMENT)
- {
- if (xmlStrEqual(name, BAD_CAST "sender") || xmlStrEqual(name, BAD_CAST "recipient"))
- {
- // "user" is the name of a sub-dictionary in each <status> item
- [dictionary setObject:[self _userDictionaryForNodeWithName:name] forKey:[NSString stringWithUTF8String:(const char *)name]];
- }
- else if (xmlStrEqual(name, BAD_CAST "id") || xmlStrEqual(name, BAD_CAST "sender_id") || xmlStrEqual(name, BAD_CAST "recipient_id"))
- {
- // process element as an integer
- NSNumber *number = [self _nodeValueAsInt];
- if (number)
- {
- [dictionary setObject:number forKey:[NSString stringWithUTF8String:(const char *)name]];
- }
- }
- else if (xmlStrEqual(name, BAD_CAST "created_at"))
- {
- // process element as a date
- NSDate *date = [self _nodeValueAsDate];
- if (date)
- {
- [dictionary setObject:date forKey:[NSString stringWithUTF8String:(const char *)name]];
- }
- }
- else if (xmlStrEqual(name, BAD_CAST "protected"))
- {
- // process element as a boolean
- NSNumber *number = [self _nodeValueAsBool];
- if (number)
- {
- [dictionary setObject:number forKey:[NSString stringWithUTF8String:(const char *)name]];
- }
- }
- else
- {
- // process element as a string
- NSString *string = [self _nodeValueAsString];
- if (string)
- {
- [dictionary setObject:string forKey:[NSString stringWithUTF8String:(const char *)name]];
- }
- }
- }
-
- // advance reader
- int readerResult = xmlTextReaderRead(_reader);
- if (readerResult != 1)
- break;
- nodeType = xmlTextReaderNodeType(_reader);
- name = xmlTextReaderConstName(_reader);
+ [_sender setObject:value forKey:key];
+#if DEBUG_PARSING
+ NSLog(@"messages: sender: %@ = %@ (%@)", key, value, NSStringFromClass([value class]));
+#endif
+ }
+ else if (_recipient)
+ {
+ [_recipient setObject:value forKey:key];
+#if DEBUG_PARSING
+ NSLog(@"messages: recipient: %@ = %@ (%@)", key, value, NSStringFromClass([value class]));
+#endif
+ }
+ else if (_status)
+ {
+ [_status setObject:value forKey:key];
+#if DEBUG_PARSING
+ NSLog(@"messages: status: %@ = %@ (%@)", key, value, NSStringFromClass([value class]));
+#endif
}
-
- // save the request type in the tweet
- [dictionary setObject:[NSNumber numberWithInt:requestType] forKey:TWITTER_SOURCE_REQUEST_TYPE];
-
- return dictionary;
}
-*/
-- (void)parse
+- (void)startDictionaryWithKey:(NSString *)key
{
-/*
- int readerResult = xmlTextReaderRead(_reader);
- if (readerResult != 1)
- return;
- int nodeType = xmlTextReaderNodeType(_reader);
- const xmlChar *name = xmlTextReaderConstName(_reader);
- while (! (nodeType == XML_READER_TYPE_END_ELEMENT && xmlStrEqual(BAD_CAST "direct-messages", name)))
+#if DEBUG_PARSING
+ NSLog(@"messages: dictionary start = %@", key);
+#endif
+
+ if (! _status)
{
- if (nodeType == XML_READER_TYPE_ELEMENT)
+ _status = [[NSMutableDictionary alloc] initWithCapacity:0];
+ }
+ else
+ {
+ if ([key isEqualToString:@"sender"])
{
- if (xmlStrEqual(name, BAD_CAST "direct_message"))
- {
- [parsedObjects addObject:[self _directMessageDictionaryForNodeWithName:BAD_CAST "direct_message"]];
- }
+ _sender = [[NSMutableDictionary alloc] initWithCapacity:0];
}
-
- // advance reader
- int readerResult = xmlTextReaderRead(_reader);
- if (readerResult != 1)
+ else
{
- break;
+ _recipient = [[NSMutableDictionary alloc] initWithCapacity:0];
}
- nodeType = xmlTextReaderNodeType(_reader);
- name = xmlTextReaderConstName(_reader);
}
-*/
}
+- (void)endDictionary
+{
+ if (_sender)
+ {
+ [_status setObject:_sender forKey:@"sender"];
+ [_sender release];
+ _sender = nil;
+ }
+ else if (_recipient)
+ {
+ [_status setObject:_recipient forKey:@"recipient"];
+ [_recipient release];
+ _recipient = nil;
+ }
+ else
+ {
+ [_status setObject:[NSNumber numberWithInt:requestType] forKey:TWITTER_SOURCE_REQUEST_TYPE];
+
+ [parsedObjects addObject:_status];
+ [_status release];
+ _status = nil;
+ }
+
+#if DEBUG_PARSING
+ NSLog(@"messages: dictionary end");
+#endif
+}
+
+- (void)startArrayWithKey:(NSString *)key
+{
+#if DEBUG_PARSING
+ NSLog(@"messages: array start = %@", key);
+#endif
+}
+
+- (void)endArray
+{
+#if DEBUG_PARSING
+ NSLog(@"messages: array end");
+#endif
+}
+
+
@end
View
2  MGTwitterMiscYAJLParser.h
@@ -12,6 +12,8 @@
@interface MGTwitterMiscYAJLParser : MGTwitterYAJLParser {
+ NSMutableDictionary *_results;
+
}
@end
View
84 MGTwitterMiscYAJLParser.m
@@ -8,49 +8,59 @@
#import "MGTwitterMiscYAJLParser.h"
+#define DEBUG_PARSING 0
@implementation MGTwitterMiscYAJLParser
-- (void)parse
+- (void)addValue:(id)value forKey:(NSString *)key
{
-/*
- int readerResult = xmlTextReaderRead(_reader);
- if (readerResult != 1)
- return;
-
- int nodeType = xmlTextReaderNodeType(_reader);
- const xmlChar *name = xmlTextReaderConstName(_reader);
- while (! (nodeType == XML_READER_TYPE_END_ELEMENT))
+ if (_results)
{
- if (nodeType == XML_READER_TYPE_ELEMENT)
- {
- if (xmlStrEqual(name, BAD_CAST "hash"))
- {
- [parsedObjects addObject:[self _hashDictionaryForNodeWithName:name]];
- }
- else
- {
- // process element as a string -- API calls like friendships/exists.xml just return <friends>false</friends> or <friends>true</friends>
- NSString *string = [self _nodeValueAsString];
- if (string)
- {
- NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
- [dictionary setObject:string forKey:[NSString stringWithUTF8String:(const char *)name]];
- [parsedObjects addObject:dictionary];
- }
- }
- }
-
- // advance reader
- int readerResult = xmlTextReaderRead(_reader);
- if (readerResult != 1)
- {
- break;
- }
- nodeType = xmlTextReaderNodeType(_reader);
- name = xmlTextReaderConstName(_reader);
+ [_results setObject:value forKey:key];
+#if DEBUG_PARSING
+ NSLog(@"misc: results: %@ = %@ (%@)", key, value, NSStringFromClass([value class]));
+#endif
}
-*/
}
+- (void)startDictionaryWithKey:(NSString *)key
+{
+#if DEBUG_PARSING
+ NSLog(@"misc: dictionary start = %@", key);
+#endif
+
+ if (! _results)
+ {
+ _results = [[NSMutableDictionary alloc] initWithCapacity:0];
+ }
+}
+
+- (void)endDictionary
+{
+ [_results setObject:[NSNumber numberWithInt:requestType] forKey:TWITTER_SOURCE_REQUEST_TYPE];
+
+ [parsedObjects addObject:_results];
+ [_results release];
+ _results = nil;
+
+#if DEBUG_PARSING
+ NSLog(@"misc: dictionary end");
+#endif
+}
+
+- (void)startArrayWithKey:(NSString *)key
+{
+#if DEBUG_PARSING
+ NSLog(@"misc: array start = %@", key);
+#endif
+}
+
+- (void)endArray
+{
+#if DEBUG_PARSING
+ NSLog(@"misc: array end");
+#endif
+}
+
+
@end
View
88 MGTwitterStatusesYAJLParser.m
@@ -8,38 +8,82 @@
#import "MGTwitterStatusesYAJLParser.h"
+#define DEBUG_PARSING 0
@implementation MGTwitterStatusesYAJLParser
+- (void)addValue:(id)value forKey:(NSString *)key
+{
+ if (_user)
+ {
+ [_user setObject:value forKey:key];
+#if DEBUG_PARSING
+ NSLog(@"status: user: %@ = %@ (%@)", key, value, NSStringFromClass([value class]));
+#endif
+ }
+ else if (_status)
+ {
+ [_status setObject:value forKey:key];
+#if DEBUG_PARSING
+ NSLog(@"status: status: %@ = %@ (%@)", key, value, NSStringFromClass([value class]));
+#endif
+ }
+}
-- (void)parse
+- (void)startDictionaryWithKey:(NSString *)key
{
-/*
- int readerResult = xmlTextReaderRead(_reader);
- if (readerResult != 1)
- return;
- int nodeType = xmlTextReaderNodeType(_reader);
- const xmlChar *name = xmlTextReaderConstName(_reader);
- while (! (nodeType == XML_READER_TYPE_END_ELEMENT && xmlStrEqual(BAD_CAST "statuses", name)))
+#if DEBUG_PARSING
+ NSLog(@"status: dictionary start = %@", key);
+#endif
+
+ if (! _status)
+ {
+ _status = [[NSMutableDictionary alloc] initWithCapacity:0];
+ }
+ else
{
- if (nodeType == XML_READER_TYPE_ELEMENT)
+ if (! _user)
{
- if (xmlStrEqual(name, BAD_CAST "status"))
- {
- [parsedObjects addObject:[self _statusDictionaryForNodeWithName:name]];
- }
+ _user = [[NSMutableDictionary alloc] initWithCapacity:0];
}
+ }
+}
- // advance reader
- int readerResult = xmlTextReaderRead(_reader);
- if (readerResult != 1)
- {
- break;
- }
- nodeType = xmlTextReaderNodeType(_reader);
- name = xmlTextReaderConstName(_reader);
+- (void)endDictionary
+{
+ if (_user)
+ {
+ [_status setObject:_user forKey:@"user"];
+ [_user release];
+ _user = nil;
}
-*/
+ else
+ {
+ [_status setObject:[NSNumber numberWithInt:requestType] forKey:TWITTER_SOURCE_REQUEST_TYPE];
+
+ [parsedObjects addObject:_status];
+ [_status release];
+ _status = nil;
+ }
+
+#if DEBUG_PARSING
+ NSLog(@"status: dictionary end");
+#endif
+}
+
+- (void)startArrayWithKey:(NSString *)key
+{
+#if DEBUG_PARSING
+ NSLog(@"status: array start = %@", key);
+#endif
+}
+
+- (void)endArray
+{
+#if DEBUG_PARSING
+ NSLog(@"status: array end");
+#endif
}
+
@end
View
3  MGTwitterUsersYAJLParser.h
@@ -12,6 +12,9 @@
@interface MGTwitterUsersYAJLParser : MGTwitterYAJLParser {
+ NSMutableDictionary *_user;
+ NSMutableDictionary *_status;
+
}
@end
View
88 MGTwitterUsersYAJLParser.m
@@ -8,37 +8,81 @@
#import "MGTwitterUsersYAJLParser.h"
+#define DEBUG_PARSING 0
@implementation MGTwitterUsersYAJLParser
-- (void)parse
+- (void)addValue:(id)value forKey:(NSString *)key
{
-/*
- int readerResult = xmlTextReaderRead(_reader);
- if (readerResult != 1)
- return;
- int nodeType = xmlTextReaderNodeType(_reader);
- const xmlChar *name = xmlTextReaderConstName(_reader);
- while (! (nodeType == XML_READER_TYPE_END_ELEMENT && xmlStrEqual(BAD_CAST "users", name)))
+ if (_status)
{
- if (nodeType == XML_READER_TYPE_ELEMENT)
- {
- if (xmlStrEqual(name, BAD_CAST "user"))
- {
- [parsedObjects addObject:[self _userDictionaryForNodeWithName:name]];
- }
- }
+ [_status setObject:value forKey:key];
+#if DEBUG_PARSING
+ NSLog(@"user: status: %@ = %@ (%@)", key, value, NSStringFromClass([value class]));
+#endif
+ }
+ else if (_user)
+ {
+ [_user setObject:value forKey:key];
+#if DEBUG_PARSING
+ NSLog(@"user: user: %@ = %@ (%@)", key, value, NSStringFromClass([value class]));
+#endif
+ }
+}
- // advance reader
- int readerResult = xmlTextReaderRead(_reader);
- if (readerResult != 1)
+- (void)startDictionaryWithKey:(NSString *)key
+{
+#if DEBUG_PARSING
+ NSLog(@"user: dictionary start = %@", key);
+#endif
+
+ if (! _user)
+ {
+ _user = [[NSMutableDictionary alloc] initWithCapacity:0];
+ }
+ else
+ {
+ if (! _status)
{
- break;
+ _status = [[NSMutableDictionary alloc] initWithCapacity:0];
}
- nodeType = xmlTextReaderNodeType(_reader);
- name = xmlTextReaderConstName(_reader);
}
-*/
+}
+
+- (void)endDictionary
+{
+ if (_status)
+ {
+ [_user setObject:_status forKey:@"status"];
+ [_status release];
+ _status = nil;
+ }
+ else
+ {
+ [_user setObject:[NSNumber numberWithInt:requestType] forKey:TWITTER_SOURCE_REQUEST_TYPE];
+
+ [parsedObjects addObject:_user];
+ [_user release];
+ _user = nil;
+ }
+
+#if DEBUG_PARSING
+ NSLog(@"user: dictionary end");
+#endif
+}
+
+- (void)startArrayWithKey:(NSString *)key
+{
+#if DEBUG_PARSING
+ NSLog(@"user: array start = %@", key);
+#endif
+}
+
+- (void)endArray
+{
+#if DEBUG_PARSING
+ NSLog(@"user: array end");
+#endif
}
@end
View
6 MGTwitterYAJLParser.h
@@ -32,7 +32,7 @@ connectionIdentifier:(NSString *)identifier requestType:(MGTwitterRequestType)re
connectionIdentifier:(NSString *)identifier requestType:(MGTwitterRequestType)reqType
responseType:(MGTwitterResponseType)respType URL:(NSURL *)URL;
-- (void)parse;
+//- (void)parse;
// subclass utilities
/*
@@ -48,9 +48,9 @@ connectionIdentifier:(NSString *)identifier requestType:(MGTwitterRequestType)re
- (void)addValue:(id)value forKey:(NSString *)key;
- (void)addValue:(id)value forKey:(NSString *)key;
- (void)startDictionaryWithKey:(NSString *)key;
-- (void)endDictionaryWithKey:(NSString *)key;
+- (void)endDictionary;
- (void)startArrayWithKey:(NSString *)key;
-- (void)endArrayWithKey:(NSString *)key;
+- (void)endArray;
// delegate callbacks
- (void)_parsingDidEnd;
View
120 MGTwitterYAJLParser.m
@@ -18,7 +18,6 @@ int process_yajl_null(void *ctx)
{
id self = ctx;
- //NSLog(@"%@: null", self);
if (currentKey)
{
[self addValue:[NSNull null] forKey:currentKey];
@@ -31,10 +30,9 @@ int process_yajl_boolean(void * ctx, int boolVal)
{
id self = ctx;
- //NSLog(@"%@: bool: %s", self, boolVal ? "true" : "false");
if (currentKey)
{
- [self addValue:[NSNumber numberWithBool:boolVal] forKey:currentKey];
+ [self addValue:[NSNumber numberWithBool:(BOOL)boolVal] forKey:currentKey];
[currentKey release];
currentKey = nil;
@@ -47,8 +45,7 @@ int process_yajl_integer(void *ctx, long integerVal)
{
id self = ctx;
- //NSLog(@"%@: integer: %ld", self, integerVal);
- if (currentKey)
+ if (currentKey)
{
[self addValue:[NSNumber numberWithLong:integerVal] forKey:currentKey];
@@ -63,8 +60,7 @@ int process_yajl_double(void *ctx, double doubleVal)
{
id self = ctx;
- //NSLog(@"%@: double: %lf", self, doubleVal);
- if (currentKey)
+ if (currentKey)
{
[self addValue:[NSNumber numberWithDouble:doubleVal] forKey:currentKey];
@@ -79,12 +75,23 @@ int process_yajl_string(void *ctx, const unsigned char * stringVal, unsigned int
{
id self = ctx;
- //NSLog(@"%@: string: %@", self, [[[NSString alloc] initWithBytes:stringVal length:stringLen encoding:NSUTF8StringEncoding] autorelease]);
if (currentKey)
{
NSString *value = [[[NSString alloc] initWithBytes:stringVal length:stringLen encoding:NSUTF8StringEncoding] autorelease];
- [self addValue:value forKey:currentKey];
-
+
+ if ([currentKey isEqualToString:@"created_at"])
+ {
+ // we have a priori knowledge that the value is a date, not a string
+ struct tm theTime;
+ strptime([value UTF8String], "%a %b %d %H:%M:%S +0000 %Y", &theTime);
+ time_t epochTime = timegm(&theTime);
+ [self addValue:[NSDate dateWithTimeIntervalSince1970:epochTime] forKey:currentKey];
+ }
+ else
+ {
+ [self addValue:value forKey:currentKey];
+ }
+
[currentKey release];
currentKey = nil;
}
@@ -94,9 +101,6 @@ int process_yajl_string(void *ctx, const unsigned char * stringVal, unsigned int
int process_yajl_map_key(void *ctx, const unsigned char * stringVal, unsigned int stringLen)
{
- id self = ctx;
-
- //NSLog(@"%@: key: %@", self, [[[NSString alloc] initWithBytes:stringVal length:stringLen encoding:NSUTF8StringEncoding] autorelease]);
if (currentKey)
{
[currentKey release];
@@ -112,11 +116,8 @@ int process_yajl_start_map(void *ctx)
{
id self = ctx;
- //NSLog(@"%@: map open '{'", self);
[self startDictionaryWithKey:currentKey];
-/*
- dict = [[NSMutableDictionary alloc] initWithCapacity:0];
-*/
+
return 1;
}
@@ -125,12 +126,8 @@ int process_yajl_end_map(void *ctx)
{
id self = ctx;
- //NSLog(@"%@: map close '}'", self);
- [self endDictionaryWithKey:currentKey];
-/*
- [dict release];
- dict = nil;
-*/
+ [self endDictionary];
+
return 1;
}
@@ -138,7 +135,6 @@ int process_yajl_start_array(void *ctx)
{
id self = ctx;
- //NSLog(@"%@: array open '['", self);
[self startArrayWithKey:currentKey];
return 1;
@@ -148,8 +144,7 @@ int process_yajl_end_array(void *ctx)
{
id self = ctx;
- //NSLog(@"%@: array close ']'", self);
- [self endArrayWithKey:currentKey];
+ [self endArray];
return 1;
}
@@ -200,30 +195,41 @@ - (id)initWithJSON:(NSData *)theJSON delegate:(NSObject *)theDelegate
delegate = theDelegate;
parsedObjects = [[NSMutableArray alloc] initWithCapacity:0];
- // setup the yajl parser
- yajl_parser_config cfg = {
- 0, // allowComments: if nonzero, javascript style comments will be allowed in the input (both /* */ and //)
- 1 // checkUTF8: if nonzero, invalid UTF8 strings will cause a parse error
- };
- _handle = yajl_alloc(&callbacks, &cfg, self);
- if (! _handle)
+ // this is a hack for the API methods that just return "true" or "false" and can't be parsed by YAJL
+ if ([json length] <= 5)
{
- return nil;
+ NSString *result = [[[NSString alloc] initWithBytes:[json bytes] length:[json length] encoding:NSUTF8StringEncoding] autorelease];
+ NSMutableDictionary *dictionary = [[[NSMutableDictionary alloc] initWithCapacity:1] autorelease];
+ [dictionary setObject:[NSNumber numberWithBool:[result isEqualToString:@"true"]] forKey:@"result"];
+ [parsedObjects addObject:dictionary];
}
-
- // run the parser and create parsedObjects
- [self parse];
-
- yajl_status status = yajl_parse(_handle, [json bytes], [json length]);
- if (status != yajl_status_insufficient_data && status != yajl_status_ok)
+ else
{
- unsigned char *errorMessage = yajl_get_error(_handle, 0, [json bytes], [json length]);
- NSLog(@"YAJL error = %s", errorMessage);
- yajl_free_error(errorMessage);
- }
+ // setup the yajl parser
+ yajl_parser_config cfg = {
+ 0, // allowComments: if nonzero, javascript style comments will be allowed in the input (both /* */ and //)
+ 1 // checkUTF8: if nonzero, invalid UTF8 strings will cause a parse error
+ };
+ _handle = yajl_alloc(&callbacks, &cfg, self);
+ if (! _handle)
+ {
+ return nil;
+ }
+
+ // run the parser and create parsedObjects
+ //[self parse];
- // free the yajl parser
- yajl_free(_handle);
+ yajl_status status = yajl_parse(_handle, [json bytes], [json length]);
+ if (status != yajl_status_insufficient_data && status != yajl_status_ok)
+ {
+ unsigned char *errorMessage = yajl_get_error(_handle, 0, [json bytes], [json length]);
+ NSLog(@"MGTwitterYAJLParser: error = %s", errorMessage);
+ yajl_free_error(errorMessage);
+ }
+
+ // free the yajl parser
+ yajl_free(_handle);
+ }
// notify the delegate that parsing completed
[self _parsingDidEnd];
@@ -253,27 +259,37 @@ - (void)parse
- (void)addValue:(id)value forKey:(NSString *)key
{
+ // default implementation -- override in subclasses
+
NSLog(@"%@ = %@ (%@)", key, value, NSStringFromClass([value class]));
}
- (void)startDictionaryWithKey:(NSString *)key
{
- NSLog(@"%@ = dictionary start", key);
+ // default implementation -- override in subclasses
+
+ NSLog(@"dictionary start = %@", key);
}
-- (void)endDictionaryWithKey:(NSString *)key
+- (void)endDictionary
{
- NSLog(@"%@ = dictionary end", key);
+ // default implementation -- override in subclasses
+
+ NSLog(@"dictionary end");
}
- (void)startArrayWithKey:(NSString *)key
{
- NSLog(@"%@ = array start", key);
+ // default implementation -- override in subclasses
+
+ NSLog(@"array start = %@", key);
}
-- (void)endArrayWithKey:(NSString *)key
+- (void)endArray
{
- NSLog(@"%@ = array end", key);
+ // default implementation -- override in subclasses
+
+ NSLog(@"array end");
}
Please sign in to comment.
Something went wrong with that request. Please try again.