How to download image from JSON using the Swift 3 and Alamofire? - ios

How to download image from JSON using Alamofire and Swift 3? I am getting dictionary of data. See the following JSON response. I am able to print data in labels but I can't download the image. This is the response I am getting from the API.
userJson userJson userJson userJson ["status": 1, "student": { "admission_date" = "14/06/2017";
"admission_no" = 13538; "class_teacher" = "Caroline Forbes"; dob =
"04/05/2001"; email = "ranisagar.sivadas#gmail.com"; "father_name" =
"SAGAR SIVADAS"; gender = Male; image =
"/system/images/86/j1f9DiJi_medium.jpg?1504593436"; "mother_name" =
"RANI R S"; name = "Abhijith Sagar"; phone = 9066260799; religion =
Hindu; "school_email" = "13538.861#demo.in"; "student_id" = 86; },
"message": Details fetched successfully.]
This is my code.
func SetUpUIProfiledata() {
APIManager.sharedInstance.getParentDataFromURL(){(userJson)-> Void in
let swiftyJsonVar = JSON(userJson)
print("userJson userJson userJson userJson",userJson)
print("swiftyJsonVar",swiftyJsonVar)
let message = swiftyJsonVar["message"].rawString()
let sudent = swiftyJsonVar["student"].rawString()!
let jsonData = sudent.data(using: .utf8)!
let dictionary = try? JSONSerialization.jsonObject(with: jsonData, options: []) as! Dictionary<String, Any>
self.name_lbl.text = dictionary?["name"] as? String
self.fatherName_lbl.text = dictionary?["father_name"] as? String
self.motherName_lbl.text = dictionary?["mother_name"] as? String
self.phone_lbl.text = dictionary?["phone"] as? String
self.email_lbl.text = dictionary?["email"] as? String
self.dob_lbl.text=dictionary?["dob"] as? String
self.gender_lbl.text=dictionary?["gender"] as? String
self.religion_lbl.text=dictionary?["religion"] as? String
self.admissionDate_lbl.text=dictionary?["admission_date"] as? String
self.admissionNum_lbl.text=dictionary?["admission_no"] as? String
self.schoolMail_lbl.text=dictionary?["school_email"] as? String
self.teacher_lbl.text=dictionary?["class_teacher"] as? String
}
}

Have a look at below code you just need to pass a link url to alamofire and you can download a image . if its not the expected answer please Re edit your question .
let strURL1:String = "https://www.planwallpaper.com/static/images/9-credit-1.jpg"
Alamofire.request(strURL1).responseData(completionHandler: { response in
debugPrint(response)
debugPrint(response.result)
if let image1 = response.result.value {
let image = UIImage(data: image1)
self.imageView.image = image
}
})
I looked at output you had provided you are getting
image =
"/system/images/86/j1f9DiJi_medium.jpg?1504593436";
is this a valid url or path if its a url you need to add your base url + your " /system/images/86/j1f9DiJi_medium.jpg?1504593436" and pass it to alamofire block to download image
as in my above example
"https://www.planwallpaper.com" - baseURl
"static/images/9-credit-1.jpg" - image Path as in your case
Hope it helps.

First get the image key corresponding value & marge it with your base URL. Like
let url = "www.yourbaseurlhere.com" + "/system/images/86/j1f9DiJi_medium.jpg?1504593436"
Now create a destination path for it like
let destination = DownloadRequest.suggestedDownloadDestination(
for: .documentDirectory,
in: .userDomainMask
)
Now use Alamofire download method like
Alamofire.download(url, to: destination)
.downloadProgress { progress in
print("Download Progress: \(progress.fractionCompleted)")
}
.responseData { response in
if response.result.value != nil {
if let directoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] as? URL {
let fileName = response.response?.suggestedFilename // get your file name here.
let finalPath = directoryURL.appendingPathComponent(fileName!) //get your file path here
}
}
}
Hope it helps.

Related

How to convert userdefault value to URL?

I'm trying to retrieve the URL from a UserDefault I saved previously, but parsing it to URL fails as states: "Cannot convert NSINLINEDATA to NSURL"
I've tried parsing it to String and then to URL but it only gives nil
Set value
let videourl = info["UIImagePickerControllerReferenceURL"] as? URL
if let videoURL = videourl{
defaults.set(videourl,forKey: "LullabyURL")
}
Get value
let videoURL = defaults.value(forKey: "LullabyURL")
let newStr = String(data: videoURL as! Data, encoding: .utf8)
let vu = URL.init(string:newStr ?? "nil")
let player = AVPlayer(url: vu!)
You can use built in method func url(forKey defaultName: String) -> URL? to retrieve URL as below,
if let defaultsUrl = UserDefaults.standard.url(forKey: "urlString") {
let player = AVPlayer(url: defaultsUrl)
}

