Если вы хотите проверить, существует ли программа и действительно ли это программа, а не встроенная команда bash, тогда command
, type
и hash
не подходят для тестирования, поскольку все они возвращают 0 выход статус для встроенных команд.
Например, есть программа времени, которая предлагает больше возможностей, чем встроенная команда времени. Чтобы проверить, существует ли программа, я бы предложил использовать which
, как в следующем примере:
# first check if the time program exists
timeProg=`which time`
if [ "$timeProg" = "" ]
then
echo "The time program does not exist on this system."
exit 1
fi
# invoke the time program
$timeProg --quiet -o result.txt -f "%S %U + p" du -sk ~
echo "Total CPU time: `dc -f result.txt` seconds"
rm result.txt
Xcode 8 • Swift 3
Синхронно:
if let filePath = Bundle.main.path(forResource: "imageName", ofType: "jpg"), let image = UIImage(contentsOfFile: filePath) {
imageView.contentMode = .scaleAspectFit
imageView.image = image
}
Асинхронно:
Создайте метод с обработчиком завершения, чтобы получить данные изображения из вашего url
func getData(from url: URL, completion: @escaping (Data?, URLResponse?, Error?) -> ()) {
URLSession.shared.dataTask(with: url, completionHandler: completion).resume()
}
Создайте способ загрузки изображения (запустите задачу)
func downloadImage(from url: URL) {
print("Download Started")
getData(from: url) { data, response, error in
guard let data = data, error == nil else { return }
print(response?.suggestedFilename ?? url.lastPathComponent)
print("Download Finished")
DispatchQueue.main.async() {
self.imageView.image = UIImage(data: data)
}
}
}
Использование:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
print("Begin of code")
if let url = URL(string: "http://www.apple.com/euro/ios/ios8/a/generic/images/og.png") {
imageView.contentMode = .scaleAspectFit
downloadImage(from: url)
}
print("End of code. The image will continue downloading in the background and it will be loaded when it ends.")
}
Расширение:
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)
}
}
Использование:
imageView.downloaded(from: "http://www.apple.com/euro/ios/ios8/a/generic/images/og.png")
Swift 2.0:
1)
if let url = NSURL(string: "http://etc...") {
if let data = NSData(contentsOfURL: url) {
imageURL.image = UIImage(data: data)
}
}
ИЛИ
imageURL.image =
NSURL(string: "http:// image name...")
.flatMap { NSData(contentsOfURL: $0) }
.flatMap { UIImage(data: $0) }
2) Добавьте этот метод в VC или Extension.
func load_image(urlString:String)
{ let imgURL: NSURL = NSURL(string: urlString)!
let request: NSURLRequest = NSURLRequest(URL: imgURL)
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()) { (response: NSURLResponse?, data: NSData?, error: NSError?) in
if error == nil {
self.image_element.image = UIImage(data: data)
}
}
}
Использование:
self.load_image(" url strig here")
let url = NSURL.URLWithString("http://live-wallpaper.net/iphone/img/app/i/p/iphone-4s-wallpapers-mobile-backgrounds-dark_2466f886de3472ef1fa968033f1da3e1_raw_1087fae1932cec8837695934b7eb1250_raw.jpg");
var err: NSError?
var imageData :NSData = NSData.dataWithContentsOfURL(url,options: NSDataReadingOptions.DataReadingMappedIfSafe, error: &err)
var bgImage = UIImage(data:imageData)
Способ получения безопасного изображения и работы с Swift 2.0 и X-Code 7.1:
static func imageForImageURLString(imageURLString: String, completion: (image: UIImage?, success: Bool) -> Void) {
guard let url = NSURL(string: imageURLString),
let data = NSData(contentsOfURL: url),
let image = UIImage(data: data)
else {
completion(image: nil, success: false);
return
}
completion(image: image, success: true)
}
Затем вы вызываете этот метод следующим образом:
imageForImageURLString(imageString) { (image, success) -> Void in
if success {
guard let image = image
else { return } // Error handling here
// You now have the image.
} else {
// Error handling here.
}
}
Если вы обновляете представление с изображением, вам придется использовать его после «if success {»:
dispatch_async(dispatch_get_main_queue()) { () -> Void in
guard let image = image
else { return } // Error handling here
// You now have the image. Use the image to update the view or anything UI related here
// Reload the view, so the image appears
}
. Причина, по которой эта последняя часть необходима, если вы используете изображение в пользовательский интерфейс связан с тем, что сетевые вызовы требуют времени. Если вы попытаетесь обновить пользовательский интерфейс, используя изображение, не вызывая dispatch_async, как показано выше, компьютер будет искать изображение, пока изображение все еще будет извлечено, найдите, что изображения нет (пока), и двигайтесь так, как если бы не было изображения найденный. Поместив свой код в завершение закрытия dispatch_async, он говорит компьютеру: «Идите, получите это изображение, и когда вы закончите, заполните этот код». Таким образом, вы получите изображение, когда код будет вызван, и все будет хорошо работать.
Используйте этот код в Swift
imageView.image=UIImage(data: NSData(contentsOfURL: NSURL(string: "http://myURL/ios8.png")!)!
Swift 4
Этот метод будет загружать изображение с сайта асинхронно и кэшировать его:
func getImageFromWeb(_ urlString: String, closure: @escaping (UIImage?) -> ()) {
guard let url = URL(string: urlString) else {
return closure(nil)
}
let task = URLSession(configuration: .default).dataTask(with: url) { (data, response, error) in
guard error == nil else {
print("error: \(String(describing: error))")
return closure(nil)
}
guard response != nil else {
print("no response")
return closure(nil)
}
guard data != nil else {
print("no data")
return closure(nil)
}
DispatchQueue.main.async {
closure(UIImage(data: data!))
}
}; task.resume()
}
При использовании:
getImageFromWeb("http://www.apple.com/euro/ios/ios8/a/generic/images/og.png") { (image) in
if let image = image {
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
imageView.image = image
self.view.addSubview(imageView)
} // if you use an Else statement, it will be in background
}
Swift 2 с ошибкой Ручка и пользовательский заголовок запроса
Просто добавьте расширение в UIImageView:
extension UIImageView {
public func imageFromUrl(urlString: String) {
if let url = NSURL(string: urlString) {
let request = NSMutableURLRequest(URL: url)
request.setValue("<YOUR_HEADER_VALUE>", forHTTPHeaderField: "<YOUR_HEADER_KEY>")
NSURLSession.sharedSession().dataTaskWithRequest(request) {
(data, response, error) in
guard let data = data where error == nil else{
NSLog("Image download error: \(error)")
return
}
if let httpResponse = response as? NSHTTPURLResponse{
if httpResponse.statusCode > 400 {
let errorMsg = NSString(data: data, encoding: NSUTF8StringEncoding)
NSLog("Image download error, statusCode: \(httpResponse.statusCode), error: \(errorMsg!)")
return
}
}
dispatch_async(dispatch_get_main_queue(), {
NSLog("Image download success")
self.image = UIImage(data: data)
})
}.resume()
}
}
}
И затем используйте новый imageFromUrl(urlString: String)
для загрузки изображения
Использование:
imageView.imageFromUrl("https://i.imgur.com/ONaprQV.png")
Swift 2.x ответ, который загружает изображение в файл (в отличие от ответа Лео Дабуса, в котором хранится изображение в памяти). На основании ответа Льва Дабуса и ответа Роба из Получить данные из NSURLSession DownloadTaskWithRequest из обработчика завершения :
// Set download vars
let downloadURL = NSURL() // URL to download from
let localFilename = "foobar.png" // Filename for storing locally
// Create download request
let task = NSURLSession.sharedSession().downloadTaskWithURL(downloadURL) { location, response, error in
guard location != nil && error == nil else {
print("Error downloading message: \(error)")
return
}
// If here, no errors so save message to permanent location
let fileManager = NSFileManager.defaultManager()
do {
let documents = try fileManager.URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: false)
let fileURL = documents.URLByAppendingPathComponent(localFilename)
try fileManager.moveItemAtURL(location!, toURL: fileURL)
self.doFileDownloaded(fileURL, localFilename: localFilename)
print("Downloaded message @ \(localFilename)")
} catch {
print("Error downloading message: \(error)")
}
}
// Start download
print("Starting download @ \(downloadURL)")
task.resume()
// Helper function called after file successfully downloaded
private func doFileDownloaded(fileURL: NSURL, localFilename: String) {
// Do stuff with downloaded image
}
Я обернул код наилучших ответов на вопрос в один многоразовый класс, расширяющий UIImageView, поэтому вы можете напрямую использовать асинхронную загрузку UIImageViews в своем раскадровке (или создать их из кода).
Здесь это мой класс:
import Foundation
import UIKit
class UIImageViewAsync :UIImageView
{
override init()
{
super.init(frame: CGRect())
}
override init(frame:CGRect)
{
super.init(frame:frame)
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
func getDataFromUrl(url:String, completion: ((data: NSData?) -> Void)) {
NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: url)!) { (data, response, error) in
completion(data: NSData(data: data))
}.resume()
}
func downloadImage(url:String){
getDataFromUrl(url) { data in
dispatch_async(dispatch_get_main_queue()) {
self.contentMode = UIViewContentMode.ScaleAspectFill
self.image = UIImage(data: data!)
}
}
}
}
и вот как его использовать:
imageView.downloadImage("http://www.image-server.com/myImage.jpg")
Для Swift-3 и выше:
extension UIImageView {
public func imageFromUrl(urlString: String) {
if let url = URL(string: urlString) {
let request = URLRequest(url: url)
NSURLConnection.sendAsynchronousRequest(request as URLRequest, queue: .main, completionHandler: { (response, data, error) in
if let imageData = data as NSData? {
self.image = UIImage(data: imageData as Data)
}
})
}
}
}
Xcode 8 • Swift 3
Ответ Leo Dabus является потрясающим! Я просто хотел предоставить решение «все-в-одном»:
let url = URL(string:
"http://www.apple.com/euro/ios/ios8/a/generic/images/og.png")
let task = URLSession.shared.dataTask(with: url!) { data, response, error in
guard let data = data, error == nil else { return }
DispatchQueue.main.async() { // execute on main thread
self.imageView.image = UIImage(data: data)
}
}
task.resume()
Swift 4.1 У меня есть функция, которая просто передаёт URL-адрес изображения, кэш-ключ после создания изображения устанавливает его в блок завершения.
class NetworkManager: NSObject {
private var imageQueue = OperationQueue()
private var imageCache = NSCache<AnyObject, AnyObject>()
func downloadImageWithUrl(imageUrl: String, cacheKey: String, completionBlock: @escaping (_ image: UIImage?)-> Void) {
let downloadedImage = imageCache.object(forKey: cacheKey as AnyObject)
if let _ = downloadedImage as? UIImage {
completionBlock(downloadedImage as? UIImage)
} else {
let blockOperation = BlockOperation()
blockOperation.addExecutionBlock({
let url = URL(string: imageUrl)
do {
let data = try Data(contentsOf: url!)
let newImage = UIImage(data: data)
if newImage != nil {
self.imageCache.setObject(newImage!, forKey: cacheKey as AnyObject)
self.runOnMainThread {
completionBlock(newImage)
}
} else {
completionBlock(nil)
}
} catch {
completionBlock(nil)
}
})
self.imageQueue.addOperation(blockOperation)
blockOperation.completionBlock = {
print("Image downloaded \(cacheKey)")
}
}
}
}
extension NetworkManager {
fileprivate func runOnMainThread(block:@escaping ()->Void) {
if Thread.isMainThread {
block()
} else {
let mainQueue = OperationQueue.main
mainQueue.addOperation({
block()
})
}
}
}
Вы хотите сделать:
UIImage(data: data)
В Swift они заменили большинство стандартных методов Objective C на обычные конструкторы.
Смотрите:
Kingfisher - одна из лучших библиотек для загрузки изображения в URL.
blockquote>Github URL - https://github.com/onevcat/Kingfisher
// If you want to use Activity Indicator. imageview_pic.kf.indicatorType = .activity imageview_pic.kf.setImage(with: URL(string: "Give your url string")) // If you want to use custom placeholder image. imageview_pic.kf.setImage(with: URL(string: "Give your url string"), placeholder: UIImage(named: "placeholder image name"), options: nil, progressBlock: nil, completionHandler: nil)
FYI: для Swift-2.0 Xcode7.0 beta2
extension UIImageView {
public func imageFromUrl(urlString: String) {
if let url = NSURL(string: urlString) {
let request = NSURLRequest(URL: url)
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()) {
(response: NSURLResponse?, data: NSData?, error: NSError?) -> Void in
self.image = UIImage(data: data!)
}
}
}
}
(обновление Swift 4) Чтобы ответить на исходный вопрос напрямую, вот быстрый эквивалент опубликованного фрагмента Objective-C.
let url = URL(string: image.url)
let data = try? Data(contentsOf: url!) //make sure your image in this url does exist, otherwise unwrap in a if let check / try-catch
imageView.image = UIImage(data: data!)
ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ:
важно отметить, что метод Data(contentsOf:)
будет загружать содержимое URL синхронно в том же потоке, который выполняется кодом, поэтому не вызывайте его в основном потоке вашего приложения.
Простым способом для того, чтобы один и тот же код выполнялся асинхронно, а не для блокировки пользовательского интерфейса, - это использование GCD:
let url = URL(string: image.url)
DispatchQueue.global().async {
let data = try? Data(contentsOf: url!) //make sure your image in this url does exist, otherwise unwrap in a if let check / try-catch
DispatchQueue.main.async {
imageView.image = UIImage(data: data!)
}
}
При этом в реальных приложениях, если вы хотите иметь лучший пользовательский интерфейс и избегать нескольких загрузок то же изображение, вы можете захотеть также, чтобы они не только загружались, но и кэшировались. Там уже довольно много библиотек, которые делают это очень бесшовно, и все они очень просты в использовании. Я лично рекомендую Kingfisher :
import Kingfisher
let url = URL(string: "url_of_your_image")
// this downloads the image asynchronously if it's not cached yet
imageView.kf.setImage(with: url)
И это все
swift 3 с обработкой ошибок
let url = URL(string: arr[indexPath.row] as! String)
if url != nil {
DispatchQueue.global().async {
let data = try? Data(contentsOf: url!) //make sure your image in this url does exist, otherwise unwrap in a if let check / try-catch
DispatchQueue.main.async {
if data != nil {
cell.imgView.image = UIImage(data:data!)
}else{
cell.imgView.image = UIImage(named: "default.png")
}
}
}
}
С расширением
extension UIImageView {
func setCustomImage(_ imgURLString: String?) {
guard let imageURLString = imgURLString else {
self.image = UIImage(named: "default.png")
return
}
DispatchQueue.global().async {
let data = try? Data(contentsOf: URL(string: imageURLString)!)
DispatchQueue.main.async {
self.image = data != nil ? UIImage(data: data!) : UIImage(named: "default.png")
}
}
}
}
Использование расширения
myImageView. setCustomImage ( "URL")
Если вы ищете очень простую реализацию. (Это работало для меня в Swift 2)
let imageURL = NSURL(string: "https://farm2.staticflickr.com/1591/26078338233_d1466b7da2_m.jpg")
let imagedData = NSData(contentsOfURL: imageURL!)!
imageView?.image = UIImage(data: imagedData)
Я реализовал в представлении таблицы с пользовательской ячейкой, которая имеет только изображение
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
let cell = tableView.dequeueReusableCellWithIdentifier("theCell", forIndexPath: indexPath) as! customTableViewCell
let imageURL = NSURL(string: "https://farm2.staticflickr.com/1591/26078338233_d1466b7da2_m.jpg")
let imagedData = NSData(contentsOfURL: imageURL!)!
cell.imageView?.image = UIImage(data: imagedData)
return cell
}
func NKPlaceholderImage(image:UIImage?, imageView:UIImageView?,imgUrl:String,compate:@escaping (UIImage?) -> Void){
if image != nil && imageView != nil {
imageView!.image = image!
}
var urlcatch = imgUrl.replacingOccurrences(of: "/", with: "#")
let documentpath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
urlcatch = documentpath + "/" + "\(urlcatch)"
let image = UIImage(contentsOfFile:urlcatch)
if image != nil && imageView != nil
{
imageView!.image = image!
compate(image)
}else{
if let url = URL(string: imgUrl){
DispatchQueue.global(qos: .background).async {
() -> Void in
let imgdata = NSData(contentsOf: url)
DispatchQueue.main.async {
() -> Void in
imgdata?.write(toFile: urlcatch, atomically: true)
let image = UIImage(contentsOfFile:urlcatch)
compate(image)
if image != nil {
if imageView != nil {
imageView!.image = image!
}
}
}
}
}
}
}
Использовать следующим образом:
// Here imgPicture = your imageView
// UIImage(named: "placeholder") is Display image brfore download and load actual image.
NKPlaceholderImage(image: UIImage(named: "placeholder"), imageView: imgPicture, imgUrl: "Put Here your server image Url Sting") { (image) in }
Swift 4: простой загрузчик для небольших изображений (например, миниатюр), который использует NSCache и всегда работает по основному потоку:
class ImageLoader {
private static let cache = NSCache<NSString, NSData>()
class func image(for url: URL, completionHandler: @escaping(_ image: UIImage?) -> ()) {
DispatchQueue.global(qos: DispatchQoS.QoSClass.background).async {
if let data = self.cache.object(forKey: url.absoluteString as NSString) {
DispatchQueue.main.async { completionHandler(UIImage(data: data as Data)) }
return
}
guard let data = NSData(contentsOf: url) else {
DispatchQueue.main.async { completionHandler(nil) }
return
}
self.cache.setObject(data, forKey: url.absoluteString as NSString)
DispatchQueue.main.async { completionHandler(UIImage(data: data as Data)) }
}
}
}
Использование:
ImageLoader.image(for: imageURL) { image in
self.imageView.image = image
}
Использование Ascyimageview вы можете легко загрузить imageurl в imageview.
let image1Url: URL = URL (строка: "(imageurl)" как String)! imageview.imageURL = image1Url
Единственное, чего не хватает, это:!
let url = NSURL.URLWithString("http://live-wallpaper.net/iphone/img/app/i/p/iphone-4s-wallpapers-mobile-backgrounds-dark_2466f886de3472ef1fa968033f1da3e1_raw_1087fae1932cec8837695934b7eb1250_raw.jpg");
var err: NSError?
var imageData :NSData = NSData.dataWithContentsOfURL(url!,options: NSDataReadingOptions.DataReadingMappedIfSafe, error: &err)
var bgImage = UIImage(data:imageData!)
Если вы просто хотите загрузить изображение (асинхронно!) - просто добавьте это небольшое расширение в ваш быстрый код:
extension UIImageView {
public func imageFromUrl(urlString: String) {
if let url = NSURL(string: urlString) {
let request = NSURLRequest(URL: url)
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()) {
(response: NSURLResponse?, data: NSData?, error: NSError?) -> Void in
if let imageData = data as NSData? {
self.image = UIImage(data: imageData)
}
}
}
}
}
И используйте его следующим образом:
myImageView.imageFromUrl("https://robohash.org/123.png")
Swift 2.2 || Xcode 7.3
У меня получились потрясающие результаты !! с быстрой библиотекой AlamofireImage
blockquote>Он предоставляет множество функций, таких как:
- Асинхронно скачать
- Авто-очистка кэша изображений, если для приложения обнаружены предупреждения о памяти
- Кэширование URL-адреса изображения
- Кэширование изображений
- Избегайте дублирования загрузок
и очень легко реализуется для вашего приложения
Шаг.1 Установите контейнеры
Alamofire 3.3.x
pod 'Alamofire'
blockquote>AlamofireImage 2.4.x
pod 'AlamofireImage'
blockquote>Шаг 2. Импорт и использование
import Alamofire import AlamofireImage let downloadURL = NSURL(string: "http://cdn.sstatic.net/Sites/stackoverflow/company/Img/photos/big/6.jpg?v=f4b7c5fee820")! imageView.af_setImageWithURL(downloadURL)
вот и все! он позаботится обо всем
Огромное спасибо ребятам из Alamofire , для облегчения жизни iDevelopers;)