How to convert NSURLConnecion statement to Xcode 7 (swift 2.0)? - ios

NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()) {
(response: NSURLResponse!, data: NSData!, error: NSError!) -> Void in
Sorry, new to iOS, etc. Just cannot convert it. Xcode beta 7.0 (7A121I)

Based on your included code, it looks like the syntax for your closure (completion handler) is incorrect. I'm not 100% sure if this will work as I don't have Xcode in front of me but try something like this:
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue(), completionHandler: { (response, data, error) -> Void in
// code here
})

Related

Unit testing network calls (failing tests) - Swift

I'm trying to write failing tests for my network calls but can't find anyway to access the connection settings from within my tests.
This code works fine for testing a success case:
func testRetrieveProducts() {
let expectation = expectationWithDescription("asynchronous request")
Requests().retrieveProducts({ (products) -> () in
// check that we have two arrays returned.
XCTAssert(products.count == 2)
expectation.fulfill()
}) { (error) -> () in
XCTFail("Request failed")
}
waitForExpectationsWithTimeout(5.0, handler: nil)
}
But I've been looking for a way to test network timeouts, and incorrect data being returned.
I can probably test incorrect data by calling functions individually inside the retrieveProducts function and stubbing stuff out, but doing something as simple as turning off the internet is proving to be quite difficult.
I know we have access to the Network Link Conditioner, but turning this on and off for each test isn't an option.
I'd love to have access to something as simple as:
func testFailRetrieveProducts() {
let expectation = expectationWithDescription("asynchronous request")
SomeNetworkClass.disableInternet()
Requests().retrieveProducts({ (products) -> () in
}) { (error) -> () in
XCTAssert(error == SomeError.TimeoutError)
}
waitForExpectationsWithTimeout(5.0, handler: nil)
}
Any solutions out there that can handle what I'm after, or am I going about this all wrong?
Take a look at this NSHipster article about Apple's Network Link Conditioner. There's a lot of presets and you can create your own custom network profile. Unfortunately there doesn't seem to be a way to throttle the network in code.
A somewhat viable alternative however is to use ReactiveCocoa and model all your network events as SignalProducers. Then you can use the throttle or wait function, depending on your intentions.
I ended up just mocking the network calls, which to be honest is a lot better than performing tests over an actual connection, as these can be very unreliable anyway.
Here's my mock NSURLSession
class MockSession: NSURLSession {
var completionHandler:((NSData!, NSURLResponse!, NSError!) -> Void)?
static var mockResponse: (data: NSData?, urlResponse: NSURLResponse?, error: NSError?)
override class func sharedSession() -> NSURLSession {
return MockSession()
}
override func dataTaskWithRequest(request: NSURLRequest, completionHandler: (NSData?, NSURLResponse?, NSError?) -> Void) -> NSURLSessionDataTask {
self.completionHandler = completionHandler
return MockTask(response: MockSession.mockResponse, completionHandler: completionHandler)
}
class MockTask: NSURLSessionDataTask {
typealias Response = (data: NSData?, urlResponse: NSURLResponse?, error: NSError?)
var mockResponse: Response
let completionHandler: ((NSData!, NSURLResponse!, NSError!) -> Void)?
init(response: Response, completionHandler:((NSData!, NSURLResponse!, NSError!) -> Void)?) {
self.mockResponse = response
self.completionHandler = completionHandler
}
override func resume() {
completionHandler!(mockResponse.data, mockResponse.urlResponse, mockResponse.error)
}
}
}
Here's how I use it in a test:
Note that you still have to use an expectation even though there's no network delay.
func testRetrieveProductsValidResponse() {
let testBundle = NSBundle(forClass: self.dynamicType)
let filepath = testBundle.pathForResource("products", ofType: "txt")
let data = NSData(contentsOfFile: filepath!)
let urlResponse = NSHTTPURLResponse(URL: NSURL(string: "https://anyURL.com")!, statusCode: 200, HTTPVersion: nil, headerFields: nil)
MockSession.mockResponse = (data, urlResponse: urlResponse, error: nil)
let requestsClass = RequestManager()
requestsClass.Session = MockSession.self
let expectation = expectationWithDescription("ready")
requestsClass.retrieveProducts("N/R FOR TEST", branchID: "N/R FOR TEST", products: { (products) -> () in
XCTAssertTrue(products.count == 7)
expectation.fulfill()
}) { (error) -> () in
XCTAssertFalse(error == Errors.NetworkError, "Its a network error")
XCTAssertFalse(error == Errors.ParseError, "Its a parse error")
XCTFail("Error not covered by previous asserts. Shouln't get to here anyway.")
expectation.fulfill()
}
waitForExpectationsWithTimeout(3.0, handler: nil)
}
Finally, I have an accessible property on my RequestManager class that I can swap out with the MockSession when doing my tests.
var Session = NSURLSession.self

