Getting crash reported in crashlytics about partial apply for closure - ios

I am getting a crash reported in firebase related with - partial apply for closure. I tried answers on SO but they mainly says about use of [Weak self], I used it but still getting crash report of same. However not facing crash on my device.
Snapshot of crash report is this:
Related code of Network Manager is this:
//MARK: POST Methods for API Calls
func postRequest(urlString: String,
params:[String : Any],
view:UIView,
token:String,
success:#escaping (SuccessHandler),
failure:#escaping (ErrorHandler)) {
showProgressView(in: view)
let url = self.baseURL.appendingPathComponent(urlString)
var urlRequest = URLRequest(url: url)
urlRequest.httpMethod = "POST"
if token != "" {
urlRequest.addValue("\(token)", forHTTPHeaderField: "token")
}
urlRequest.networkServiceType = .default
urlRequest.cachePolicy = .reloadRevalidatingCacheData
urlRequest.timeoutInterval = 100
urlRequest.httpShouldHandleCookies = true
urlRequest.httpShouldUsePipelining = false
urlRequest.allowsCellularAccess = true
do {
urlRequest.httpBody = try JSONSerialization.data(withJSONObject: params, options: [])
}
catch let error as NSError {
print(error.localizedDescription)
}
let task = defaultSession.dataTask(with: urlRequest, completionHandler: { [weak self] (data, response, error) -> () in
self?.hideProgressView()
guard error == nil else {
failure(error!)
return
}
let statusCode = (response as? HTTPURLResponse)?.statusCode
if urlString.contains("signin") {
let token = (response as? HTTPURLResponse)?.value(forHTTPHeaderField: "token")
UserDefaults.standard.setValue(token, forKey: "authToken")
}
switch statusCode {
case 200:
if let aData = data {
do {
let responseJSON = try JSONSerialization.jsonObject(with: aData, options: [])
success(responseJSON) // Line no 160 mentioned in crash report
}
catch let error as NSError {
failure(error)
}
}
case 404:
if let aData = data {
do {
let responseJSON = try JSONSerialization.jsonObject(with: aData, options: [])
let dictObj = responseJSON as? [String: Any] ?? [String: Any]()
let message = dictObj["message"] ?? ""
let error = NSError(domain: "", code: 0, userInfo: [NSLocalizedDescriptionKey : message])
failure(error)
}
catch let error as NSError {
failure(error)
}
}
default:
self?.logger.error("New Http Response Code")
}
})
task.resume()
}
Login Class method from where this api call is invocated:
func loginAPICall() {
email = txtFieldUsername.text ?? ""
let password = txtFieldPassword.text ?? ""
let params = ["username" : email,"password":password]
NetworkManager.shared().postRequest(urlString: API.signIn, params: params, view: self.view, token: "") { (response) in
let arrObj = response as? [AnyObject] ?? [AnyObject]()
let dictObj = arrObj[0] as? [String: Any] ?? [String: Any]()
self.saveUserdata(dict: dictObj)
DispatchQueue.main.async {
let vc = self.storyboard?.instantiateViewController(identifier: ViewControllerIdentifier.ProfileLandingId) as! ProfileLandingVC
vc.modalPresentationStyle = .fullScreen
self.present(vc, animated: true, completion: nil)
}
} failure: { (error) in
print("error")
}
}
Earlier i was not using [weak self], recently added after following some answers. Can someone suggest a solution for it?

Related

How to save one person UID globally to retrieve it in any ViewController in Swift

