問題描述
Apakah NSURLConnections termasuk dalam model atau pengontrol saya? (Do NSURLConnections belong in my model or controller?)
Say I'm using a JSON or XML API to get data about my projects from a URL using an asyncronous NSURLConnection, parsing that into an NSMutableArray and then populating an NSTableView.
I have a model: Project I have a controller: TableViewController (acting as table data source and delegate)
Where should I put the code that starts the request and parses the result into a NSMutableArray.
Should I have:
1:
A method inside Project called ‑(NSMutableArray* ) getAllProjects
and call this from my Controller.
Or 2:
Should I enumerate an NSMutableArray of Project* objects, called for instance ProjectsArray* inside my Controller; each time calling [[Project alloc] init]
?
Option 1 makes much more sense to me because I might want to get all the projects from multiple controllers and this would save repeating code, I only need to call a public method inside my Project model. In this case would I be doing lots of [[self alloc] init]
statements? Is this ok? Also my model would need to be an NSURLConnection delegate. Is this correct?
‑‑‑‑‑
參考解法
方法 1:
No doubt it must be in your Model.
Reason :
Because you will be requiring to update it many times from different controllers, you can use KVO for that in future.
方法 2:
From my experience, I think the good way is to have the parsing routines in the model (ProjectsArray) and connection stuff in another class, which initiates the connection and returns raw NSData (through a delegate for example), which you pass to the model to parse it. This way your model or viewController won't have multiple roles.
As for calling [[Project alloc] init]
each time you need the data—you can use static reference in the model class and then getting it by something like ‑ (ProjectsArray *)instance
方法 3:
/*
* UITableViewController has the word "controller" in it but that
* does not make it a controller... it's a view. Pure and simple.
*
* /This/ is a controller...
*/
@implementation MyController
@synthesize data; // assume readonly @property in interface
‑(void)fetchData {
NSURLConnection *connection;
// Set up URL connection, etc. Speaking very loosely, and
// lossing over some important threading details...
NSURLResponse *response = GetResponse();
NSError *__autoreleasing error;
@autoreleasepool {
// build objects. premature optimization is the root of all evil,
// but if you're really worried about too much allocation, you
// can resist duplication with custom logic in parse().
self.data = parse([response data], &error);
}
if (data == nil) {
// Error notification
}
else { // Success notification
NSNotification *didFetch = [NSNotification notificationWithName:@"didFetch" object:self.data userInfo:nil];
[[NSNotificationCenter defaultCenter] performSelectorOnMainThread:@selector(postNotification:) withObject:didFetch waitUntilDone:NO];
}
}
@end
@interface MyTableViewController ()
@property (unsafe_unretained) MyController *controller;
@property (strong, nonatomic) NSArray *dataView;
@end
@implementation MyTableViewController
@synthesize controller = _controller;
@synthesize dataView = _dataView;
‑(void)viewDidLoad {
_controller = [MyController controller]; // singleton
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(updateData:)
name:@"didFetch"
object:nil];
}
‑(IBAction)buttonPress {
[_controller fetchData]; // again, I'm glossing over threading details...
}
‑(void)updateData {
// Controller owns the data, we just get a view of it here.
self.dataView = [[_controller data] arrayOfSomeSort];
[self.view reloadData];
}
@end
(by Matt Harrison、Anoop Vaidya、Michael Ruml、QED)