创建加载图像/ activity 指示器,直到图像显示在 swift 中的屏幕上
create a loading image/ activity indicator, until the image is shown in the screen in swift
我想在从网站下载图像时在屏幕上显示一个 activity 指示器 url 然后在 images.image 中显示这是我下面的代码。每次我下载图像时,它都会立即打印状态,并且 activity 指示器永远不会出现。一直在网上搜索,但我还是不明白。请帮忙
let mygroup = DispatchGroup()
var activityIndicator = UIActivityIndicatorView()
func downloadpic(sender:UIButton){
let catPictureURL = URL(string: addr)!
// Creating a session object with the default configuration.
// You can read more about it here https://developer.apple.com/reference/foundation/urlsessionconfiguration
let session = URLSession(configuration: .default)
// Define a download task. The download task will download the contents of the URL as a Data object and then you can do what you wish with that data.
let downloadPicTask = session.dataTask(with: catPictureURL) { (data, response, error) in
// The download has finished.
if let e = error {
print("Error downloading cat picture: \(e)")
} else {
// No errors found.
// It would be weird if we didn't have a response, so check for that too.
if let res = response as? HTTPURLResponse {
// put loading screen here
self.activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: .white)
self.activityIndicator.frame = CGRect(x: 0, y: 0, width: 46, height: 46)
self.activityIndicator.startAnimating()
self.mygroup.enter()
print("downloading image")
print("Downloaded cat picture with response code \(res.statusCode)")
if let imageData = data {
// Finally convert that Data into an image and do what you wish with it.
self.images.image = UIImage(data: imageData)
self.mygroup.leave()
print("image already downloaded")
self.activityIndicator.stopAnimating()
self.activityIndicator.hidesWhenStopped = true
// Do something with your image.
} else {
print("Couldn't get image: Image is nil")
}
} else {
print("Couldn't get response code for some reason")
}
}
}
downloadPicTask.resume()
}
您遇到了这个问题,因为:
- 您没有将
activityIndicator
添加到任何视图
- 您在
completionHandler
块中配置了 activityIndicator
让我们在 activityIndicator
中配置 viewDidLoad()
方法:
self.activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: .gray)
self.activityIndicator.frame = CGRect(x: 0, y: 0, width: 46, height: 46)
self.activityIndicator.hidesWhenStopped = true
view.addSubview(self.activityIndicator)
并在恢复 dataTask
之前开始对其进行动画处理
self.activityIndicator.startAnimating()
然后,停止在 completionHandler
self.activityIndicator.stopAnimating()
最终代码:
let mygroup = DispatchGroup()
var activityIndicator = UIActivityIndicatorView()
override func viewDidLoad() {
super.viewDidLoad()
self.activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: .gray)
self.activityIndicator.frame = CGRect(x: 0, y: 0, width: 46, height: 46)
self.activityIndicator.hidesWhenStopped = true
view.addSubview(self.activityIndicator)
}
func downloadpic(sender: UIButton) {
let catPictureURL = URL(string: addr)!
// Creating a session object with the default configuration.
// You can read more about it here https://developer.apple.com/reference/foundation/urlsessionconfiguration
let session = URLSession(configuration: .default)
// Define a download task. The download task will download the contents of the URL as a Data object and then you can do what you wish with that data.
self.activityIndicator.startAnimating()
let downloadPicTask = session.dataTask(with: catPictureURL) { (data, response, error) in
// The download has finished.
if let e = error {
print("Error downloading cat picture: \(e)")
} else {
// No errors found.
// It would be weird if we didn't have a response, so check for that too.
if let res = response as? HTTPURLResponse {
// put loading screen here
self.mygroup.enter()
print("downloading image")
print("Downloaded cat picture with response code \(res.statusCode)")
if let imageData = data {
// Finally convert that Data into an image and do what you wish with it.
self.images.image = UIImage(data: imageData)
self.mygroup.leave()
print("image already downloaded")
self.activityIndicator.stopAnimating()
// Do something with your image.
} else {
print("Couldn't get image: Image is nil")
}
} else {
print("Couldn't get response code for some reason")
}
}
}
downloadPicTask.resume()
}
结果!
我推荐你使用像 AlamofireImage 这样的库,并在 UIImageView 中选择自定义 class。
自定义 Class UIImageView:
import Foundation
import UIKit
import AlamofireImage
class CustomImageView: UIImageView {
func ImageViewLoading(mediaUrl: String) {
guard let url = URL(string: mediaUrl) else { return }
let activityIndicator = self.activityIndicator
DispatchQueue.main.async {
activityIndicator.startAnimating()
}
self.af.setImage(
withURL: url,
placeholderImage: nil,
filter: nil,
completion: { response in
DispatchQueue.main.async {
activityIndicator.stopAnimating()
activityIndicator.removeFromSuperview()
}
}
)
}
private var activityIndicator: UIActivityIndicatorView {
let activityIndicator = UIActivityIndicatorView()
activityIndicator.hidesWhenStopped = true
activityIndicator.color = UIColor.black
self.addSubview(activityIndicator)
activityIndicator.translatesAutoresizingMaskIntoConstraints = false
let centerX = NSLayoutConstraint(item: self,
attribute: .centerX,
relatedBy: .equal,
toItem: activityIndicator,
attribute: .centerX,
multiplier: 1,
constant: 0)
let centerY = NSLayoutConstraint(item: self,
attribute: .centerY,
relatedBy: .equal,
toItem: activityIndicator,
attribute: .centerY,
multiplier: 1,
constant: 0)
self.addConstraints([centerX, centerY])
return activityIndicator
}
}
将此 class 用于您的 UIImageView:
@IBOutlet weak var photoImageViewWithLoading: CustomImageView!
photoImageViewWithLoading.ImageViewLoading(mediaUrl: mediaUrl!)
当您从 url 加载图像时,UIImageView 将显示活动指示器
我这个回答对你有帮助。
注:我用的是Swift5
我写了一个使用 SDWebImage 的扩展。以下是我的代码,并提供了良好的用户体验。
import SDWebImage
extension UIImageView {
func imageURL(_ url: String) {
let activityIndicator = UIActivityIndicatorView(style: .gray)
activityIndicator.frame = CGRect(x: 0, y: 0, width: 64, height: 64)
activityIndicator.hidesWhenStopped = true
activityIndicator.startAnimating()
activityIndicator.translatesAutoresizingMaskIntoConstraints = false
activityIndicator.center = CGPoint(x: self.frame.size.width / 2, y: self.frame.size.height / 2)
self.addSubview(activityIndicator)
//self.sd_setImage(with: URL(string: url), placeholderImage: UIImage(named: "placeholder.png"))
self.sd_setImage(with: URL(string: url)) { (image, error, cacheType, url) in
activityIndicator.stopAnimating()
}
}
}
我想在从网站下载图像时在屏幕上显示一个 activity 指示器 url 然后在 images.image 中显示这是我下面的代码。每次我下载图像时,它都会立即打印状态,并且 activity 指示器永远不会出现。一直在网上搜索,但我还是不明白。请帮忙
let mygroup = DispatchGroup()
var activityIndicator = UIActivityIndicatorView()
func downloadpic(sender:UIButton){
let catPictureURL = URL(string: addr)!
// Creating a session object with the default configuration.
// You can read more about it here https://developer.apple.com/reference/foundation/urlsessionconfiguration
let session = URLSession(configuration: .default)
// Define a download task. The download task will download the contents of the URL as a Data object and then you can do what you wish with that data.
let downloadPicTask = session.dataTask(with: catPictureURL) { (data, response, error) in
// The download has finished.
if let e = error {
print("Error downloading cat picture: \(e)")
} else {
// No errors found.
// It would be weird if we didn't have a response, so check for that too.
if let res = response as? HTTPURLResponse {
// put loading screen here
self.activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: .white)
self.activityIndicator.frame = CGRect(x: 0, y: 0, width: 46, height: 46)
self.activityIndicator.startAnimating()
self.mygroup.enter()
print("downloading image")
print("Downloaded cat picture with response code \(res.statusCode)")
if let imageData = data {
// Finally convert that Data into an image and do what you wish with it.
self.images.image = UIImage(data: imageData)
self.mygroup.leave()
print("image already downloaded")
self.activityIndicator.stopAnimating()
self.activityIndicator.hidesWhenStopped = true
// Do something with your image.
} else {
print("Couldn't get image: Image is nil")
}
} else {
print("Couldn't get response code for some reason")
}
}
}
downloadPicTask.resume()
}
您遇到了这个问题,因为:
- 您没有将
activityIndicator
添加到任何视图 - 您在
completionHandler
块中配置了activityIndicator
让我们在 activityIndicator
中配置 viewDidLoad()
方法:
self.activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: .gray)
self.activityIndicator.frame = CGRect(x: 0, y: 0, width: 46, height: 46)
self.activityIndicator.hidesWhenStopped = true
view.addSubview(self.activityIndicator)
并在恢复 dataTask
self.activityIndicator.startAnimating()
然后,停止在 completionHandler
self.activityIndicator.stopAnimating()
最终代码:
let mygroup = DispatchGroup()
var activityIndicator = UIActivityIndicatorView()
override func viewDidLoad() {
super.viewDidLoad()
self.activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: .gray)
self.activityIndicator.frame = CGRect(x: 0, y: 0, width: 46, height: 46)
self.activityIndicator.hidesWhenStopped = true
view.addSubview(self.activityIndicator)
}
func downloadpic(sender: UIButton) {
let catPictureURL = URL(string: addr)!
// Creating a session object with the default configuration.
// You can read more about it here https://developer.apple.com/reference/foundation/urlsessionconfiguration
let session = URLSession(configuration: .default)
// Define a download task. The download task will download the contents of the URL as a Data object and then you can do what you wish with that data.
self.activityIndicator.startAnimating()
let downloadPicTask = session.dataTask(with: catPictureURL) { (data, response, error) in
// The download has finished.
if let e = error {
print("Error downloading cat picture: \(e)")
} else {
// No errors found.
// It would be weird if we didn't have a response, so check for that too.
if let res = response as? HTTPURLResponse {
// put loading screen here
self.mygroup.enter()
print("downloading image")
print("Downloaded cat picture with response code \(res.statusCode)")
if let imageData = data {
// Finally convert that Data into an image and do what you wish with it.
self.images.image = UIImage(data: imageData)
self.mygroup.leave()
print("image already downloaded")
self.activityIndicator.stopAnimating()
// Do something with your image.
} else {
print("Couldn't get image: Image is nil")
}
} else {
print("Couldn't get response code for some reason")
}
}
}
downloadPicTask.resume()
}
结果!
我推荐你使用像 AlamofireImage 这样的库,并在 UIImageView 中选择自定义 class。
自定义 Class UIImageView:
import Foundation
import UIKit
import AlamofireImage
class CustomImageView: UIImageView {
func ImageViewLoading(mediaUrl: String) {
guard let url = URL(string: mediaUrl) else { return }
let activityIndicator = self.activityIndicator
DispatchQueue.main.async {
activityIndicator.startAnimating()
}
self.af.setImage(
withURL: url,
placeholderImage: nil,
filter: nil,
completion: { response in
DispatchQueue.main.async {
activityIndicator.stopAnimating()
activityIndicator.removeFromSuperview()
}
}
)
}
private var activityIndicator: UIActivityIndicatorView {
let activityIndicator = UIActivityIndicatorView()
activityIndicator.hidesWhenStopped = true
activityIndicator.color = UIColor.black
self.addSubview(activityIndicator)
activityIndicator.translatesAutoresizingMaskIntoConstraints = false
let centerX = NSLayoutConstraint(item: self,
attribute: .centerX,
relatedBy: .equal,
toItem: activityIndicator,
attribute: .centerX,
multiplier: 1,
constant: 0)
let centerY = NSLayoutConstraint(item: self,
attribute: .centerY,
relatedBy: .equal,
toItem: activityIndicator,
attribute: .centerY,
multiplier: 1,
constant: 0)
self.addConstraints([centerX, centerY])
return activityIndicator
}
}
将此 class 用于您的 UIImageView:
@IBOutlet weak var photoImageViewWithLoading: CustomImageView!
photoImageViewWithLoading.ImageViewLoading(mediaUrl: mediaUrl!)
当您从 url 加载图像时,UIImageView 将显示活动指示器
我这个回答对你有帮助。
注:我用的是Swift5
我写了一个使用 SDWebImage 的扩展。以下是我的代码,并提供了良好的用户体验。
import SDWebImage
extension UIImageView {
func imageURL(_ url: String) {
let activityIndicator = UIActivityIndicatorView(style: .gray)
activityIndicator.frame = CGRect(x: 0, y: 0, width: 64, height: 64)
activityIndicator.hidesWhenStopped = true
activityIndicator.startAnimating()
activityIndicator.translatesAutoresizingMaskIntoConstraints = false
activityIndicator.center = CGPoint(x: self.frame.size.width / 2, y: self.frame.size.height / 2)
self.addSubview(activityIndicator)
//self.sd_setImage(with: URL(string: url), placeholderImage: UIImage(named: "placeholder.png"))
self.sd_setImage(with: URL(string: url)) { (image, error, cacheType, url) in
activityIndicator.stopAnimating()
}
}
}