After successful registration, I am getting UID in LoginViewController. I am saving UID in LoginViewController. and I am retrieving UID in RegistrationViewController. but here I am getting nil for all person why?
Please help me in the code.
saving UID in LoginViewController:
func logInService(){
let parameters = ["username":Int(userIdTextFielf.text ?? "") as Any,
"imei_number":"",
"password":passwordTextField.text as Any,
"name":"name"]
let url = URL(string: "https://dev.com/webservices/login")
var req = URLRequest(url: url!)
req.httpMethod = "POST"
guard let httpBody = try? JSONSerialization.data(withJSONObject: parameters as Any, options: .prettyPrinted) else {return}
req.httpBody = httpBody
let session = URLSession.shared
session.dataTask(with: req, completionHandler: {(data, response, error) in
if response != nil {
// print(response)
}
if let data = data {
do{
let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as! [String: Any]
print("the json of loginnnnnn \(json)")
self.Uid = json["id"] as? Int
let emailL = json["user_email"] as? String
KeychainWrapper.standard.set(emailL ?? "", forKey: "user_email")
KeychainWrapper.standard.set(self.Uid!, forKey: "Uid")
let saveUserId: Bool = KeychainWrapper.standard.set(self.Uid!, forKey: "Uid")
DispatchQueue.main.async {
let mainStoryBoard = UIStoryboard(name: "Main", bundle: nil)
let navigationController = mainStoryBoard.instantiateViewController(withIdentifier: "HomeNavigation")
let appDelagate = UIApplication.shared.delegate
appDelagate?.window??.rootViewController = navigationController
}
}catch{
print("error")
}
}
}).resume()
}
retrieving UID in RegistrationViewController:
#IBAction func registerButton(_ sender: Any) {
if (nameTextField.text == "" || phoneNumTextField.text == "" || passwordTextField.text == "" || conformPasswordTextField.text == "")
{
registerButton.isHidden = false
sendOtpButton.isHidden = true
AlertFun.ShowAlert(title: "Title", message: "RequiredAllFields", in: self)
}
else{
registerButton.isHidden = true
sendOtpButton.isHidden = false
otpTextField.isHidden = false
resendButn.isHidden = false
DispatchQueue.main.async {
self.otpTextField.text = self.otpField as? String
}
registerService()
otpTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(update), userInfo: nil, repeats: true)
}
}
#IBAction func sendOTPButton(_ sender: Any) {
otpService()
}
//MARK:- Service part
#objc func registerService()
{
print("register tapped")
let parameters = ["mobile_number": Int(phoneNumTextField.text ?? "") as Any,
"email":emailTextField.text as Any,
"password":passwordTextField.text as Any,
"name": nameTextField.text as Any]
let url = URL(string: "https://dev.anyemi.com/webservices/anyemi/register")
var req = URLRequest(url: url!)
req.httpMethod = "POST"
guard let httpBody = try? JSONSerialization.data(withJSONObject: parameters, options: .prettyPrinted) else {return}
req.httpBody = httpBody
let session = URLSession.shared
session.dataTask(with: req, completionHandler: {(data, response, error) in
if response != nil {
// print(response)
}
if let data = data {
do{
let userId: Int? = KeychainWrapper.standard.integer(forKey: "Uid")
print("login userid \(userId)")
if userId != nil{
AlertFun.ShowAlert(title: "Title", message: "user exist", in: self)
}
else{
let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as! [String: Any]
print("the json regggggggggggis \(json)")
let phNum = json["mobile_number"] as? Int
let status = json["status"] as? String
self.otpField = json["otp"] as? Int
}
}catch{
print("error")
}
}
}).resume()
}
#objc func otpService(){
let parameters = ["mobile_number": phoneNumTextField.text as Any,
"otp": otpTextField.text as Any]
let url = URL(string: "https://dev.com/webservices/otpverify")
var req = URLRequest(url: url!)
req.httpMethod = "POST"
guard let httpBody = try? JSONSerialization.data(withJSONObject: parameters, options: .prettyPrinted) else {return}
req.httpBody = httpBody
let session = URLSession.shared
session.dataTask(with: req, completionHandler: {(data, response, error) in
if response != nil {
// print(response)
}
if let data = data {
do{
let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as! [String: Any]
print("the json of otppppppppp \(json)")
DispatchQueue.main.async {
if (self.otpTextField.text == String(self.otpField ?? 12)){
print("registration successfullllll...")
let mobileNum = json["mobile_number"] as! [String : Any]
//self.Uid = mobileNum["id"] as? String
let name = mobileNum["name"] as? String
let phNum = mobileNum["username"] as? String
print("otp name \(String(describing: name))")
print("otp phnumber \(String(describing: phNum))")
let loginVC = self.storyboard?.instantiateViewController(withIdentifier: "LoginViewController") as! LoginViewController
self.present(loginVC, animated: true)
}
else if self.otpTextField.text == ""{
AlertFun.ShowAlert(title: "", message: "Please enter OTP", in: self)
print("register fail")
}
else {
AlertFun.ShowAlert(title: "", message: "Invalid OTP", in: self)
print("register fail")
}
}
}catch{
print("error")
}
}
}).resume()
}
}
All the time I am going to else part why? where I did mistake.
KeychainWrapper is not a good approach to save user details. Better to go with "UserDefaults".

