I am creating an iOS app using swift. I would like to achieve some GET or POST HTTP request. I know that Alamofire exists but i want to create my own functions.
What I have done :
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()
}
}
The interesting part is mostly the GET function (since the POST function works the same). Well, everything seems to work fine. I achieve to use this GET function 2 times but the third time I want to use it, there is no way to access the main thread to send data. I can log something just before my commentary //The third time I use this class function, no way to access the main thread to send data
but nothing logs in the dispatch_async(dispatch_get_main_queue(),block)
.
Any idea?
What you're trying here seems a bit odd to me. You're dispatching asynchronously from the main thread to the main thread. Usually you dispatch async to perform something concurrently on another thread than the current one so the current thread can go about doing its thing without having to wait for the completion of the async task. Dispatching to the same thread will (my guess) queue the task for execution at a later moment, when the main thread has nothing to do. I don't get why you want to have these tasks executed on the main thread. Any thread would be allright as long as you're not trying to manipulate UI objects. I would really only use the main thread when touching the UI. Now getting to the matter of performing an HTTP fetch or post I would recommend following the approach that Apple propagates. That is using delegates for handling the asynchronous callbacks. Apple has defined three delegate protocols: NSURLSessionDelegate, NSURLSessionTaskDelegate, NSURLSessionDataDelegate. I would create a class, say HTTPClient that implements these protocols:
@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
After receiving all the data you can perform the necessary JSON processing. Of course you need to initialize the dictionary runningTasks.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.