Cannot invoke 'responseArray' with an argument list of type

I'm using Alamofire, with ObjectMapper, things were so smooth before upgrading to Swift 2.0, now,
For the following signature:
public func responseArray<T: Mappable>(completionHandler: ([T]?, ErrorType?) -> Void) -> Self
I'm calling
Alamofire.request(.GET, URL, parameters: nil)
.responseArray { (response: [MyObject]?, error: NSError?) in
}
and getting the following error:
Cannot invoke 'responseArray' with an argument list of type
(([MyObject]?, NSError?) -> ())
Any help will be super appreciated.
try this.
Alamofire.request(.GET, URL, parameters: nil)
.responseArray { (response: [MyObject]?, error) in
//your process
}

How to mock NSURLConnection.sendAsynchronousRequest in unit testing

I have a function in which i am calling a network call as,
func newtorkCall() {
//some other code
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue(), completionHandler: {(response:
NSURLResponse!, data: NSData!, error: NSError!) -> Void in
if (data != nil) {
//save the data in a variable temp
}
})
}
this is working fine and i am getting the data.
But i want to mock this NSURLConnection.sendAsynchronousRequest in unit testing so that i can hardcode the data and pass it to the variable temp in the source code and test it.
How can I do it?

Not able to make a network request from FileProvider extension on iOS

I am writing a FileProvider extension (NSFileProviderExtension) for iOS. When "itemChangedAtURL" is called, I want to take the data from the NSURL and commit it back to my server. The problem I am having is that I will use Alamofire to make a request call and the request will never fire. I have tried setting backgroundSessionConfigurationWithIdentifier and using a sharedContainerIdentifier but none of that worked either. The same alamofire calls worked outside of the FileProvider extension. Does anyone know how exactly I have to setup NSURLSession or Alamofire to get this to work correctly?
I ran into this similar problem with AFNetworking. I decided to wrap my calls in a block based on what I read in http://z43studio.com/2015/04/storage-providers/
override func itemChangedAtURL(url: NSURL) {
var manager = AFHTTPSessionManager()
var request = manager.requestSerializer.multipartFormRequestWithMethod("PUT", URLString: "http://somewhere.awesome", parameters: nil, constructingBodyWithBlock: { (data: AFMultipartFormData!) -> Void in
var res = data.appendPartWithFileURL(fileUrl, name: "custom_name", error: nil)
}, error: nil)
var semaphore = dispatch_semaphore_create(0)
let task:NSURLSessionDataTask = manager.uploadTaskWithStreamedRequest(request, progress: nil,
completionHandler: {(response: NSURLResponse!, responseObject: AnyObject!, error: NSError!) -> Void in
if ((error) != nil) {
println("ERROR")
// Attempt to recover - otherwise release
dispatch_semaphore_signal(semaphore)
} else {
println("SUCCESS")
dispatch_semaphore_signal(semaphore)
}
})
task.resume()
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
}

Swift : Converting inline to trailing closures in function

So I have the following function defined:
public typealias RESTClosure = (response: NSURLResponse!, data: NSData!, error: NSError!) -> Void
public func queryAllFlightsWithClosure(completionHandler : RESTClosure) {
// code ....
}
I'm able to call this function as:
func myResponseHandler(response: NSURLResponse!, data: NSData!, error: NSError!) -> Void {
// code ...
}
rest?.queryAllFlightsWithClosure(myResponseHandler)
From my understanding of Swift, however, if the final argument of a function is a closure it can be converted into a trailing closure ... but I've run into some syntax confusion:
Attempt #1
rest?.queryAllFlightsWithClosure() {
println("Called with Closure")
}
Error:
Tuples types '(response: NSURLResponse!, data NSData!, error: NSError!)' and '()' have different number of elements (3 vs. 0)
Attempt #2
rest?.queryAllFlightsWithClosure() (RESTClosure.self) { // Xcode told me to add a .self
//...code
}
Error: Missing argument for parameter #1 in call
I know I'm close ... but anybody can help me here?
Your parameters go inside the closure, and since there's just the one argument, you can even leave out the parentheses:
rest?.queryAllFlightsWithClosure {
(response: NSURLResponse!, data: NSData!, error: NSError!) in
// code ...
}
If you're going to be accessing self or any properties inside the closure, you'll want to include self in a capture list, like this:
rest?.queryAllFlightsWithClosure {
[weak self] (response: NSURLResponse!, data: NSData!, error: NSError!) in
// code ...
// note that self is optional inside this closure b/c of [weak self]
self?.doSomething()
}
Well this seems to compile
rest?.queryAllFlightsWithClosure() { RESTClosure in
// code ...
}

Resources