我有一个在UIImageView
上打印图片网址的扩展程序。但我认为问题是我的tableView
因为这个扩展而变得如此缓慢。我想我需要为它打开线程。如何在此扩展中创建一个线程,或者您是否知道另一个解决此问题的解决方案?
我的代码:
extension UIImageView{
func setImageFromURl(stringImageUrl url: String){
if let url = NSURL(string: url) {
if let data = NSData(contentsOf: url as URL) {
self.image = UIImage(data: data as Data)
}
}
}
}
答案 0 :(得分:2)
我认为,这里的问题是,您需要在table view
中缓存图片以实现平滑滚动。每次程序调用{{1}}时,它都会再次下载图像。这需要时间。
对于缓存图片,您可以使用cellForRowAt indexPath
,Kingfisher等库。
Kingfisher用法示例:
SDWebImage
希望有所帮助
答案 1 :(得分:2)
你可以使用这里建议的框架,但你也可以考虑"滚动你自己的" this article
中描述的扩展程序"所有"你需要做的是:
public static HashMap<String, String> getContactsForGroup(String groupID, Activity activity){
Cursor dataCursor = activity.getContentResolver().query(
ContactsContract.Data.CONTENT_URI,
new String[]{ // PROJECTION
ContactsContract.Data.CONTACT_ID,
ContactsContract.Data.DISPLAY_NAME, // contact name
ContactsContract.Data.DATA1 // group
},
ContactsContract.Data.MIMETYPE + " = ? " + "AND " + // SELECTION
ContactsContract.Data.DATA1 + " = ? ", // set groupID
new String[]{ // SELECTION_ARGS
ContactsContract.CommonDataKinds.GroupMembership.CONTENT_ITEM_TYPE,
groupID
},
null
);
dataCursor.moveToFirst();
HashMap<String, String> map = new HashMap<>();
while (dataCursor.moveToNext()) //
{
String s0 = dataCursor.getString(0); //contact_id
String s1 = dataCursor.getString(1); //contact_name
String s2 = dataCursor.getString(2); //group_id
Log.d("tag", "contact_id: " + s0 + " contact: " + s1 + " groupID: "+ s2);
map.put(s0, s1);
}
return map;
}
下载您的图片,这是在后台线程上完成的,因此不会出现卡顿和慢速滚动。第一次尝试可能看起来像这样:
URLSession
你可以这样称呼方法:
func loadImage(fromURL urlString: String, toImageView imageView: UIImageView) {
guard let url = URL(string: urlString) else {
return
}
//Fetch image
URLSession.shared.dataTask(with: url) { (data, response, error) in
//Did we get some data back?
if let data = data {
//Yes we did, update the imageview then
let image = UIImage(data: data)
DispatchQueue.main.async {
imageView.image = image
}
}
}.resume() //remember this one or nothing will happen :)
}
如果你想要它,你可以添加一个loadImage(fromURL: "yourUrlToAnImageHere", toImageView: yourImageView)
来向用户显示&#34;正在加载某些内容&#34;,如下所示:
UIActivityIndicatorView
文章中提到的另一项改进可能是将其移至func loadImage(fromURL urlString: String, toImageView imageView: UIImageView) {
guard let url = URL(string: urlString) else {
return
}
//Add activity view
let activityView = UIActivityIndicatorView(activityIndicatorStyle: .gray)
imageView.addSubview(activityView)
activityView.frame = imageView.bounds
activityView.translatesAutoresizingMaskIntoConstraints = false
activityView.centerXAnchor.constraint(equalTo: imageView.centerXAnchor).isActive = true
activityView.centerYAnchor.constraint(equalTo: imageView.centerYAnchor).isActive = true
activityView.startAnimating()
//Fetch image
URLSession.shared.dataTask(with: url) { (data, response, error) in
//Done, remove the activityView no matter what
DispatchQueue.main.async {
activityView.stopAnimating()
activityView.removeFromSuperview()
}
//Did we get some data back?
if let data = data {
//Yes we did, update the imageview then
let image = UIImage(data: data)
DispatchQueue.main.async {
imageView.image = image
}
}
}.resume() //remember this one or nothing will happen :)
}
extension
,如下所示:
UIImageView
基本上它与以前的代码相同,但对extension UIImageView {
func loadImage(fromURL urlString: String) {
guard let url = URL(string: urlString) else {
return
}
let activityView = UIActivityIndicatorView(activityIndicatorStyle: .gray)
self.addSubview(activityView)
activityView.frame = self.bounds
activityView.translatesAutoresizingMaskIntoConstraints = false
activityView.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
activityView.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true
activityView.startAnimating()
URLSession.shared.dataTask(with: url) { (data, response, error) in
DispatchQueue.main.async {
activityView.stopAnimating()
activityView.removeFromSuperview()
}
if let data = data {
let image = UIImage(data: data)
DispatchQueue.main.async {
self.image = image
}
}
}.resume()
}
}
的引用已更改为imageView
。
你可以像这样使用它:
self
当然......包括SDWebImage或Kingfisher作为依赖关系更快,并且&#34;只是工作&#34;大多数情况下,它还为您提供其他好处,如缓存图像等。但我希望这个例子表明,为图像编写自己的扩展并不是那么糟糕......再加上你知道在不工作时应该责怪谁;)
希望能帮到你。
答案 2 :(得分:1)
用于在后台缓存图像&amp;滚动更快使用SDWebImage
库
imageView.sd_setImage(with: URL(string: "http://image.jpg"), placeholderImage: UIImage(named: "placeholder.png"))
答案 3 :(得分:1)
你的tableview因为你在主线程的当前线程中加载数据而变慢。您应该加载其他线程的数据,然后在主线程中设置图像(因为所有UI作业必须在主线程中完成)。您不需要使用第三方库,只需更改您的扩展程序:
extension UIImageView{
func setImageFromURl(stringImageUrl url: String){
if let url = NSURL(string: url) {
DispatchQueue.global(qos: .default).async{
if let data = NSData(contentsOf: url as URL) {
DispatchQueue.main.async {
self.image = UIImage(data: data as Data)
}
}
}
}
}
}