Function Return Error in iOS - ios

I have the following function: prepare() which returns NSMUtableArray. When I try, to return a json which is NSMutableArray object, I get the following error:
'NSMutableArray' is not convertible to 'Void'
Function Source Code:
func prepare() -> NSMutableArray {
let statusesShowEndpoint = "https://api.twitter.com/1.1/statuses/user_timeline.json"
let params = ["screen_name": "tikaDotMe"]
var clientError : NSError?
let request = Twitter.sharedInstance().APIClient.URLRequestWithMethod(
"GET", URL: statusesShowEndpoint, parameters: params,
error: &clientError)
if request != nil {
Twitter.sharedInstance().APIClient.sendTwitterRequest(request) {
(response, data, connectionError) -> Void in
if (connectionError == nil) {
var jsonError : NSError?
let json = NSJSONSerialization.JSONObjectWithData(data,
options: nil,
error: &jsonError) as NSMutableArray
//Error: 'NSMutableArray' is not convertible to 'Void'
return json
}
else {
println("Error: \(connectionError)")
}
}
}
else {
println("Error: \(clientError)")
}
return [""]
}

The problem is that you are trying to return json from a closure which is defined as returning a Void:
(response, data, connectionError) -> Void
EDIT: As #Paulw11 mentions, you need to handle the data in your closure, you can't return it from your prepare function.

Related

Migration Alamofire 4 to 5 build issue

I am doing migration after 2 years a lots things have been changed, now flagging a lots of error while building. Most are related to Alamofire 5. Now there are many error keeps coming fixing one by one.
Error: // ERROR: Cannot specialize non-generic type
public static func ObjMappingSerializer<T: Mappable>(_ keyPath: String?) -> DataResponseSerializer<T> { 'DataResponseSerializer'
return DataResponseSerializer { request, response, data, error in
//LogResponse(response, data: data, error: error)
Logger._reqresLogger.logResponse(response, data: data, error: error)
guard error == nil else {
return .failure(parseErrorResponse(data: data, response: response, errorType: error!))
}
guard let _ = data else {
return .failure(errorForNilData())
}
let JSONToMap = deserializeJSON(request: request, response: response, data: data, error: error, keyPath: keyPath)
if let json = JSONToMap as? [String:Any], let parsedObject = Mapper<T>().map(JSON:json) {
return .success(parsedObject)
}
let errorCode = response?.statusCode ?? NSURLErrorCannotParseResponse
return .failure(APIError(code: errorCode, errorUserInfo: nil))
}
}
Fixed by autosuggestion however next error comes
Error: Trailing closure passed to parameter of type 'DataPreprocessor' that does not accept a closure
public static func ObjMappingSerializer(_ keyPath: String?) -> DataResponseSerializer {
return DataResponseSerializer { request, response, data, error in
//LogResponse(response, data: data, error: error)
Logger._reqresLogger.logResponse(response, data: data, error: error)
guard error == nil else {
return .failure(parseErrorResponse(data: data, response: response, errorType: error!))
}
guard let _ = data else {
return .failure(errorForNilData())
}
let JSONToMap = deserializeJSON(request: request, response: response, data: data, error: error, keyPath: keyPath)
if let json = JSONToMap as? [String:Any], let parsedObject = Mapper<T>().map(JSON:json) {
return .success(parsedObject)
}
let errorCode = response?.statusCode ?? NSURLErrorCannotParseResponse
return .failure(APIError(code: errorCode, errorUserInfo: nil))
}
}
Now in Alamofire many methods have been removed in Alamofire 5. How can I fix these errors?
You can no longer initialize a DataResponseSerializer with a closure. I suggest you reevaluate your parsing needs and rebuild around responseDecodable. If you need, you can create your own serializer by adopting ResponseSerializer. Your logic would be the same, just copied into the parse method.

Generic parameter 'T' could not be inferred while calling a method

