gpt4 book ai didi

swift - 关闭 UIViewController 后 UI 卡住 5 秒

转载 作者:行者123 更新时间:2023-11-30 10:04:32 25 4
gpt4 key购买 nike

我有一个图像的 UICollectionView 和一个在选择任何图像时打开的完整 ImageView 。打开完整图像效果很好,但一旦我关闭它,整个应用程序就会卡住超过 5 秒。我读到主线程可能过载,这可以解释延迟,但我不确定要移动到哪些线程以及移动到哪里,如果这是问题的话。

import UIKit

class FullImageViewController: UIViewController , UIScrollViewDelegate {

var scroller: UIScrollView!
var width = CGFloat()
var images = [Image]()
var imageArray = [UIImage]()
var imgs: [UIImage] = [UIImage(named: "pug7")!, UIImage(named: "pug6")!, UIImage(named: "pug7")!, UIImage(named: "pug6")!]
var index = Int()
var fullImagesAdded = Bool()

init(width: CGFloat, images: [Image], index: Int, imageArray: [UIImage]) {

super.init(nibName: nil, bundle: nil)
self.width = width
self.images = images
self.index = index
self.imageArray = imageArray
}

required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

override func viewDidLoad() {
super.viewDidLoad()

let downSwipe = UISwipeGestureRecognizer(target: self, action: #selector(FullImageViewController.swipeDown))
downSwipe.direction = .Down
view.addGestureRecognizer(downSwipe)

self.scroller = UIScrollView()
self.scroller.delegate = self
var i = 0
for img in images {
let aimageDetailViewController = ImageDetailViewController(index: self.index, image: img)
self.scroller.addSubview(aimageDetailViewController.view)
var aimageDetailViewFrame: CGRect = aimageDetailViewController.view.frame
aimageDetailViewFrame.origin.x = (super.view.frame.width) * CGFloat(i)
aimageDetailViewController.view.frame = aimageDetailViewFrame

i += 1
}

self.scroller.backgroundColor = UIColor.blackColor()
self.scroller.contentSize = CGSizeMake(self.view.frame.width * CGFloat(images.count), self.view.frame.height)
self.scroller.bounces = false
self.scroller.showsHorizontalScrollIndicator = false
self.scroller.setContentOffset(CGPoint(x: self.view.frame.width * CGFloat(index), y: 0), animated: false)
self.scroller.pagingEnabled = true

self.view.addSubview(scroller)
}

func swipeDown(){
dispatch_async(dispatch_get_main_queue()) {
self.dismissViewControllerAnimated(true, completion: nil)
}
}

override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
scroller.frame = view.bounds
}
}

这是我在 UICollectionView 中调用完整 ImageView 的地方:

func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
let fullImage = FullImageViewController(width: CGFloat(imageURLSCache.count), images: imageURLSCache, index: Int(indexPath.row), imageArray: images)
self.presentViewController(fullImage, animated: true, completion: nil)
}

谢谢!

这是我用来下载完整 ImageView 和 Collection View 的图像的扩展

extension UIImageView {

func downloadFrom(link link:String?, cache: NSCache ) {
image = UIImage(named: "logo")
self.alpha = 0.3
let data: NSData? = cache.objectForKey(link!) as? NSData


if let cachedData = data {
let image = UIImage(data: cachedData)
dispatch_async(dispatch_get_main_queue(), {() in
self.image = image
self.alpha = 1
images.append(self.image!)
})
return
}


if link != nil, let url = NSURL(string: link!) {
NSURLSession.sharedSession().dataTaskWithURL(url) { data, response, error in
guard let data = data where error == nil else {
print("\nerror on download \(error)")
return
}
if let httpResponse = response as? NSHTTPURLResponse where httpResponse.statusCode != 200 {
print("statusCode != 200; \(httpResponse.statusCode)")
return
}
dispatch_async(dispatch_get_main_queue()) {
print("\ndownload completed \(url.lastPathComponent!)")
self.image = UIImage(data: data)
self.alpha = 1
cache.setObject(data, forKey: link!)
}
}.resume()
} else {
dispatch_async(dispatch_get_main_queue(), {
self.image = UIImage(named: "logo")
})

}
}

}

最佳答案

func swipeDown(){
dispatch_async(dispatch_get_main_queue()) {
self.dismissViewControllerAnimated(true, completion: nil)
}
}

此方法已设置为 UISwipeGestureRecognizer 的操作。它将由手势识别器在主线程上调用,因此您不需要将其分派(dispatch)到主队列。这会增加延迟,具体取决于队列的繁忙程度。

将其更改为:

func swipeDown() {
self.dismissViewControllerAnimated(true, completion: nil)
}

有关您添加的附加信息的更新:

UIImageView 上的扩展不是很好(即,当使用它作为缓存的键时,它假设 link 不是 nil ,但稍后检查它是否为 nil,但不可能是这样,否则你已经崩溃了)。但它至少使用 dataTaskWithURL 方法在后台进行下载。

我会尝试在调度到后台调用中调用它,如下所示,以确保您不会因缓存检查等而使主线程重载。我假设您正在安全地为此扩展创建缓存,并且当然会重用所有调用的缓存,而不是为每个调用创建一个新的缓存(我已经看到这样做了)。

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)) {
imageView.downloadFrom(....)
}

这是一个可供使用的替代扩展。这是我经常使用的一个。它会为您创建缓存,因此您不必担心在扩展之外执行此操作。它还具有确认自图像开始下载以来尚未在图像上设置另一个 URL 的好处。例如,当 ImageView 位于可重复使用的单元上时,这一点很重要。创建单元格,将图像 url 设置为 x,当它仍在下载时,单元格滚动到屏幕外并重新使用,图像 url 设置为 y,然后 x 下载完成并显示适用于旧单元格的图像。

代码如下:

//  UIImageView+XCGAdditions.swift
// Cerebral Gardens
//
// Created by Dave Wood
// Copyright © Cerebral Gardens. All rights reserved.

import UIKit

extension UIImageView {

func setImageWithLink(link: String) {
guard let url = NSURL(string: link) else { return }
setImageWithURL(url: url)
}

func setImageWithURL(url url: NSURL) {
let checkInt = Int(arc4random_uniform(100000))
tag = checkInt

struct Statics {
static var onceToken: dispatch_once_t = 0
static var imageCache: NSCache!
}
dispatch_once(&Statics.onceToken) { () -> Void in
Statics.imageCache = NSCache()
}

if let cachedImage = Statics.imageCache.objectForKey(url) as? UIImage {
self.image = cachedImage
return
}

NSURLSession.sharedSession().dataTaskWithURL(url, completionHandler: { (data: NSData?, response: NSURLResponse?, error: NSError?) -> () in
guard let data = data where error == nil,
let image = UIImage(data: data) where self.tag == checkInt else { return }

dispatch_async(dispatch_get_main_queue()) { () -> () in
Statics.imageCache.setObject(image, forKey: url)
self.image = image
}
}).resume()
}
}

关于swift - 关闭 UIViewController 后 UI 卡住 5 秒,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36815317/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com