在加载 viewcontroller 之后加载 collectionview 的图像视图
loading imageviews of collectionview after the viewcontroller is loaded
所以我正在 swift 构建一个应用程序,用户可以在其中上传带有图片的产品。上传工作完美,但我遇到的问题是图片的下载。用户获得所有产品的概览并单击它们,然后将他发送到该产品的详细概览。在该概览中,有一个包含所有图像的 collection 视图(这是目标)。我的问题是图片对于 collection 视图来说加载速度太慢并且没有出现在屏幕上。我想知道是否有一个选项可以在函数中提供图像视图并将图像分配给它们,并且图片会在屏幕加载后一张一张地加载?
这是我现在加载图像的功能:
func getPictures(imageStrings: [String], imageViews: [UIImageView]){
let storage = Storage.storage();
for index in 0...imageStrings.count - 1 {
let gsReference = storage.reference(forURL: imageStrings[index])
gsReference.getData(maxSize: 15 * 1024 * 1024) { data, error in
if let error = error {
// Uh-oh, an error occurred!
print(error)
return
} else {
DispatchQueue.main.async {
imageViews[index].image = UIImage(data: data!)
}
print(UIImage(data: data!) as Any)
}
}
}
}
这是我的 collection 视图处于活动状态的 viewcontroller
import MessageUI
import FirebaseStorage
class ProductDetailViewController: UIViewController, MFMailComposeViewControllerDelegate, UINavigationControllerDelegate, UICollectionViewDelegate, UICollectionViewDataSource {
@IBOutlet var TitleLable: UILabel!
@IBOutlet var PriceLable: UILabel!
@IBOutlet var ProductDate: UILabel!
@IBOutlet var UsernameLable: UILabel!
@IBOutlet var LocationLable: UILabel!
@IBOutlet var Userdate: UILabel!
@IBOutlet var ReserveerButton: UIButton!
@IBOutlet var DescriptionTextView: UITextView!
@IBOutlet var collectionView: UICollectionView!
var titleLable = String()
var priceLable = String()
var productDate = String()
var descriptionLable = String()
var userId = String()
var usernameLable = String()
var locationLable = String()
var userdate = String()
var email = String()
var imageStrings = [String]()
var images = [UIImage]()
var dbhelper = DBHelper()
override func viewDidLoad() {
super.viewDidLoad()
ReserveerButton.layer.cornerRadius = 20
loadUser(id: userId)
TitleLable.text = titleLable
PriceLable.text = priceLable
ProductDate.text = productDate
DescriptionTextView.text = descriptionLable
UsernameLable.text = usernameLable
loadImages()
// Do any additional setup after loading the view.
}
private func loadUser(id: String){
let dbhelper = DBHelper()
dbhelper.getUserbyUserID(id: id){ success in
if(dbhelper.users[0].Bedrijf != "NULL"){
self.UsernameLable.text = dbhelper.users[0].Bedrijf
} else {
self.UsernameLable.text = dbhelper.users[0].Voornaam + " " + dbhelper.users[0].Familienaam
}
self.Userdate.text = dbhelper.users[0].Added_on
self.LocationLable.text = dbhelper.users[0].Stad
self.email = dbhelper.users[0].Email
}
}
@IBAction func ReserveerProduct(_ sender: Any) {
if !MFMailComposeViewController.canSendMail() {
print("Mail services are not available")
return
}
let composeVC = MFMailComposeViewController()
composeVC.mailComposeDelegate = self
// Configure the fields of the interface.
composeVC.setToRecipients([self.email])
composeVC.setSubject(self.titleLable)
composeVC.setMessageBody("Beste " + self.usernameLable + ", \n\nIk zou graag het zoekertje " + self.titleLable + " reserveren. Is dit nog steeds mogelijk? \n\nMet vriendelijke groet" , isHTML: false)
// Present the view controller modally.
self.present(composeVC, animated: true, completion: nil)
}
func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
switch result.rawValue {
case MFMailComposeResult.cancelled.rawValue :
print("Cancelled")
case MFMailComposeResult.failed.rawValue :
print("Failed")
case MFMailComposeResult.saved.rawValue :
print("Saved")
case MFMailComposeResult.sent.rawValue :
print("Sent")
default: break
}
self.dismiss(animated: true, completion: nil)
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return imageStrings.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ImageCollectionViewCell", for: indexPath) as! ImageCollectionViewCell
cell.contentMode = .scaleAspectFill
return cell
}
func loadImages(){
let dbhelper = DBHelper()
//dbhelper.getPictures2(imageStrings: self.imageStrings, imageViews: self.images)
}
}
希望我能最终解决这个问题!
亲切的问候
B.
我想您面临的问题是加载图像后没有更新集合视图。
首先,您的 getPictures(...)
方法需要一组 UIImageView。但事实上,您不能将它们传递给方法,因为它们是在您的 collectionView 中动态创建的。相反,你应该 return 图像,一旦它们被加载。问题是图像是异步加载的。这意味着您需要使用完成处理程序。
func getPictures(imageStrings: [String], completionHandler: @escaping (UIImage) -> ()) {
let storage = Storage.storage();
for index in 0...imageStrings.count - 1 {
let gsReference = storage.reference(forURL: imageStrings[index])
gsReference.getData(maxSize: 15 * 1024 * 1024) { data, error in
if let error = error {
// Uh-oh, an error occurred!
print(error)
return
} else {
completionHandler(UIImage(data: data!))
print(UIImage(data: data!) as Any)
}
}
}
}
然后你需要修改你的loadImages()
方法:
func loadImages() {
let dbhelper = DBHelper()
dbhelpergetPictures(imageStrings: [""]) { (loadedImage) in
DispatchQueue.main.async {
self.images.append(loadedImage)
self.collectionView.reloadData()
}
}
}
之后,您需要修改 collectionView(numberOfItemsInSection) 方法,以使显示的单元格数等于加载的图像数:
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return images.count
}
最后,您需要在集合视图中实际显示 UIImageViews 中的图像:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ImageCollectionViewCell", for: indexPath) as! ImageCollectionViewCell
cell.contentMode = .scaleAspectFill
cell.imageView.image = images[indexPath.row]
return cell
}
如果您对此有任何疑问,请在评论中提问。
(PS:一个善意的建议:看看 swift 命名约定 (here is a good style guide)。除了 类 之外的所有名称都应该始终以小写字母开头,并应描述其用途。
例子:
var TitleLable: UILabel!
-> var titleLable: UILabel!
和:var titleLable = String()
-> var title = String()
这将使您的代码更易于理解!)
所以我正在 swift 构建一个应用程序,用户可以在其中上传带有图片的产品。上传工作完美,但我遇到的问题是图片的下载。用户获得所有产品的概览并单击它们,然后将他发送到该产品的详细概览。在该概览中,有一个包含所有图像的 collection 视图(这是目标)。我的问题是图片对于 collection 视图来说加载速度太慢并且没有出现在屏幕上。我想知道是否有一个选项可以在函数中提供图像视图并将图像分配给它们,并且图片会在屏幕加载后一张一张地加载?
这是我现在加载图像的功能:
func getPictures(imageStrings: [String], imageViews: [UIImageView]){
let storage = Storage.storage();
for index in 0...imageStrings.count - 1 {
let gsReference = storage.reference(forURL: imageStrings[index])
gsReference.getData(maxSize: 15 * 1024 * 1024) { data, error in
if let error = error {
// Uh-oh, an error occurred!
print(error)
return
} else {
DispatchQueue.main.async {
imageViews[index].image = UIImage(data: data!)
}
print(UIImage(data: data!) as Any)
}
}
}
}
这是我的 collection 视图处于活动状态的 viewcontroller
import MessageUI
import FirebaseStorage
class ProductDetailViewController: UIViewController, MFMailComposeViewControllerDelegate, UINavigationControllerDelegate, UICollectionViewDelegate, UICollectionViewDataSource {
@IBOutlet var TitleLable: UILabel!
@IBOutlet var PriceLable: UILabel!
@IBOutlet var ProductDate: UILabel!
@IBOutlet var UsernameLable: UILabel!
@IBOutlet var LocationLable: UILabel!
@IBOutlet var Userdate: UILabel!
@IBOutlet var ReserveerButton: UIButton!
@IBOutlet var DescriptionTextView: UITextView!
@IBOutlet var collectionView: UICollectionView!
var titleLable = String()
var priceLable = String()
var productDate = String()
var descriptionLable = String()
var userId = String()
var usernameLable = String()
var locationLable = String()
var userdate = String()
var email = String()
var imageStrings = [String]()
var images = [UIImage]()
var dbhelper = DBHelper()
override func viewDidLoad() {
super.viewDidLoad()
ReserveerButton.layer.cornerRadius = 20
loadUser(id: userId)
TitleLable.text = titleLable
PriceLable.text = priceLable
ProductDate.text = productDate
DescriptionTextView.text = descriptionLable
UsernameLable.text = usernameLable
loadImages()
// Do any additional setup after loading the view.
}
private func loadUser(id: String){
let dbhelper = DBHelper()
dbhelper.getUserbyUserID(id: id){ success in
if(dbhelper.users[0].Bedrijf != "NULL"){
self.UsernameLable.text = dbhelper.users[0].Bedrijf
} else {
self.UsernameLable.text = dbhelper.users[0].Voornaam + " " + dbhelper.users[0].Familienaam
}
self.Userdate.text = dbhelper.users[0].Added_on
self.LocationLable.text = dbhelper.users[0].Stad
self.email = dbhelper.users[0].Email
}
}
@IBAction func ReserveerProduct(_ sender: Any) {
if !MFMailComposeViewController.canSendMail() {
print("Mail services are not available")
return
}
let composeVC = MFMailComposeViewController()
composeVC.mailComposeDelegate = self
// Configure the fields of the interface.
composeVC.setToRecipients([self.email])
composeVC.setSubject(self.titleLable)
composeVC.setMessageBody("Beste " + self.usernameLable + ", \n\nIk zou graag het zoekertje " + self.titleLable + " reserveren. Is dit nog steeds mogelijk? \n\nMet vriendelijke groet" , isHTML: false)
// Present the view controller modally.
self.present(composeVC, animated: true, completion: nil)
}
func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
switch result.rawValue {
case MFMailComposeResult.cancelled.rawValue :
print("Cancelled")
case MFMailComposeResult.failed.rawValue :
print("Failed")
case MFMailComposeResult.saved.rawValue :
print("Saved")
case MFMailComposeResult.sent.rawValue :
print("Sent")
default: break
}
self.dismiss(animated: true, completion: nil)
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return imageStrings.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ImageCollectionViewCell", for: indexPath) as! ImageCollectionViewCell
cell.contentMode = .scaleAspectFill
return cell
}
func loadImages(){
let dbhelper = DBHelper()
//dbhelper.getPictures2(imageStrings: self.imageStrings, imageViews: self.images)
}
}
希望我能最终解决这个问题! 亲切的问候 B.
我想您面临的问题是加载图像后没有更新集合视图。
首先,您的 getPictures(...)
方法需要一组 UIImageView。但事实上,您不能将它们传递给方法,因为它们是在您的 collectionView 中动态创建的。相反,你应该 return 图像,一旦它们被加载。问题是图像是异步加载的。这意味着您需要使用完成处理程序。
func getPictures(imageStrings: [String], completionHandler: @escaping (UIImage) -> ()) {
let storage = Storage.storage();
for index in 0...imageStrings.count - 1 {
let gsReference = storage.reference(forURL: imageStrings[index])
gsReference.getData(maxSize: 15 * 1024 * 1024) { data, error in
if let error = error {
// Uh-oh, an error occurred!
print(error)
return
} else {
completionHandler(UIImage(data: data!))
print(UIImage(data: data!) as Any)
}
}
}
}
然后你需要修改你的loadImages()
方法:
func loadImages() {
let dbhelper = DBHelper()
dbhelpergetPictures(imageStrings: [""]) { (loadedImage) in
DispatchQueue.main.async {
self.images.append(loadedImage)
self.collectionView.reloadData()
}
}
}
之后,您需要修改 collectionView(numberOfItemsInSection) 方法,以使显示的单元格数等于加载的图像数:
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return images.count
}
最后,您需要在集合视图中实际显示 UIImageViews 中的图像:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ImageCollectionViewCell", for: indexPath) as! ImageCollectionViewCell
cell.contentMode = .scaleAspectFill
cell.imageView.image = images[indexPath.row]
return cell
}
如果您对此有任何疑问,请在评论中提问。
(PS:一个善意的建议:看看 swift 命名约定 (here is a good style guide)。除了 类 之外的所有名称都应该始终以小写字母开头,并应描述其用途。
例子:
var TitleLable: UILabel!
-> var titleLable: UILabel!
和:var titleLable = String()
-> var title = String()
这将使您的代码更易于理解!)