I am getting below error
Generic parameter 'T' could not be inferred
I have created a method and when I am trying to call that method then getting that error. I am adding both methods below.
func requestNew<T> ( _ request: URLRequest, completion: #escaping( Result< T , NetworkError>) -> Void ) where T : Decodable {
URLCache.shared.removeAllCachedResponses()
print("URL \((request.url as AnyObject).absoluteString ?? "nil")")
//use the currentrequest for cancel or resume alamofire request
currentAlamofireRequest = self.sessionManager.request(request).responseJSON { response in
//validate(statusCode: 200..<300)
if response.error != nil {
var networkError : NetworkError = NetworkError()
networkError.statusCode = response.response?.statusCode
if response.response?.statusCode == nil{
let error = (response.error! as NSError)
networkError.statusCode = error.code
}
//Save check to get the internet connection is on or not
if self.reachabilityManager?.isReachable == false {
networkError.statusCode = Int(CFNetworkErrors.cfurlErrorNotConnectedToInternet.rawValue)
}
completion(.failure(networkError))
}else{
print("response --- > ",String(data: response.data!, encoding: .utf8) ?? "No Data found")
if let responseObject = try? JSONDecoder().decode(T.self, from: response.data!) {
completion(.success(responseObject.self))
}else {
}
}
}
}
Below is screenshot of error
![
]1
func getVersion1(complete :#escaping (Response<Version>) -> Void, failure:#escaping onFailure) {
self.network.requestNew(self.httpRequest) { (result) in
print("hello")
}
When Swift cannot infer the generic parameter, although it accepts the generic declaration of the method, you can specify the type by passing type fixed parameters.
Try this:
func getVersion1(complete :#escaping (Response<Version>) -> Void, failure:#escaping onFailure) {
self.network.requestNew(self.httpRequest) { (result: Result<Version, NetworkError>) in
print("hello")
}
}
You may need to change Result<Version, NetworkError> to Result<SomeDecodableType, NetworkError>, if Version is not the type you expect from the request.

Swift3 closure crash

Crashing while creating an instance of URLSessionTask with the completion handlers
func sessionTaskPostRequest (_ urlRequest : URLRequest , responseHandler: #escaping ResponseHandler) -> URLSessionTask {
// 5
let sesstionTask : URLSessionTask = networkSession.dataTask(with: urlRequest, completionHandler: { (data : Data? , urlResponse : URLResponse? , error : NSError? ) in
var json: NSDictionary!
do {
json = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions()) as? NSDictionary
} catch {
print(error)
}
// Did the JSONObjectWithData constructor return an error? If so, log the error to the console
if(error != nil) {
responseHandler (false , nil , error , nil)
}
else {
// The JSONObjectWithData constructor didn't return an error. But, we should still
// check and make sure that json has a value using optional binding.
if let parseJSON = json {
let errorJSON = parseJSON ["Err"] as! String
if !errorJSON.isEmpty {
responseHandler (false , nil , nil , errorJSON)
}else {
responseHandler (true , parseJSON , nil , nil)
}
print("Succes: \(parseJSON)")
}
else {
// Woa, okay the json object was nil, something went worng. Maybe the server isn't running?
let jsonStr = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
responseHandler (false , nil , error , "Error could not parse JSON")
print("Error could not parse JSON: \(jsonStr)")
}
}
} as! (Data?, URLResponse?, Error?) -> Void)
return sesstionTask
}
And created a type alias for response handler that returns the response JSON Object . Type alias as follows
typealias ResponseHandler = (_ successFlag :Bool , _ data : NSDictionary? , _ errorObject : NSError? , _ errorString : String?) -> Void
Seems like Response handler is getting the Error Object as NSError which will get crashed if Error object is nil and failed to cast it to NSError
Error = nil
and when you receive it as NSError Typecasting fails because of nil object , but the same thing is handled wisely if you don't do any typecasting

Twitter API invalid URLRequestWithMethod using Swift

