How to load Image into UIButton Swift From HTTP Request - ios

I have been getting images from my API and in the past I have loaded them into a UIImage with the extension you will see below. However, now I am trying to get the images from the API and load them into UIButton image views. I don't know what to do to the extension and the other code to make it work. I appreciate the help!
Extension
Extension UIImageView {
func getURL2(url: URL, contentMode mode: UIViewContentMode = .scaleAspectFit) {
contentMode = mode
URLSession.shared.dataTask(with: url) { data, response, error in
guard
let httpURLResponse = response as? HTTPURLResponse, httpURLResponse.statusCode == 200,
let mimeType = response?.mimeType, mimeType.hasPrefix("image"),
let data = data, error == nil,
let image = UIImage(data: data),
httpURLResponse.url == url
else { return }
DispatchQueue.main.async() {
self.image = image
}
}.resume()
}
func downloadedFrom2(link: String, contentMode mode: UIViewContentMode = .scaleAspectFit) {
guard let url = URL(string: link) else { return }
getURL2(url: url, contentMode: mode)
}
}
Other code
func loadProfilePhoto(image: UIButton, link: String) {
image.downloadedFrom2(link: link)
image.imageView!.clipsToBounds = true
image.imageView!.layer.cornerRadius = (image.imageView!.frame.height) / 2
image.imageView!.contentMode = .scaleAspectFill
}
func loadRandom8() {
if self.users.count == 8 {
let completelink1 = users[0].picture_url
//ex. https://api.adorable.io/avatars/200/AngelicAlling.png
let completelink2 = users[1].picture_url
let completelink3 = users[2].picture_url
let completelink4 = users[3].picture_url
let completelink5 = users[4].picture_url
let completelink6 = users[5].picture_url
let completelink7 = users[6].picture_url
let completelink8 = users[7].picture_url
loadProfilePhoto(image: p2Image, link: completelink1)
loadProfilePhoto(image: p2Image, link: completelink2)
loadProfilePhoto(image: p3Image, link: completelink3)
loadProfilePhoto(image: p4Image, link: completelink4)
loadProfilePhoto(image: p5Image, link: completelink5)
loadProfilePhoto(image: p6Image, link: completelink6)
loadProfilePhoto(image: p7Image, link: completelink7)
loadProfilePhoto(image: p8Image, link: completelink8)

Your current extension is for UIImageView but you want to load the image in a UIButton, so change the extension to UIButton and make sure the button's type is set to Custom and not System. You can do this from the storyboard.
extension UIButton {
func getURL2(url: URL, contentMode mode: UIViewContentMode = .scaleAspectFit) {
contentMode = mode
URLSession.shared.dataTask(with: url) { data, response, error in
guard
let httpURLResponse = response as? HTTPURLResponse, httpURLResponse.statusCode == 200,
let mimeType = response?.mimeType, mimeType.hasPrefix("image"),
let data = data, error == nil,
let image = UIImage(data: data),
httpURLResponse.url == url
else { return }
DispatchQueue.main.async() {
self.setImage(image, for: .normal)
self.imageView?.contentMode = mode
}
}.resume()
}
public func downloadedFrom2(link: String, contentMode mode: UIViewContentMode = .scaleAspectFit) {
guard let url = URL(string: link) else { return }
getURL2(url: url, contentMode: mode)
}
}
If it didn't work for you read this

Related

How to parse partial link in swift 4?

I am trying to show an image into my table cell view from an API. But it has given a partial link there, as a result, I am getting NSURL connection error code -1002.
Here is my API link: https://api.opendota.com/api/heroStats
I am trying to parse "icon" among them:
"img": "/apps/dota2/images/heroes/antimage_full.png?",
"icon": "/apps/dota2/images/heroes/antimage_icon.png",
My code:
// Generating imageview
if let imageURL = URL(string: heroes[indexPath.row].icon){
print (imageURL)
DispatchQueue.global().async {
let data = try? Data (contentsOf: imageURL)
if let data = data {
let image = UIImage(data: data)
DispatchQueue.main.async {
cell.charIcon.image = image
} //end of 2nd dispatch
}//end of if
}//end of 1st dispatch
}// end of imageURL
How can I solve this problem? Any easy way for swift 4?
You can get the url components of your api link and use your icon "partial link" to set the path property of the URL components. After that you just need to get the resulting url of the url components:
let apiLink = "https://api.opendota.com/api/heroStats"
let apiURL = URL(string: apiLink)!
if var urlComponents = URLComponents(url: apiURL, resolvingAgainstBaseURL: false) {
let iconString = "/apps/dota2/images/heroes/antimage_icon.png"
urlComponents.path = iconString
if let iconURL = urlComponents.url {
print(iconURL.absoluteString)
}
}
This will print
https://api.opendota.com/apps/dota2/images/heroes/antimage_icon.png
You can create a custom method to return a new URL based on the new path string as follow:
extension URL {
var urlComponents: URLComponents? {
return URLComponents(url: self, resolvingAgainstBaseURL: false)
}
func bySettingNew(path: String) -> URL? {
guard var urlComponents = urlComponents else { return nil }
urlComponents.path = path
return urlComponents.url
}
}
let apiLink = "https://api.opendota.com/api/heroStats"
let apiURL = URL(string: apiLink)!
let iconString = "/apps/dota2/images/heroes/antimage_icon.png"
if let iconURL = apiURL.bySettingNew(path: iconString) {
print(iconURL.absoluteString)
}
You can also add this helper to your project to make it easier for you to download an image asynchronously into your image view:
extension UIImageView {
func downloaded(from url: URL, contentMode mode: UIView.ContentMode = .scaleAspectFit) {
URLSession.shared.dataTask(with: url) { data, response, error in
guard
let httpURLResponse = response as? HTTPURLResponse, httpURLResponse.statusCode == 200,
let mimeType = response?.mimeType, mimeType.hasPrefix("image"),
let data = data, error == nil,
let image = UIImage(data: data)
else { return }
DispatchQueue.main.async() { [weak self] in
self?.contentMode = mode
self?.image = image
}
}.resume()
}
}
if let imageURL = apiURL.bySettingNew(path: heroes[indexPath.row].icon) {
cell.charIcon.downloaded(from: imageURL)
}

Custom marker on google map as per below image

I want to add custom markers as per follow. I have method for markers on google map, But I want to put users image on marker pin as per below. I have transparent marker image and I want to load user image from url. So image must dynamic. So I cannot put static markers.
//Add Marker
func dropMarker(_ location : CLLocation, _ isHotelLocation: Bool = false,_ memberModel : membersModel? = nil){
let marker = GMSMarker()
let position = self.checkIfMutlipleCoordinates(latitude: Float(location.coordinate.latitude), longitude: Float(location.coordinate.longitude))
marker.position = position
if isHotelLocation == false{
if let url = URL.init(string: memberModel!.avatar_url ?? ""){
let imageView = UIImageView(image: UIImage.init(named: "locationPin"))
imageView.sd_setImage(with: url, placeholderImage: UIImage.init(named: "locationPin"))
marker.iconView = imageView
}else{
marker.icon = UIImage(named : "LocationPlaceholderPin")
}
marker.userData = memberModel
}else{
marker.icon = UIImage(named : "hotelMarker")
hotelLocationMarker = marker
}
marker.map = mapView
arrMarkers.append(marker)
}
Use this extension for downloading image from server:
extension UIImageView {
func downloaded(from url: URL, contentMode mode: UIViewContentMode = .scaleAspectFit) { // for swift 4.2 syntax just use ===> mode: UIView.ContentMode
contentMode = mode
URLSession.shared.dataTask(with: url) { data, response, error in
guard
let httpURLResponse = response as? HTTPURLResponse, httpURLResponse.statusCode == 200,
let mimeType = response?.mimeType, mimeType.hasPrefix("image"),
let data = data, error == nil,
let image = UIImage(data: data)
else { return }
DispatchQueue.main.async() {
self.image = image
}
}.resume()
}
func downloaded(from link: String, contentMode mode: UIViewContentMode = .scaleAspectFit) { // for swift 4.2 syntax just use ===> mode: UIView.ContentMode
guard let url = URL(string: link) else { return }
downloaded(from: url, contentMode: mode)
}
}
then add the image as subview to marker image:
var userImage = UIImageView()
userImage.downloaded(from: "user image url")
let userMarkerImage = UIImageView(named: "your marker placeholder")
userMarkerImage.addsubView(userImage)
then set the image to marker:
marker.icon = userMarkerImage
Note
You should set the frame of image before adding as subview

How to show/convert oData weblink to UIImage in Swift?

I am getting image from microsoft account by using this api :
https://graph.microsoft.com/beta/me/photo
And this api gets this data which is shown in output. But i don't know how to show this link into image in Swift.
Output :
"#odata.context" = "https://graph.microsoft.com/beta/$metadata#users('rahulchopra.93%40outlook.com')/photo/$entity";
"#odata.mediaContentType" = "image/jpeg";
height = 2;
id = 2X2;
width = 2;
Create extension of UIImageView
extension UIImageView {
func downloaded(from url: URL, contentMode mode: UIViewContentMode = .scaleAspectFit) {
contentMode = mode
URLSession.shared.dataTask(with: url) { data, response, error in
guard
let httpURLResponse = response as? HTTPURLResponse, httpURLResponse.statusCode == 200,
let mimeType = response?.mimeType, mimeType.hasPrefix("image"),
let data = data, error == nil,
let image = UIImage(data: data)
else { return }
DispatchQueue.main.async() {
self.image = image
}
}.resume()
}
func downloaded(from link: String, contentMode mode: UIViewContentMode = .scaleAspectFit) {
guard let url = URL(string: link) else { return }
downloaded(from: url, contentMode: mode)
}
}
and Use like this
imageView.downloaded(from: "http://www.apple.com/euro/ios/ios8/a/generic/images/og.png")

How to add flag image from an API?

import UIKit
class DetailsViewController: UIViewController {
#IBOutlet weak var alpha3CodeLbl: UILabel!
#IBOutlet weak var regionLbl: UILabel!
#IBOutlet weak var flagImage: UIImageView!
var countrie:jsonStruct?
override func viewDidLoad() {
super.viewDidLoad()
alpha3CodeLbl.text = countrie?.alpha3Code
regionLbl.text = countrie?.region
let urlString = "http://restcountries.eu/rest/v2/all" + (countrie?.flag)!
flagImage.downloadedFrom(url: url!)
}
}
extension UIImageView {
func downloadedFrom(url: URL, contentMode mode: UIViewContentMode = .scaleAspectFit) {
contentMode = mode
URLSession.shared.dataTask(with: url) { data, response, error in
guard
let httpURLResponse = response as? HTTPURLResponse, httpURLResponse.statusCode == 200,
let mimeType = response?.mimeType, mimeType.hasPrefix("image"),
let data = data, error == nil,
let image = UIImage(data: data)
else { return }
DispatchQueue.main.async() {
self.image = image
}
}.resume()
}
func downloadedFrom(link: String, contentMode mode: UIViewContentMode = .scaleAspectFit) {
guard let url = URL(string: link) else { return }
downloadedFrom(url: url, contentMode: mode)
}
}
I'm trying to get the flag image form this API http://restcountries.eu/rest/v2/all
There is no error but the image does not appear. But there is no result if there anyone here can fix this issue.
Please, not that everything is okay and try to get the image in too many ways but still no result.
Also, I try this
let urlString = "http[enter image description
here][1]://restcountries.eu" + (countrie?.flag)!
A few things to fix. You should test the url before using it.
let str = "yourURL"
guard let theUrl = URL(string: str) else { return }
As mentioned by #rmaddy in a comment above, UIImage isn't going to work with SVG files. Use a UIWebView instead
var request = URLRequest(url:theUrl)
webView.loadRequest(request)
Or try SVGKit to convert SVG as described here

Async image loading from url inside a UITableView cell - wrong image loading while scrolling

I have a tableView that displays an image in the cell. Most of the time the correct image will be displayed, however occasionally it will display the wrong image (usually if scrolling down the tableView very quickly). I download the images asynchronously.
cell.profImg.getImgFromUrl(link: man.img, contentMode: cell.profImg.contentMode)
And here i do async request:
extension UIImageView {
func getImgFromUrl(link link:String, contentMode mode: UIViewContentMode) {
guard
let url = NSURL(string: link)
else {return}
contentMode = mode
NSURLSession.sharedSession().dataTaskWithURL(url, completionHandler: { (data, response, error) -> Void in
guard
let httpURLResponse = response as? NSHTTPURLResponse where httpURLResponse.statusCode == 200,
let mimeType = response?.MIMEType where mimeType.hasPrefix("image"),
let data = data where error == nil,
let image = UIImage(data: data)
else { return }
dispatch_async(dispatch_get_main_queue()) { () -> Void in
self.image = image
}
}).resume()
}
}
I think it's because you do not reset the content of your UIImageView when you start loading you HTTP image. So, when the cell is reused, you display the previously loaded image.
You just have to start your getImgFromUrl by something like self.image = nil (if you want a blank image) or self.image = myPlaceholderImage (if you want a placeholder image during the loading time). Here is how to integrate it in your code:
extension UIImageView {
func getImgFromUrl(link: String, contentMode mode: UIView.ContentMode) {
guard let url = URL(string: link) else { return }
contentMode = mode
URLSession.shared.dataTask(with: url, completionHandler: { (data, response, error) -> Void in
guard
let httpURLResponse = response as? HTTPURLResponse, httpURLResponse.statusCode == 200,
let mimeType = response?.mimeType, mimeType.hasPrefix("image"),
let data = data, error == nil, let image = UIImage(data: data) else { return }
DispatchQueue.main.async {
self.image = image
}
}).resume()
}
}
But I think you should consider the use of SDWebImage. This library provides a category for UIImageView with support for remote images coming from the web. It will be much more efficient and easier for you.

Resources