如何使用Swift在UITableView中将ActivityIndicator放入UIImageView中?(How to put ActivityIndicator inside UIImage inside UITableView using Swift?)

我有UITableView,其中每个单元格都有一个UIImage,并且使用JSON从API下载图像。

我通过Background Threading处理了初始图像和数据。 但是,当用户在表格视图中向下滚动时,其他单元格的图像开始下载,因此这些单元格需要一些刷新。

我想在UIImageView中添加一个ActivityIndi​​cator,因此用户会注意到正在下载图像。

其他信息,UIImageView是在一个UIStackView。 我想过是isHidden方法,无法实现。

感谢您的时间。

I have UITableView where each cell has one UIImage and the image is being downloaded from an API using JSON.

I handled the initial images and data via Background Threading. However, as user scrolls down inside table view, images to other cells begins to download, so those cells requires some refreshing.

I thought about adding an ActivityIndicator inside UIImageView, so user will notice image is being downloaded.

Additional info, UIImageView is inside an UIStackView. I thought about isHidden method, could not implemented.

Thank you for your time.

最满意答案

通常我会推荐使用像Kingfisher这样的库来为你管理(我相信你可以在加载时设置一个占位符视图来显示),但是如果你想手动执行此操作,你可能会有类似的东西

enum LoadingState { case notLoading case loading case loaded(UIImage) } class MyTableViewCell: UITableViewCell { let activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.gray) let imageStackView = UIStackView() let myImageView = UIImageView() // can't be named imageView because UITableViewCell already has one with that name var loadingState: LoadingState = .notLoading { // many ways you could do this, you just need one or more "update" mechanisms to start/stop the spinner and set your image didSet { switch loadingState { case .notLoading: myImageView.image = nil activityIndicator.stopAnimating() case .loading: myImageView.image = nil activityIndicator.startAnimating() case let .loaded(img): myImageView.image = img activityIndicator.stopAnimating() } } } override init(style: UITableViewCellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) configure() } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) configure() } private func configure() { contentView.addSubview(activityIndicator) contentView.addSubview(imageStackView) imageStackView.addArrangedSubview(myImageView) // constrain activity indicator and stack view } override func prepareForReuse() { super.prepareForReuse() loadingState = .notLoading } }

Ordinarily I'd recommend using a library like Kingfisher to manage this for you (I believe you can set a placeholder view to display while you're loading) but if you want to do this manually you could have something like

enum LoadingState { case notLoading case loading case loaded(UIImage) } class MyTableViewCell: UITableViewCell { let activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.gray) let imageStackView = UIStackView() let myImageView = UIImageView() // can't be named imageView because UITableViewCell already has one with that name var loadingState: LoadingState = .notLoading { // many ways you could do this, you just need one or more "update" mechanisms to start/stop the spinner and set your image didSet { switch loadingState { case .notLoading: myImageView.image = nil activityIndicator.stopAnimating() case .loading: myImageView.image = nil activityIndicator.startAnimating() case let .loaded(img): myImageView.image = img activityIndicator.stopAnimating() } } } override init(style: UITableViewCellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) configure() } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) configure() } private func configure() { contentView.addSubview(activityIndicator) contentView.addSubview(imageStackView) imageStackView.addArrangedSubview(myImageView) // constrain activity indicator and stack view } override func prepareForReuse() { super.prepareForReuse() loadingState = .notLoading } }

更多推荐