How to reload new data to UITable when one row data is deleted or updated in swift IOS?

So for I've a UITableView in which I'm showing comments which is fetch from my localhost DB, when a user post comment it's send to localhost and store there and it the same time I reload table and the comment is shown it the time but when a user delete a comment or update a comment then in the DB data is actually deleted or updated but my tableview is not reloading with new data till I close the view and open it again.
following is my code.
This my delete comment code:
#objc func deleteComment(){
ProgressHUD.show("Wait Deleting", interaction: false)
customView.removeFromSuperview()
var commentArray : Dictionary<String, Any> = [:]
commentArray["commentId"] = self.getCommentId
let myUrl = URL(string: "http://127.0.0.1:8000/api/comment/delete");
var request = URLRequest(url:myUrl!)
request.httpMethod = "POST"// Compose a query string
request.addValue("application/json", forHTTPHeaderField: "Content-type")
guard let httpbody = try? JSONSerialization.data(withJSONObject: commentArray, options: []) else { return }
request.httpBody = httpbody
let task = URLSession.shared.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in
if error != nil
{
print("error=\(error)")
return
}
// print out response object
// print("response = \(response)")
//Let's convert response sent from a server side script to a NSDictionary object:
do {
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary
if let parseJSON = json {
if parseJSON["delete"] != nil{
ProgressHUD.dismiss()
self.alertDeleted()
}else {
if parseJSON["error"] != nil{
ProgressHUD.dismiss()
print(parseJSON["error"] as Any)
}
}
}
} catch {
print(error)
}
}
task.resume()
}
This is delete comment alert.
public func alertDeleted(){
let alertController = UIAlertController(title: "Comment Deleted:", message: "Press Ok to continue.", preferredStyle: .alert)
let confirmAction = UIAlertAction(title: "Ok", style: .default) { (_) in
self.showMatchCommentsApiCall()
}
alertController.addAction(confirmAction)
self.present(alertController, animated: true, completion: nil)
}
This is update comment code.
#objc func updateComment(){
ProgressHUD.show("Wait Upating", interaction: false)
updateCommentView.removeFromSuperview()
var commentArray : Dictionary<String, Any> = [:]
commentArray["commentId"] = self.getCommentId
commentArray["updatedComment"] = textView.text
let myUrl = URL(string: "http://127.0.0.1:8000/api/comment/update");
var request = URLRequest(url:myUrl!)
request.httpMethod = "POST"// Compose a query string
request.addValue("application/json", forHTTPHeaderField: "Content-type")
guard let httpbody = try? JSONSerialization.data(withJSONObject: commentArray, options: []) else { return }
request.httpBody = httpbody
let task = URLSession.shared.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in
if error != nil
{
print("error=\(error)")
return
}
// print out response object
//print("response = \(response)")
//Let's convert response sent from a server side script to a NSDictionary object:
do {
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary
if let parseJSON = json {
if parseJSON["update"] != nil{
ProgressHUD.dismiss()
self.alertCommentUpdated()
self.showMatchCommentsApiCall()
return
}else {
if parseJSON["error"] != nil{
ProgressHUD.dismiss()
print(parseJSON["error"] as Any)
}
}
}
} catch {
print(error)
}
}
task.resume()
}
My ShowMatchCommentsApiCall() function.
public func showMatchCommentsApiCall(){
ProgressHUD.show("Please Wait", interaction: false)
guard let url = URL(string: "http://127.0.0.1:8000/api/matchComments/\(getMatchId)") else {return}
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
guard let dataResponse = data,
error == nil else {
print(error?.localizedDescription ?? "Response Error")
return }
do{
//here dataResponse received from a network request
let jsonResponse = try JSONSerialization.jsonObject(with:
dataResponse, options: [])
// print(jsonResponse) //Response result
guard let jsonArray = jsonResponse as? [[String: Any]] else {
return
}
//print(jsonArray)
for comments in jsonArray{
guard let commentID = comments["commentId"] as? Int else { return }
guard let userID = comments["userId"] as? Int else { return }
guard let userName = comments["userName"] as? String else { return }
let userImgUrl = comments["userImg"] as? String
if userImgUrl != nil{
self.commentsUserImgUrl.append(userImgUrl!)
}else {
self.commentsUserImgUrl.append("nil")
}
guard let commentMessage = comments["comment"] as? String else { return }
self.commentId.append(commentID)
self.commmentsUserId.append(userID)
self.commentsUserName.append(userName)
self.comments.append(commentMessage)
}
} catch let parsingError {
print("Error", parsingError)
}
DispatchQueue.main.async {
self.MatchScoreTable.reloadData()
ProgressHUD.dismiss()
}
}
task.resume()
}
STEP 1. :self.commentsArray.remove(at: indexPath.row)
STEP 2. : self.tableView.deleteRows(at:[indexPath],with:UITableViewRowAnimation.automatic)
STEP 3. : self.tableView.reloadData()
After deleting or updating data just call a UITableView method reloadData
Syntax is as follows :
tableView.reloadData()

