Swift TableView ImageView + Label = 致命错误:索引超出范围
Posted
技术标签:
【中文标题】Swift TableView ImageView + Label = 致命错误:索引超出范围【英文标题】:Swift TableView ImageView + Label = Fatal Error: Index out of range 【发布时间】:2020-06-11 10:58:27 【问题描述】:我正在使用 tableview 来显示项目的标题,包括图像。 我正在使用 FirebaseStorage 和 FirebaseDatabase。
问题是,当我只有 一个 保护时,我一点击标题就会收到“致命错误:索引超出范围”。 当我有多个项目时,您可以在视频中看到发生了什么。
也许有人可以帮助我,因为索引处理有问题。 :)
import UIKit
import Kingfisher
import Foundation
import FirebaseStorage
import FirebaseDatabase
class HomeViewController: UIViewController
// MARK: - Properties
@IBOutlet weak var tableView: UITableView!
@IBOutlet weak var addProject: UIButton!
var posts = [Post]()
var textToBeSent: String = ""
override func viewDidLoad()
super.viewDidLoad()
UserService.posts(for: User.current) (posts) in
self.posts = posts
self.tableView.reloadData()
Utilities.addShadowtoButton(addProject)
func configureTableView()
// remove separators for empty cells
tableView.tableFooterView = UIView()
// remove separators from cells
tableView.separatorStyle = .none
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
if segue.identifier == "toDetails"
let destVC = segue.destination as! ShowProjectDetailsViewController
destVC.post = sender as? Post
extension Collection where Indices.Iterator.Element == Index
public subscript(safe index: Index) -> Iterator.Element?
return (startIndex <= index && index < endIndex) ? self[index] : nil
// MARK: - UITableViewDataSource
extension HomeViewController: UITableViewDataSource
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
let post = posts[indexPath.row]
performSegue(withIdentifier: "toDetails", sender: post)
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
return 2
func numberOfSections(in tableView: UITableView) -> Int
return posts.count
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
let post = posts[indexPath.section]
switch indexPath.row
case 0:
let cell = tableView.dequeueReusableCell(withIdentifier: "PostImageCell") as! PostImageCell
let imageURL = URL(string: post.imageURL)
cell.postImageView.kf.setImage(with: imageURL)
return cell
case 1:
let cell = tableView.dequeueReusableCell(withIdentifier: "PostSubCell") as! PostSubCell
cell.projectName.text = post.projectTitle
return cell
default:
fatalError("Error: unexpected indexPath.")
// MARK: - UITableViewDelegate
extension HomeViewController: UITableViewDelegate
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
switch indexPath.row
case 0:
let post = posts[indexPath.section]
return post.imageHeight
case 1:
return PostSubCell.height
default:
fatalError()
import Foundation
import FirebaseAuth.FIRUser
import FirebaseDatabase
import FirebaseUI
import FirebaseAuth
struct UserService
static func posts(for user: User, completion: @escaping ([Post]) -> Void)
let ref = Database.database().reference().child("posts").child(user.uid)
ref.observe(DataEventType.value, with: (snapshot) in
guard let snapshot = snapshot.children.allObjects as? [DataSnapshot] else
return completion([])
let posts = snapshot.reversed().compactMap(Post.init)
completion(posts)
)
import Foundation
import UIKit
import FirebaseDatabase.FIRDataSnapshot
class Post
// Next let's add properties to store all the additional information we need. Add the following to your post class.
var key: String?
let imageURL: String
let imageHeight: CGFloat
let creationDate: Date
let imageName: String
let projectTitle: String
let projectLocation: String
let projectDescription: String
let projectBeginn: String
let projectEnd: String
// You'll get some compiler errors for not having any initializers or default values for certain properties. Let's go ahead and fix that:
init(imageURL: String, imageName: String, imageHeight: CGFloat, projectTitle: String, projectLocation: String, projectDescription: String, projectBeginn: String, projectEnd: String)
self.imageURL = imageURL
self.imageName = imageName
self.imageHeight = imageHeight
self.creationDate = Date()
self.projectTitle = projectTitle
self.projectLocation = projectLocation
self.projectDescription = projectDescription
self.projectBeginn = projectBeginn
self.projectEnd = projectEnd
var dictValue: [String : Any]
let createdAgo = creationDate.timeIntervalSince1970
return ["image_url" : imageURL,
"image_name" : imageName,
"image_height" : imageHeight,
"created_at" : createdAgo,
"projectTitle" : projectTitle,
"projectLocation" : projectLocation,
"projectDescription" : projectDescription,
"projectBeginn" : projectBeginn,
"projectEnd": projectEnd ]
init?(snapshot: DataSnapshot)
guard let dict = snapshot.value as? [String : Any],
let imageURL = dict["image_url"] as? String,
let imageName = dict["image_name"] as? String,
let imageHeight = dict["image_height"] as? CGFloat,
let createdAgo = dict["created_at"] as? TimeInterval,
let projectTitle = dict["projectTitle"] as? String,
let projectLocation = dict["projectLocation"] as? String,
let projectDescription = dict["projectDescription"] as? String,
let projectBeginn = dict["projectBeginn"] as? String,
let projectEnd = dict["projectEnd"] as? String
else return nil
self.key = snapshot.key
self.imageURL = imageURL
self.imageName = imageName
self.imageHeight = imageHeight
self.creationDate = Date(timeIntervalSince1970: createdAgo)
self.projectTitle = projectTitle
self.projectLocation = projectLocation
self.projectDescription = projectDescription
self.projectBeginn = projectBeginn
self.projectEnd = projectEnd
感谢您的帮助!
【问题讨论】:
在您的didSelect
中,您使用的是indexPath.row
,但每个帖子只有一个部分,所以我认为您应该使用indexPath.section
通过使用上面的代码,布局在您的项目中根据您的需要正确显示??
【参考方案1】:
您由[Post]
创建了您的numberOfSection
。您还可以在点击indexPath.row
时分配performSegue
。所以它会抛出一个错误,你必须在didSelectItem()
方法中使用indexPath.section
而不是indexPath.row
例如
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
let post = posts[indexPath.section] // Use here section instead of row
performSegue(withIdentifier: "toDetails", sender: post)
【讨论】:
欢迎快乐 coading :)以上是关于Swift TableView ImageView + Label = 致命错误:索引超出范围的主要内容,如果未能解决你的问题,请参考以下文章