2015-02-03 2 views
0

swift를 사용하여 iOS 앱을 만들고 있습니다. 일부 GET 또는 POST HTTP 요청을 얻고 싶습니다. 나는 Alamofire가 존재하지만 내 자신의 기능을 만들고 싶다는 것을 알고 있습니다.IOS, Swift, NSURLSession의 기본 스레드에 액세스 할 수 없습니다.

은 내가 무슨 짓을 :

import Foundation 

class DatabaseRequest:NSObject{ 

    class func GET(urlAsString:String, completion : (response:NSURLResponse, result:AnyObject?, error:String?)-> Void){ 

     let configuration = NSURLSessionConfiguration.ephemeralSessionConfiguration() 
     let session = NSURLSession(configuration: configuration) 

     let url = NSURL(string: urlAsString) 
     let urlRequest = NSMutableURLRequest(URL: url!) 
     urlRequest.HTTPMethod = "GET" 

     session.dataTaskWithRequest(urlRequest, completionHandler: { (data, response, error) -> Void in 
      if let error = error{ 
       dispatch_async(dispatch_get_main_queue(), {() -> Void in 
        completion(response: response, result: nil, error: "GET Connection error : \(error.localizedDescription)") 
       }) 
      }else{ 
       var error:NSError? 

       let JSON_Object:AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments, error: &error) 
       if let error = error{ 
        dispatch_async(dispatch_get_main_queue(), {() -> Void in 
         completion(response: response, result: nil, error: "GET JSONSerialization error: \(error.localizedDescription)") 
        }) 
       }else{ 
        if let result:AnyObject = JSON_Object{ 
         //The third time I use this class function, no way to access the main thred to send data 
         dispatch_async(dispatch_get_main_queue(), {() -> Void in 
          completion(response: response, result: JSON_Object, error: nil) 
         }) 
        }else{ 
         dispatch_async(dispatch_get_main_queue(), {() -> Void in 
          completion(response: response, result: nil, error: nil) 
         }) 
        } 
       } 
      } 

      session.finishTasksAndInvalidate() 

     }).resume() 

    } 

    class func POST(urlAsString:String, parameters:[String:AnyObject], completion:(response:NSURLResponse?, result:AnyObject?, error:String?)->Void){ 
     println("POST used") 
     let configuration = NSURLSessionConfiguration.ephemeralSessionConfiguration() 
     let session = NSURLSession(configuration: configuration) 

     var errorHTTPBody:NSError? 
     let url = NSURL(string: urlAsString) 
     let urlRequest = NSMutableURLRequest(URL: url!) 
     urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type") 
     urlRequest.addValue("application/json", forHTTPHeaderField: "Accept") 
     urlRequest.HTTPMethod = "POST" 
     urlRequest.HTTPBody = NSJSONSerialization.dataWithJSONObject(parameters, options: nil, error: &errorHTTPBody) 

     if let error = errorHTTPBody{ 
      dispatch_async(dispatch_get_main_queue(), {() -> Void in 
       completion(response: nil, result: nil, error: "POST errorHTTPBody: \(error.localizedDescription)") 
      }) 
      return 
     } 

     session.dataTaskWithRequest(urlRequest, completionHandler: { (data, response, error) -> Void in 
      println(data) 
      if let error = error{ 
       dispatch_async(dispatch_get_main_queue(), {() -> Void in 
        completion(response: response, result: nil, error: "POST Connection error : \(error.localizedDescription)") 
       }) 
      }else{ 
       var error:NSError? 
       var JSON_Object:AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments, error: &error) 
       if let error = error{ 
        dispatch_async(dispatch_get_main_queue(), {() -> Void in 
         completion(response: response, result: nil, error: "POST JSONSerialization error : \(error.localizedDescription)") 
        }) 
       }else{ 
        if let result:AnyObject = JSON_Object{ 
         dispatch_async(dispatch_get_main_queue(), {() -> Void in 
          completion(response: response, result: JSON_Object, error: nil) 
         }) 
        }else{ 
         dispatch_async(dispatch_get_main_queue(), {() -> Void in 
          completion(response: response, result: nil, error: nil) 
         }) 
        } 
       } 
      } 

      session.finishTasksAndInvalidate() 

     }).resume() 

    } 

} 

흥미로운 부분은 주로 GET 기능입니다합니다 (POST 기능이 동일하게 작동하기 때문에). 음, 모든 것이 잘 작동하는 것 같습니다. 나는이 GET 함수를 두 번 사용하려고하지만 세 번째로 사용하고 싶을 때 데이터를 보내기 위해 주 스레드에 액세스 할 수있는 방법이 없다. 내 논평 //The third time I use this class function, no way to access the main thread to send data 바로 전에 로그 할 수 있지만 dispatch_async(dispatch_get_main_queue(),block)에 로그인하지 않습니다.

아이디어가 있으십니까?

답변

1

당신이 여기서 시도하는 것은 저에게 조금 이상하게 보입니다. 주 스레드에서 주 스레드로 비동기 적으로 디스 패칭합니다. 일반적으로 비동기 작업을 완료하기 위해 기다리지 않고 현재 스레드가 수행 할 수 있도록 현재 스레드와 다른 스레드에서 동시에 수행 할 비동기를 전달합니다. 같은 스레드로 파견하는 것은 (메인 추측) 메인 스레드가 할 일이없는 나중에 실행을위한 작업을 큐에 넣을 것이다. 나는 왜 당신이이 작업들을 메인 스레드에서 실행시키고 싶어하는지 알지 못한다. UI 객체를 조작하려고 시도하지 않는 한 모든 스레드는 괜찮습니다. 난 UI를 만질 때 정말 메인 스레드를 사용합니다. 이제 HTTP 가져 오기 또는 게시 작업을 수행하면서 Apple이 전파하는 방식을 따르는 것이 좋습니다. 그것은 비동기 콜백을 처리하기 위해 델리게이트를 사용합니다. Apple은 NSURLSessionDelegate, NSURLSessionTaskDelegate, NSURLSessionDataDelegate의 세 가지 대리 프로토콜을 정의했습니다. 나는 클래스를 만들 것이다, 이러한 프로토콜을 구현하는 HttpClient를 말 : 당신이 필요한 JSON 처리를 수행 할 수

@interface HTTPClient : NSObject <NSURLSessionDelegate, NSURLSessionTaskDelegate, NSURLSessionDataDelegate> 

@property (strong, nonatomic) NSURLSession *session; 

@property (strong, nonatomic) NSMutableDictionary *runningTasks; 


- (void) URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data; 

- (void) URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error; 

- (NSURLSessionTask *) startGetTaskForURL: (NSURL *) url; 

@end 

@implementation HTTPClient 

- (NSURLSessionTask *) startGetTaskForURL: (NSURL *) url { 
    NSURLSessionTask *task = [self.session dataTaskWithURL:url]; 
    NSMutableData *data = [NSMutableData data]; 
    [task resume]; 
    [self.runningTasks setObject:data forKey:task]; 
    return task; 
} 

- (void) URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *) dataTask didReceiveData: (NSData *)data { 
    NSString *dataString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 
    NSMutableData *runningData = [self.runningTasks objectForKey:task]; 
    if (!runningData) { 
     NSLog(@"No data found for task"); 
    } 
    [runningData appendData: data]; 
} 

- (void) URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error { 
    NSData *data = [self.runningTasks objectForKey:task]; 
    //process the data received 
} 

@end 

모든 데이터를받은 후. 물론 작업 실행중인 사전을 초기화해야합니다.

+0

정말 대단합니다. 고맙습니다. – soling