Issues with calling an API taking too much time to get a response

I am calling API in iOS (swift). Everything works perfectly, but it's taking too much time while getting response approximately 40 or 60 seconds. I don't know why this is happening. Let me show you my API calling method:
Code
func userDetailAPI(){
let preferences = UserDefaults.standard
let uid = "u_id"
let acctkn = "acc_tkn"
if preferences.object(forKey: uid) == nil {
// Doesn't exist
} else {
let u_id = preferences.object(forKey: uid) as! String
print(u_id)
let acc_tkn = preferences.object(forKey: acctkn) as! String
print(acc_tkn)
let userprofile: [String : Any] = ["user_id":u_id,"access_token":acc_tkn]
print(userprofile)
Alamofire.request(userDetails, method: .post, parameters: userprofile).responseJSON { response in
print("RESPONSE : \(response)")
let result = response.result.value
if result != nil{
let data = result as! [String : AnyObject]
let userdata = data["data"] as! NSDictionary
let email = userdata["email"]
let name = userdata["name"]
let photo = userdata["photo"]
//let u_type = userdata["user_type"]!
self.lblUserName.text = name as? String
self.lblEmailID.text = email as? String
let proimgurl = NSURL(string: photo as! String)
self.imgProPic.image = UIImage(data: NSData(contentsOf: proimgurl! as URL)! as Data)
// }
}
}
}
}
Please check and help me - is this the right method for API calling or is there any other, better way?
Because of this line
self.imgProPic.image = UIImage(data: NSData(contentsOf: proimgurl! as URL)! as Data)
so you have almofire request plus blocking main thread until image is downloaded , so consider using the asynchronous , automatic cashing SDWebImage
self.imgProPic.sd_setImage(with: proimgurl!, placeholderImage: UIImage(named: "placeholder.png"))
Also in swift avoid using NS stuff like here
let userdata = data["data"] as! NSDictionary // use [String:Any]
and
let proimgurl = NSURL(string: photo as! String) // use URL
You should download the ImageView's image from Url in another thread. If you do it in the main thread, it'll slow down your app and ultimately run out of memory.
The below-given line is which causes the problem is below
self.imgProPic.image = UIImage(data: NSData(contentsOf: proimgurl! as URL)! as Data)
I suggest you use the SDWebImage library.
You can do like something below
let imageUrl = URL(string: photo as! String)
self.imgProPic.image.sd_setImage(with: imageUrl, placeholderImage: UIImage(named: "profile"), options: .refreshCached, completed: nil)
If this doesn't solve your problem, try calling the same web service using API clients such as Postman. If it's taking the same amount of time, then you can't do much about it. Ask the web service developer to optimize the performance.
Hey by the way there is also alamofire image pod is available.
https://github.com/Alamofire/AlamofireImage
eg:
do import AlamofireImage into your file and call image url like below:
Alamofire.request(image_url, method: .get).responseImage(completionHandler: { (response) in
self.your_UIImage_variable.image = response.result.value
})

Saving api Facebook data for use in different ViewController swift iOS

I'm hitting Facebook's graph to pull basic user info when the user logs in. My question is how do I use swift to save/pull that information in the best way so that it persists across the child viewcontrollers thereafter (basically everything after login). For instance, I want to use the profile pic as a settings button throughout the app after the login screen (not in it) in my login view controller I have this relevant code:
let userImageView: UIImageView = {
let imageView = UIImageView()
return imageView
}()
let nameLabel: UILabel = {
let label = UILabel()
return label
}()
and then later:
func fetchProfile() {
let parameters = ["fields": "email, first_name, last_name, picture.type(large)"]
FBSDKGraphRequest(graphPath: "me", parameters: parameters).startWithCompletionHandler({ (connection, user, requestError) -> Void in
if requestError != nil {
print(requestError)
return
}
var _ = user["email"] as? String
let firstName = user["first_name"] as? String
let lastName = user["last_name"] as? String
self.nameLabel.text = "\(firstName!) \(lastName!)"
var pictureUrl = ""
if let picture = user["picture"] as? NSDictionary, data = picture["data"] as? NSDictionary, url = data["url"] as? String {
pictureUrl = url
}
let url = NSURL(string: pictureUrl)
NSURLSession.sharedSession().dataTaskWithURL(url!, completionHandler: { (data, response, error) -> Void in
if error != nil {
print(error)
return
}
let image = UIImage(data: data!)
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.userImageView.image = image
})
}).resume()
})
}
What do I need to do to access this in my second ViewController? From what I can understand, segues only help if I have a physical attribute in the first viewController to push them from.
Thanks
The best way to save images will be with Documents Directory as Core Data is not optimized for files as large as images. You would want to save the photo in Documents Directory as so......
func saveImageDocumentDirectory(){
let fileManager = NSFileManager.defaultManager()
let paths = (NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as NSString).stringByAppendingPathComponent(*** Name of DocDir Image***)
let image = // *** Your Facebook Image ***
print(paths)
let imageData = UIImageJPEGRepresentation(image!, 0.5)
fileManager.createFileAtPath(paths as String, contents: imageData, attributes: nil)
}
Then in your viewcontroller(s) create an empty public image var fbImage:UIImage() then create a getImage function and code as follows.....
func getImage()
{
let fileManager = NSFileManager.defaultManager()
let imagePAth = (self.getDirectoryPath() as NSString).stringByAppendingPathComponent(*** Name of Your DocDir Image ***)
if fileManager.fileExistsAtPath(imagePath){
self.fbImage.image = UIImage(contentsOfFile: imagePath)
}else{
print("No Image Saved")
}
}