Invalid conversion from throwing function of type '(_, _, _) throws -> ()' to non-throwing function type '(URLResponse?, Data?, Error?) -> Void

I'm attempting to follow a tutorial from Ray Wenderlich's website to learn to use Instruments. The sample code is written is Swift 2 I believe so before I'm allowed to run it, I have to migrate the code to the latest Swift version. I've gotten half-way through the conversion errors but I'm stumped on the following area of code:
class Flickr {
let processingQueue = OperationQueue()
func searchFlickrForTerm(_ searchTerm: String, completion : #escaping (_ results: FlickrSearchResults?, _ error : NSError?) -> Void){
let searchURL = flickrSearchURLForSearchTerm(searchTerm)
let searchRequest = URLRequest(url: searchURL)
NSURLConnection.sendAsynchronousRequest(searchRequest, queue: processingQueue) {response, data, error in
if error != nil {
completion(nil,error as! NSError)
return
}
var JSONError : NSError?
let resultsDictionary = try JSONSerialization.jsonObject(with: data!, options: []) as? NSDictionary
if JSONError != nil {
completion(nil, JSONError)
return
}
switch (resultsDictionary!["stat"] as! String) {
case "ok":
print("Results processed OK")
case "fail":
let APIError = NSError(domain: "FlickrSearch", code: 0, userInfo: [NSLocalizedFailureReasonErrorKey:resultsDictionary!["message"]!])
completion(results: nil, error: APIError)
return
default:
let APIError = NSError(domain: "FlickrSearch", code: 0, userInfo: [NSLocalizedFailureReasonErrorKey:"Unknown API response"])
completion(nil, APIError)
return
}
let photosContainer = resultsDictionary!["photos"] as! NSDictionary
let photosReceived = photosContainer["photo"] as! [NSDictionary]
let flickrPhotos : [FlickrPhoto] = photosReceived.map {
photoDictionary in
let photoID = photoDictionary["id"] as? String ?? ""
let title = photoDictionary["title"] as? String ?? ""
let farm = photoDictionary["farm"] as? Int ?? 0
let server = photoDictionary["server"] as? String ?? ""
let secret = photoDictionary["secret"] as? String ?? ""
let flickrPhoto = FlickrPhoto(photoID: photoID, title: title, farm: farm, server: server, secret: secret)
return flickrPhoto
}
DispatchQueue.main.async(execute: {
completion(FlickrSearchResults(searchTerm: searchTerm, searchResults: flickrPhotos), nil)
})
}
}
fileprivate func flickrSearchURLForSearchTerm(_ searchTerm:String) -> URL {
let escapedTerm = searchTerm.addingPercentEscapes(using: String.Encoding.utf8)!
let URLString = "https://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=\(apiKey)&text=\(escapedTerm)&per_page=30&format=json&nojsoncallback=1"
return URL(string: URLString)!
}
}
I get the error on the following line of code:
NSURLConnection.sendAsynchronousRequest(searchRequest, queue: processingQueue) {response, data, error in
if error != nil {
completion(nil,error as! NSError)
return
}
I'm a little confused on how this should be amended using do, try, catch so any help would be appreciated just so I can get the app running to play around with Instruments.
Here is a link to the tutorial: https://www.raywenderlich.com/97886/instruments-tutorial-with-swift-getting-started
replace your Flickr class with this.
class Flickr {
let processingQueue = OperationQueue()
func searchFlickrForTerm(_ searchTerm: String, completion : #escaping (_ results: FlickrSearchResults?, _ error : NSError?) -> Void){
let searchURL = flickrSearchURLForSearchTerm(searchTerm)
let searchRequest = URLRequest(url: searchURL)
NSURLConnection.sendAsynchronousRequest(searchRequest, queue: processingQueue) {response, data, error in
guard let data = data, error == nil else {
completion(nil, error as NSError?)
return
}
guard let jsonObject = try? JSONSerialization.jsonObject(with: data,
options: JSONSerialization.ReadingOptions(rawValue: 0)),
let resultsDictionary = jsonObject as? Dictionary<String, Any>
else
{
return
}
switch (resultsDictionary["stat"] as! String) {
case "ok":
print("Results processed OK")
case "fail":
let APIError = NSError(domain: "FlickrSearch", code: 0, userInfo: [NSLocalizedFailureReasonErrorKey:resultsDictionary["message"]!])
completion(nil, APIError)
return
default:
let APIError = NSError(domain: "FlickrSearch", code: 0, userInfo: [NSLocalizedFailureReasonErrorKey:"Unknown API response"])
completion(nil, APIError)
return
}
let photosContainer = resultsDictionary["photos"] as! NSDictionary
let photosReceived = photosContainer["photo"] as! [NSDictionary]
let flickrPhotos : [FlickrPhoto] = photosReceived.map {
photoDictionary in
let photoID = photoDictionary["id"] as? String ?? ""
let title = photoDictionary["title"] as? String ?? ""
let farm = photoDictionary["farm"] as? Int ?? 0
let server = photoDictionary["server"] as? String ?? ""
let secret = photoDictionary["secret"] as? String ?? ""
let flickrPhoto = FlickrPhoto(photoID: photoID, title: title, farm: farm, server: server, secret: secret)
return flickrPhoto
}
DispatchQueue.main.async(execute: {
completion(FlickrSearchResults(searchTerm: searchTerm, searchResults: flickrPhotos), nil)
})
}
}
fileprivate func flickrSearchURLForSearchTerm(_ searchTerm:String) -> URL {
let escapedTerm = searchTerm.addingPercentEscapes(using: String.Encoding.utf8)!
let URLString = "https://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=\(apiKey)&text=\(escapedTerm)&per_page=30&format=json&nojsoncallback=1"
return URL(string: URLString)!
}
}
Sorry spacing is all messed up but the issue is you're not doing error handling correctly. When you do JSONSerialization it can throw so you have to wrap it in a do catch block or you can use ! to ignore the throw and crash if it throws an error or ? to return nil if it fails.

Can't get data from Dark Sky API

I try to get information about the weather hourly from the Dark Sky API, but the code stops working at the if let data = hourly["data"] as? [String : AnyObject] line (checked with printing stuff after every line). I want to know what is wrong with my code. I think it could be something with the "data" let, but I don't know for sure.
let Task2 = URLSession.shared.dataTask(with: urlRequestDark) { (data, response, error) in
if error == nil {
do {
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [String : AnyObject]
if let hourly = json["hourly"] as? [String : AnyObject] {
if let data = hourly["data"] as? [String : AnyObject]{
if let hourNum = data["14"] as? [String : AnyObject] {
if let chanceRain = hourNum["precipProbability"] as? Float{
self.chanceHour1 = String(chanceRain)
}
DispatchQueue.main.sync {
self.ChanceRainLabel.text = self.chanceHour1
}
}
}
}
} catch let jsonError {
print(jsonError.localizedDescription)
}
}
}
Task2.resume() test
The strange part is, this does work:
let urlRequestDark = URLRequest(url: URL (string: "https://api.darksky.net/forecast/(API Key)/(coordinates)")!)
let Task = URLSession.shared.dataTask(with: urlRequestDark) { (data, response, error) in
if error == nil {
do{
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [String : AnyObject]
if let currently = json["currently"] as? [String : AnyObject] {
if let chance2 = currently["precipProbability"] as? Float{
print(String(chance2))
self.chance = String(Int(chance2 * 100)) + "%"
self.PreType = currently["precipType"] as? String
}
if let _ = json["error"]{
}
DispatchQueue.main.sync{
self.TypeLabel.text = self.PreType
self.ChanceLabel.text = self.chance
}
}
}catch let jsonError{
print(jsonError.localizedDescription)
}
}
}
Task.resume()
You've made couple mistakes.
First, "data" is an array of dictionaries, so it should be cast to [[String : AnyObject]].
Second, you're trying to subscript array by String, not Int.
Third, using self in escaping closures potentially creates retain cycles.
Let me propose you some fixed and adjusted code.
let task2 = URLSession.shared.dataTask(with: urlRequestDark) { [weak self] (data, response, error) in
guard error == nil else { return }
do {
if let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? [String : AnyObject],
let hourly = json["hourly"] as? [String : AnyObject],
let data = hourly["data"] as? [[String : AnyObject]],
data.count > 14,
let chanceRain = data[14]["precipProbability"] as? Float {
self?.chanceHour1 = String(chanceRain)
DispatchQueue.main.sync {
self?.ChanceRainLabel.text = self?.chanceHour1
}
}
} catch let jsonError {
print(jsonError.localizedDescription)
}
}
task2.resume()
Try like this
import UIKit
class WebService: NSObject {
var session = URLSession()
public class var sharedInstance: WebService {
struct Singleton {
static let instance = WebService()
}
return Singleton.instance
}
override init() {
let configuration = URLSessionConfiguration.default
configuration.timeoutIntervalForRequest = 30.0
configuration.timeoutIntervalForResource = 60.0
session = URLSession(configuration: configuration)
}
public func weatherData(coordinate:String,APIkey:String,completion:#escaping (_ responsedata:NSDictionary?,_ error:NSError?) -> Void) {
var Baseurl = "https://api.darksky.net/forecast/\(APIkey)/\(coordinate)"
Baseurl = Baseurl.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
let weatherRequestUrl = URL(string: Baseurl)
let request = NSMutableURLRequest(url: weatherRequestUrl!)
let task = session.dataTask(with: request as URLRequest) { (data, response, error) in
guard error == nil && data != nil else {
return
}
if let httpStatus = response as? HTTPURLResponse{
if httpStatus.statusCode != 200 {
print("Something is wrong")
}
}
do {
let WindlocationData = try JSONSerialization.jsonObject(with: data! as Data, options:.allowFragments) as! NSDictionary
print(WindlocationData)
completion(WindlocationData,nil)
}
catch let error as NSError {
completion(nil,error)
}
}
task.resume()
}
}
And call API like this!
func callAPI(latlong:String,APIkeyParm:String) {
WebService.sharedInstance.weatherData(coordinate: latlong,APIkey: APIkeyParm) { (responsData, error) in
if error == nil{
print("Response data is-\(responsData)")
}
}
}
Call the method like this
let latlongStr = "\(latitude),\(longitude)"
self.callAPI(latlong: latlongStr,APIkeyParm: "APIKeyString")
One importent thing you need to pass latlong like this format 23.022504999999999,72.571362100000002

Swift do catch inside function doesn't work

I have a function which parses JSON, but I get a nil error dealing with the URL strings:
var jsonResponse: NSMutableDictionary?
do{
jsonResponse = try NSJSONSerialization.JSONObjectWithData(data!,
options: NSJSONReadingOptions.AllowFragments) as? NSMutableDictionary;
let info : NSArray = jsonResponse!.valueForKey("latest_receipt_info") as! NSArray
let transaction_id: String? = info[0].valueForKey("transaction_id") as? String
let purchase_date: String? = info[0].valueForKey("purchase_date") as? String
let product_id: String? = info[0].valueForKey("product_id") as? String
let web_order_line_item_id: String? = info[0].valueForKey("web_order_line_item_id") as? String
print("test")
// Send Values
let addIAPUrl:NSString = "http://bla.com/application/addIAP.php?transaction_id=\(transaction_id!)&purchase_date=\(purchase_date)&product_id=\(product_id)&web_order_line_item_id=\(web_order_line_item_id)&userID=\(prefs.valueForKey("userID") as! String!)"
self.apiRequests(addIAPUrl as String, completionHandler: { (success, message) -> Void in
print("success \(addIAPUrl)")
if(success == 1){
dispatch_async(dispatch_get_main_queue()){
// ADDED
print("success \(addIAPUrl)")
}
}else{
// DONT ADDED
}
})
The output doesn't return any error but the function fails after print("test"). The apiRequests function works in other cases, but doesn't seem to work in this context.
I would appreciate any help finding the problem.
Here is the code for the apiRequest function:
func apiRequests(url : String, completionHandler : ((success : Int, message : String) -> Void)) {
guard let url = NSURL(string: url as String) else {
return
}
let urlRequest = NSURLRequest(URL: url)
let config = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration: config)
let task = session.dataTaskWithRequest(urlRequest, completionHandler: { (data, response, error) in
guard let responseData = data else {
return
}
guard error == nil else {
print(error)
return
}
let post: NSDictionary
do {
post = try NSJSONSerialization.JSONObjectWithData(responseData,
options: []) as! NSDictionary
} catch {
return
}
let numberFromString = Int((post["success"] as? String)!)
completionHandler(success: (numberFromString)!, message: (post["message"] as? String)!)
})
task.resume()
}
It seems to me that the problem is most likely that your apiRequests: function is erroring at one of many places, and is returning instead of calling your callback with an error state.
func apiRequests(url : String, completionHandler : ((success : Int, message : String) -> Void)) {
guard let url = NSURL(string: url as String) else {
completionHandler(0, "Couldn't get URL")
return
}
let urlRequest = NSURLRequest(URL: url)
let config = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration: config)
let task = session.dataTaskWithRequest(urlRequest, completionHandler: { (data, response, error) in
guard let responseData = data else {
completionHandler(0, "Data was nil")
return
}
guard error == nil else {
print(error)
completionHandler(0, "Error wasn't nil")
return
}
let post: NSDictionary
do {
post = try NSJSONSerialization.JSONObjectWithData(responseData,
options: []) as! NSDictionary
} catch {
completionHandler(0, "Error with NSJSONSerialization")
return
}
let numberFromString = Int((post["success"] as? String)!)
completionHandler(success: (numberFromString)!, message: (post["message"] as? String)!)
})
task.resume()
}
Side note, but not related to the fix,
let addIAPUrl:NSString = "http://bla.com/application/addIAP.php?transaction_id=\(transaction_id!)&purchase_date=\(purchase_date)&product_id=\(product_id)&web_order_line_item_id=\(web_order_line_item_id)&userID=\(prefs.valueForKey("userID") as! String!)"
self.apiRequests(addIAPUrl as String, completionHandler: { (success, message) -> Void in
Can easily be replaced with
let addIAPUrl = "http://bla.com/application/addIAP.php?transaction_id=\(transaction_id!)&purchase_date=\(purchase_date)&product_id=\(product_id)&web_order_line_item_id=\(web_order_line_item_id)&userID=\(prefs.valueForKey("userID") as! String!)"
self.apiRequests(addIAPUrl, completionHandler: { (success, message) -> Void in
Because you are converting a String to an NSString then back to a String

Resources