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
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".
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()
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.
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
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