开发者

Creating a Simple Utilities Class

I want to create a class to speed up things like getting application delegate, parsing xml

Implementing the utilites as class function seems to make sense. After all it's effectively just a function we could call globally.

But then when I do

[xmlParser setDelegate:self];

I am in trouble. In a class function, self refer to the class.

What would be the elegant solution for this if you're an objective-c programmer

If I turn (void)parseXMLFileAtURL:(NSString *)URL into an instance variable, then things don't look right. BNUtilitiesQuick doesn't even have a field and I really intent to have something that can be accessed anywhere.

If I turn BNUtilitiesQuick as categories of NSObject, that seems awkward. Why would all classes on my program can be the delegate of XMLParser

So what should I do?

@implementation BNUtilitiesQuick


+ (BadgerNewAppDelegate *)appDelegate
{

    return [[UIApplication sharedApplication] delegate];
}

+ (NSManagedObjectContext*)managedObjectContext;{
    return [[BNUtilitiesQuick appDelegate] managedObjectContext];
}



+ (void)parseXMLFileAtURL:(NSString *)URL {


    //you must then convert the path to a proper NSURL or it won't work
    NSURL *xmlURL = [NSURL URLWithString:URL];

    // here, for some reason you have to use NSClassFromString when trying开发者_运维问答 to alloc NSXMLParser, otherwise you will get an object not found error
    // this may be necessary only for the toolchain
    NSXMLParser* xmlParser = [[[NSXMLParser alloc] initWithContentsOfURL:xmlURL] autorelease];

    // Set self as the delegate of the parser so that it will receive the parser delegate methods callbacks.
    [xmlParser setDelegate:self];

    // Depending on the XML document you're parsing, you may want to enable these features of NSXMLParser.
    [xmlParser setShouldProcessNamespaces:NO];
    [xmlParser setShouldReportNamespacePrefixes:NO];
    [xmlParser setShouldResolveExternalEntities:NO];

    [xmlParser parse];
}

@end


There are several ways to address your concerns with BNUtilitiesQuick.

The primary reason you're having trouble is because NSXMLParser uses a callback mechanism. This is done so that you don't have to read the entire document into memory at once -- it parses as it goes. This means you need a unique delegate object for each NSXMLParser you create.

Solution #1 - use Singleton pattern

BNUtilitiesQuick could be a singleton, but then you will run into issues if you call it twice from two different threads (the class will get messages from both XML documents that are being parsed simultaneously). If threading isn't an issue, this would work.

Solution #2 - Switch XML parsers (avoid the problem)

Another solution would be to use a different XML parser that doesn't require a delegate-based parsing approach. NSXMLParser is SAX-based, which generally uses a callback or delegate pattern. Ray Wenderlich has a great post on his blog about the different XML parsers available on iOS and how to choose your favorite.

Solution #3 - Create the delegate object in the method

Add another layer of abstraction -- your parse XML method should create a new instance of a new XML Parser Delegate class that will handle callbacks for this specific parse operation. Then, when you create the parser, set the delegate to this newly created object, and parse the XML.

No state is stored on your Utils class, so you don't have to worry about multi-threaded issues.

It might also help to return the parsed object instead of (void) in your parse method -- that seems like another pitfall of your design.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