How to access data in nested JSON in swift

I have a json file
I need to get the latest "id": "article" "createdAt": "2016-04-22T03:38:39.130Z" date. How do I go about getting this data from the request in swift?
Note: Sorry im a swift newb.
let url = "https://cdn.contentful.com/spaces/maz0qqmvcx21/entries?access_token=ae8163cb8390af28cd3d7e28aba405bac8284f9fe4375a605782170aef2b0b48";
var jsonData:NSData?
do{
jsonData = try NSData(contentsOfURL: NSURL(string: url)!, options: NSDataReadingOptions.DataReadingUncached)
let jsonObject:AnyObject? = try NSJSONSerialization.JSONObjectWithData(jsonData!, options: NSJSONReadingOptions.AllowFragments)
if let itemArray = jsonObject?.objectForKey("items") as? NSArray{
for item in itemArray{
if let sysItem = item.objectForKey("sys"){
//this is createdAt
if let createdAt = sysItem.objectForKey("createdAt") as? String{
print("createdAt:\(createdAt)")
}
if let contentTypeItem = sysItem.objectForKey("contentType")!.objectForKey("sys"){
//this is id
if let id = contentTypeItem.objectForKey("id") as? String{
print("id:\(id)")
}
}
}
}
}
}catch let err as NSError{
print("err:\(err)")
}
This code dosen't use any libraries,but you can use SwiftyJSON,this is will be easy to parse json.
Hope this help.
This can be done in simple way. I am assuming that you have parsed your json to dictionary
You have a key with items which is an array of dictionary and inside that dictionary you have createdAt and id(well it is deeper into the hierarchy but I will show you how to get it) keys. You can access it by simply doing this.
for dict in jsonDict["items"] as! Array<NSDictionary> {
let sysDict = dict["sys"] as! NSDictionary
print(sysDict["createdAt"]) //prints all createdAt in the array
let contentDict = sysDict["contentType"]
print((contentDict["sys"] as! NSDictionary)["id"]) // prints all ids
}
Hope this helps.

SwiftyJSON - issues with parsing

I try to parse json with SwiftyJSON. One of the fields have url to image and i try to save it as NSData but I face crash and console errors. Crash appears when compiler comes to object creation
code it the following
var JSONStorage : [Article?]?
var objects = [Article?]()
override func viewDidLoad() {
super.viewDidLoad()
let number = arc4random_uniform(1000)
let urlString = "http://wirehead.ru/article.json?\(number)"
if let url = NSURL(string: urlString) {
if let data = try? NSData(contentsOfURL: url, options: []) {
let json = JSON(data: data)
for element in json["article"].arrayValue {
let id = Int(element["id"].stringValue)
let title = element["title"].stringValue
let subtitle = element["subtitle"].stringValue
let body = element["body"].stringValue
let img = element["images"]["main"].rawValue
let obj:Article = Article(id: id!, title: title, subtitle: subtitle, body: body, mainImage: img as! NSData)
objects.append(obj)
print("We are inside if let")
}
}
}
print(objects)
}
Link to JSON is http://wirehead.ru/article.json and here is with highlight http://pastebin.com/AAEFjsQN
Error that I get is
Any advice ?
["images"]["main"] contains an URL represented by a String
To get the image data, use something like this
let imgURLString = element["images"]["main"].stringValue
if let url = NSURL(string:imgURLString) {
let img = NSData(contentsOfURL:url)
}

Resources