Previously in my APP when I was making a call to the server if there were any errors I did the following:
Alamofire.request(mutableURLRequest).responseJSON{
response in if let JSON = response.result.value{
if JSON.count != 0{
let errorList = JSON["responseErrorsList"] as? NSArray
for error in errorList!{
let erro: String = error as! String
switch erro{
case "PersonRequired":
With the migration from swift 2 to swift 4 I am having problems because theList errors comes to nil however the result of JSON is as follows:
["Rate": , "Level": , "Code": , "ID": 0, "Zone": , "Address": , "ErrorsListServer": <__NSSingleObjectArrayI 0x17400ba90>( InvalidCode ) , "SubZone": ]
Does anyone know how I can access the "ErrorsListServer" field and fetch the errors that in this case is "InvalidCode".
What I have implemented and is not working for is the following:
if let JSON = response.result.value as? [String: Any]{
if (JSON as AnyObject).count != 0{
let errorList = JSON["responseErrorsList"] as? [[String: Any]]
From your JSON response, you need to access key ErrorsListServer and it is Array of String not Array of Dictionary so you need to cast it to [String]. Also you can reduce your code with single if let statement like this way.
if let JSON = response.result.value as? [String: Any],
let errorList = JSON["ErrorsListServer"] as? [String] {
for error in errorList {
print(error)
}
}
Related
as a coding exercise, I wrote a small program to take MySql data frm the web to the iPhone. On the server side. I wrote the php script to get the script to return the json data.
On xcode I have
[code]
.
.
.
let jsonString = try? JSONSerialization.jsonObject(with: data!, options: [])
print(jsonString!)
.
.
.
[/code]
In xcode console, I have this:
[code]
(
{
Address = "1 Infinite Loop Cupertino, CA";
Latitude = "37.331741";
Longitude = "-122";
Name = Apple;
}
)
[/code]
I have a function
[code]
func convertToDictionary(text: String) -> [String: Any]? {
if let data = text.data(using: .utf8) {
do {
return try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
} catch {
print(error.localizedDescription)
}
}
return nil
}
[/code]
When I pass the jsonString to convertToDictionary(text:)
[code]
let dict = convertToDictionary(text: jsonString as! String)
[/code]
In the console I get an error "Could not cast value of type '__NSSingleObjectArrayI' (0x10369bdb0) to 'NSString' (0x1004eac60)."
but if I hard code the json string then pass it to the convertToDictionary(text:)
[code]
let hardCodedStr = "{\"Address\":\"1 Infinite Loop Cupertino, CA\",\"Latitude\":\"37.331741\",\"Longitude\":\"-122\",\"Name\":\"Apple\"}"
let dict = convertToDictionary(text: hardCodedStr)
print(dict!)
[/code]
It works just fine. Why is that? Thanks
If you look closely at what jsonObject(with:options:) returns, you will see that it is a [String: Any] or a [Any], depending on your JSON.
Therefore, jsonString here actually stores a [String: Any], even thought the compiler thinks it is of type Any:
let jsonString = try? JSONSerialization.jsonObject(with: data!, options: [])
print(jsonString!)
If you try to pass this to convertToDictionary, which accepts a String, it of course will not work, because a dictionary and String are not compatible types.
How to solve this problem?
The problem is already solved! You don't need convertToDictionary at all. jsonString itself is the dictionary you wanted.
This is what you need to do:
let jsonString = try? JSONSerialization.jsonObject(with: data!, options: []) as! [String: Any]
^^^^^^^^^^^^^^^^^
Add this part
After that you can call dictionary methods on jsonString. I also suggest you to rename jsonString to something else.
I am struck on it because there is no AFHTTPRequestoperation to find difficult on it. please use on afnetworking 3.0 in swift.
AFHTTPRequestoperation class removed in Afnetworking 3.0
https://github.com/AFNetworking/AFNetworking/wiki/AFNetworking-3.0-Migration-Guide
Try this:
func PostData(){
let parameters : NSMutableDictionary? = [
"UserID": String(300),
"UserProfileID": String(356)]
let manager = AFHTTPSessionManager()
let serializerRequest = AFJSONRequestSerializer()
serializerRequest.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
manager.requestSerializer = serializerRequest
let serializerResponse = AFJSONResponseSerializer()
serializerResponse.readingOptions = JSONSerialization.ReadingOptions.allowFragments
serializerResponse.acceptableContentTypes = ((((NSSet(object: "application/json") as! Set<String>) as Set<String>) as Set<String>) as Set<String>) as Set<String>;
manager.responseSerializer = serializerResponse
manager.post(Webserive.DefaultProfile, parameters: parameters, progress: nil, success: { (task: URLSessionDataTask, responseObject: Any?) in
if (responseObject as? [String: AnyObject]) != nil {
print("responseObject \(responseObject)")
}
}) { (task: URLSessionDataTask?, error: Error) in
print("POST fails with error \(error)")
}
}
Just use Alamofire if you need to implement it on swift. Check answer here which shows example of Alamofire post method.
I am trying to parse the JSON data from my server and I am getting an error when it hits the try! statement and it is crashing. It is telling me
Code=3840 "Invalid value around character 0.
It my be because I have not updated my code correctly to Swift 3. I was having an issue with if let parse for the longest time until I switched the as to as?
#IBAction func registerButtonTapped(_ sender: Any) {
let userEmail = userEmailTextField.text;
let userPassword = userPasswordTextField.text;
let userRepeatPassword = repeatPasswordTextField.text;
// Check for empty fields
if((userEmail?.isEmpty)! || (userPassword?.isEmpty)! || (userRepeatPassword?.isEmpty)!){
//Display alert message
displayMyAlertMessage(userMessage: "All fields are required");
return;
}
//Check if passwords matech
if(userPassword != userRepeatPassword){
// Display alert message
displayMyAlertMessage(userMessage: "Passwords do not match");
return;
}
// Send user data to server side
let myUrl = URL(string: "http://");
let request = NSMutableURLRequest(url:myUrl!);
request.httpMethod = "Post";
let postString = "email=\(userEmail)&password=\(userPassword)";
//adding the parameters to request body
request.httpBody = postString.data(using: String.Encoding.utf8);
//creating a task to send the post request
let task = URLSession.shared.dataTask(with: request as URLRequest){
data, response, error in
if error != nil{
print("error=\(error)")
return
}
//parsing the reponse
//converting response to Any
let json = try! JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.allowFragments) as? [String:Any]
//parsing JSON
if let parseJSON = json{
let resultValue = parseJSON["status"] as? String
print("result: \resultValue)")
var isUserRegistered:Bool = false;
if(resultValue=="Success") { isUserRegistered = true;}
var messageToDisplay:String = parseJSON["messsage"] as! String;
if(!isUserRegistered)
{
messageToDisplay = parseJSON["message"] as! String;
}
DispatchQueue.main.async {
//Display alert message with confirmation.
let myAlert = UIAlertController(title:"Alert", message:messageToDisplay, preferredStyle: UIAlertControllerStyle.alert);
let okAction = UIAlertAction(title:"ok", style:UIAlertActionStyle.default){ action in
self.dismiss(animated: true, completion:nil);
}
myAlert.addAction(okAction);
self.present(myAlert, animated:true, completion:nil);
};
}
}
task.resume()
}
Please help, thanks
The reason of the error is that you are sending literal "Optional(Foo)" strings to the server via String Interpolation. userEmail and userPassword will never match and the server sends no data back. In Swift 3 you have to explicitly unwrap even implicit unwrapped optional strings.
The solution is a waterproof error handling with optional bindings
#IBAction func registerButtonTapped(_ sender: AnyObject) {
// Check for empty fields
guard let userEmail = userEmailTextField.text, !userEmail.isEmpty,
let userPassword = userPasswordTextField.text, !userPassword.isEmpty,
let userRepeatPassword = repeatPasswordTextField.text, !userRepeatPassword.isEmpty else {
//Display alert message
displayMyAlertMessage(userMessage: "All fields are required")
return
}
...
Now all relevant optionals are safely unwrapped and the server will get the right data.
Further trailing semicolons and parentheses around if conditions are not needed in Swift and use URLRequest rather than NSMutableURLRequest in Swift 3
var request = URLRequest(url:myUrl!) // var is mandatory if properties are going to be changed.
PS: In any case – as already mentioned in the comments – never use carelessly try! when receiving data from a server.
Here is my code that is returning a false instead of the json array count.
I must comment that at one point it was working and then it stopped. Please help.
let task = NSURLSession.sharedSession().dataTaskWithURL(url!, completionHandler: { (data, response, error) -> Void in
let urlError = false
if error == nil {
let urlContent = NSString(data: data!, encoding: NSUTF8StringEncoding) as NSString!
let data: NSData = urlContent.dataUsingEncoding(NSUTF8StringEncoding)!
print("data here\(data)”) // I see a lot of data in the logs with this print
do {
let jsonObject = try (NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers) as? NSArray)!
print(“here is the array count\(jsonObject.count)”) // it never prints this to the logs. What I get is “false"
…The rest of the code...
I just want to request data from Facebook's Graph API, e.g. get the current user's basic info.
The Objective-C doc is: https://developers.facebook.com/docs/ios/graph#userinfo
[FBRequestConnection startForMeWithCompletionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
if (!error) {
/* My question: How do I read the contents of "result" in Swift? */
// Success! Include your code to handle the results here
NSLog(#"user info: %#", result);
} else {
// An error occurred, we need to handle the error
// See: https://developers.facebook.com/docs/ios/errors
}
}];
There's no Swift doc yet, and I'm confused about the "result" parameter whose type is "id".
It looks like result contains a dictionary, but it may be nil. In Swift, its type will map to AnyObject?.
So, in Swift, you could do something like:
// Cast result to optional dictionary type
let resultdict = result as? NSDictionary
if resultdict != nil {
// Extract a value from the dictionary
let idval = resultdict!["id"] as? String
if idval != nil {
println("the id is \(idval!)")
}
}
This can be simplified a bit:
let resultdict = result as? NSDictionary
if let idvalue = resultdict?["id"] as? String {
println("the id value is \(idvalue)")
}
Just remember it is not a dictionary all the way down, it is combinations of dictionaries and arrays.
FBRequestConnection.startWithGraphPath("me?fields=feed", completionHandler: { (connection, result, error) -> Void in
if( error == nil){
let fbGraphObject = result as FBGraphObject
let feed = fbGraphObject.objectForKey("feed") as NSMutableDictionary
let data = feed.objectForKey("data") as NSMutableArray
let postDescription = data[0].objectForKey("description") as String
//println( post )
self.fbu.initialUserFeed = feed
self.performSegueWithIdentifier("SelectStreams", sender: self)
}else
{
//TODO Allert to user that something went wrong
println(error)
}
})
I got confused about this in the beginning
This is a simpler way:
let params: [NSObject : AnyObject] = ["redirect": false, "height": 800, "width": 800, "type": "large"]
let pictureRequest = FBSDKGraphRequest(graphPath: "me/picture", parameters: params, HTTPMethod: "GET")
pictureRequest.startWithCompletionHandler({
(connection, result, error: NSError!) -> Void in
if error == nil {
print("\(result)")
let dictionary = result as? NSDictionary
let data = dictionary?.objectForKey("data")
let urlPic = (data?.objectForKey("url"))! as! String
print(urlPic)
} else {
print("\(error)")
}
})
}