我正在尝试从名为connect的方法中获取URL的内容。它读取其配置设置并尝试获取URL。它似乎需要运行循环来执行。我虽然只执行一次并完成。似乎除了每次获取此URL时,无论何时调用connect,我都不需要运行该循环。有没有更好的方法呢?
- (BOOL) connect
{
// read serverName and eventId from preferences
NSMutableArray* preferences;
preferences = [NSMutableDictionary dictionaryWithContentsOfFile:@"/tmp/wt.plist"];
// if these values aren't nil or blank
if ([preferences valueForKey:@"serverAddress"] && [preferences valueForKey:@"eventId"]) {
[self setServerAddress:@"172.16.28.210"];
[self setEventId:@"OT-3037009"];
} else{
// return some kind of error message
}
NSLog(@"VideoDataURL: %@", [self getVideoDataURL]);
// grab the URL and query the server
NSURL *myURL = [NSURL URLWithString:@"http://localhost"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:myURL
cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
timeoutInterval:2];
__unused NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
[[NSRunLoop currentRunLoop] run];
return TRUE;
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
// This method is called when the server has determined that it
// has enough information to create the NSURLResponse.
// It can be called multiple times, for example in the case of a
// redirect, so each time we reset the data.
// receivedData is an instance variable declared elsewhere.
[incomingData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
/*
* Called each time a chunk of data arrives
*/
NSLog(@"received %lu bytes", [data length]);
// Create a mutable data if it doesn't already exist
if (!incomingData) {
incomingData = [[NSMutableData alloc] init];
}
[incomingData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
/*
* Called if the connection fails
*/
NSLog(@"connection failed: %@", [error localizedDescription]);
incomingData = nil;
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
/*
* Called when the last chunk has been processed
*/
NSLog(@"Got it all!");
NSString *string = [[NSString alloc] initWithData:incomingData encoding: NSUTF8StringEncoding];
incomingData = nil;
NSLog(@"response is: %@", string);
}
答案 0 :(得分:10)
如果您正在从主线程开始连接,是的,这是正确的。我只是使用GCD在主线程上创建并启动连接,以避免考虑运行循环。
dispatch_async(dispatch_get_main_queue(), ^{
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
[conn start];
});
从任何地方开始工作,您无需跟踪运行循环或线程。
答案 1 :(得分:3)
我会确保你手动告诉runLoop你正在运行连接的工作线程运行,直到连接完成。如果你不这样做,Cocoa会自动让线程进入休眠状态,因此你的委托方法似乎永远不会收到响应。
// The following is delcared within the scope of a NSThread, NSOperation, or GCD Block
//
// The NSURLConnection object and it's initialization/start methods
// |
// V
// Above the method call to the thread's runLoop.
//
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:<a time interval>];
// I use a minute, or 60.0, before I manually cancel the connection
// and send an error message back to the caller.
^生成连接后应该调用的方法。它应该为您提供您正在寻找的结果。
在构建异步服务器调用/任务时,请记住此结构:
每个异步任务都需要自己的RunLoop,以便在事件存在期间连续轮询事件。每个RunLoop都需要存在于线程范围内,以便执行相关的任务。
您可以使用NSThread / NSRunLoop / NSURLConnection,Grand Central Dispatch或甚至NSOperation / NSOperationQueue手动构建异步网络任务。我更喜欢操作/队列,因为我觉得它们更像面向对象,并且基于块的编程可能有点棘手(如果您只是使用“dispatch_”调用,那么您将编写请求的结构)。当一切都归结为它时,根据您的编程偏好编写您的线程模型。每种方法都会给你相同的结果。
此外,除非您正在执行需要同步的任务部分,否则不要使用dispatch_sync,否则您将锁定UI。掌握RunLoops是必要的,以便为您的应用程序创建真正的异步模型。
祝你好运!P.S。 NSURLConnection已构建为异步运行,但是,要创建真正的异步网络模型,您的应用程序将需要在与主线程分开的线程上生成连接。
答案 2 :(得分:0)
我认为同步请求不需要运行循环:
NSURLResponse* response = nil;
NSData* data = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:&response error:nil];