i'm trying to access the home_timeline request as per this example.
However, I keep getting following error:
'URLRequestWithMethod' with an argument list of type '(String, URL: String, parameters: NSArray, error: inout NSError?)'
func getHomeTimeLine(){
var clientError:NSError?
let params = []
let request = Twitter.sharedInstance().APIClient.URLRequestWithMethod(
"GET",
URL: "https://api.twitter.com/1.1/statuses/home_timeline.json",
parameters: params,
error: &clientError)
if request != nil {
Twitter.sharedInstance().APIClient.sendTwitterRequest(request) {
(response, data, connectionError) -> Void in
if (connectionError == nil) {
var jsonError : NSError?
let json : AnyObject? =
NSJSONSerialization.JSONObjectWithData(data,
options: nil,
error: &jsonError)
}
else {
println("Error: \(connectionError)")
}
}
}
else {
println("Error: \(clientError)")
}
}
Thanks in advance.
Define params as a dictionary and use it.
let params: Dictionary = Dictionary()
func getHomeTimeLine() {
var clientError:NSError?
let params: Dictionary = Dictionary<String, String>()
let request: NSURLRequest! = Twitter.sharedInstance().APIClient.URLRequestWithMethod(
"GET",
URL: "https://api.twitter.com/1.1/statuses/home_timeline.json",
parameters: params,
error: &clientError)
if request != nil {
Twitter.sharedInstance().APIClient.sendTwitterRequest(request!) {
(response, data, connectionError) -> Void in
if (connectionError == nil) {
var jsonError : NSError?
let json : AnyObject? =
NSJSONSerialization.JSONObjectWithData(data!,
options: nil,
error: &jsonError)
// check for json data
if (json != nil) {
println("response = \(json)")
} else {
println("error loading json data = \(jsonError)")
}
}
else {
println("Error: \(connectionError)")
}
}
}
else {
println("Error: \(clientError)")
}
}
Try this:
let request: NSURLRequest? = Twitter.sharedInstance().APIClient.URLRequestWithMethod("GET", URL: "https://api.twitter.com/1.1/statuses/user_timeline.json",
parameters: ["screen_name" : username,
"count" : "20"] ,
error: &clientError)
Actually, the method signature where it says 'URL' has been changed to 'URLString' the correct / updated method call (in Objective C) looks like this:
NSDictionary *params = #{#"include_email": #"true", #"skip_status": #"true"};
NSError *clientError;
NSURLRequest *request = [client URLRequestWithMethod:#"GET" URLString:#"https://api.twitter.com/1.1/account/verify_credentials.json" parameters:params error:nil];
Hope this helps someone!

Swift JSON Parsing Avoid method declaration for every view

I'm working on fetching data from json and manipulating it into a table view, but the problem is that I have many views, about 5-6 and in each one with separate class, and in each class I declare the same JSON Parsing method again and again, how can I avoid such repetition? I wanted to declare the method as class method in AppDelegate, but I ran into a problem:
After the return of json, I would use it in another function to extract the data, But I'm stuck over here with this error. Please help! If there's a better approach I would like to know.
Thank you
UPDATE
class func get_data_from_url(url:String) -> NSString
{
var json:NSString?
let url = NSURL(string: url)
let urlRequest = NSMutableURLRequest(URL: url!,
cachePolicy: .ReloadIgnoringLocalAndRemoteCacheData,
timeoutInterval: 15.0)
let queue = NSOperationQueue()
NSURLConnection.sendAsynchronousRequest(
urlRequest,
queue: queue,
completionHandler: {(response: NSURLResponse!,
data: NSData!,
error: NSError!) in
if data == nil {
dispatch_async(dispatch_get_main_queue(), {
let alert = UIAlertView()
alert.title = "Connection Error"
alert.message = "Could not connect to the server"
alert.addButtonWithTitle("Ok")
alert.show()
});
}
else {
if data.length > 0 && error == nil{
json = NSString(data: data, encoding: NSASCIIStringEncoding)
}else if data.length == 0 && error == nil{
println("Nothing was downloaded")
return
} else if error != nil{
println("Error happened = \(error)")
return
}
}
}
)
return json!
}
I'm getting an error at the last line, "return json!" -> "fatal error: unexpectedly found nil while unwrapping an Optional value"
Any Suggestions?
Try something like this : your ClassB is where you load the json, so from Class A, you call the method loadJson, and when the json has been downloaded in Class B, you send the json back to Class A :
//Class A :
ClassB.loadJson{ (success, json) -> Void in
if (success) //... you use the json
//println("receive json from Class B, use it here")
return
}
//ClassB
typealias OnComplete = (Bool, NSString) -> ()
class func loadJson(completion:OnComplete){
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), { () -> Void in
//json = ... load your json here
dispatch_async(dispatch_get_main_queue(), { () -> Void in
println("json loaded")
completion(true, json) //send result back to Class A
})//main
}

Resources