我正在制作一个包含表视图的场景的应用程序。表格视图中的每个单元格都包含一个评分控件(由5星组成)和一个标签。单击一个按钮,我想打印所有标签以及用户在整个表格视图中从评级控件中单击的星星数。到控制台。
我该怎么做?
这是我的tableview(_:cellForRowAt :)方法
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// Configure the cell
// Table view cells are reused and should be dequeued using a cell identifier
let cellId = "cell"
guard let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as? MatchingTableViewCell else {
fatalError("The dequeued cell is not an instacne of MatchingTableViewCell")
}
// Fetches the appropriate match for the data source layout.
let match = matching[indexPath.row]
cell.nameLabel.text = match.name
cell.photoImagView.image = match.photo
cell.ratingControl.rating = match.rating
return cell
}
数据模型对象是Match对象的结构数组:
import Foundation
import UIKit
import os.log
class Match: NSObject, NSCoding {
// MARK: Properties
var name: String
var photo: UIImage?
var rating: Int
// MARK: Archiving Paths
static let DocumentsDirectory = FileManager().urls(for: .documentDirectory, in: .userDomainMask).first
static let ArchiveURL = DocumentsDirectory?.appendingPathComponent("matching")
// MARK: Types
struct PropertyKey {
static let name = "name"
static let photo = "photo"
static let rating = "rating"
}
init?(name: String, photo: UIImage?, rating: Int) {
// The name must not be empty
guard !name.isEmpty else{
return nil
}
// The rating must be between 0 and 5 inclusively
guard (rating >= 0) && (rating <= 5) else {
return nil
}
// Initialize stored properties
self.name = name
self.photo = photo
self.rating = rating
}
override var description : String {
return "rating \(self.rating) \n"
}
// MARK: NSCoding
func encode(with aCoder: NSCoder) {
aCoder.encode(name, forKey: PropertyKey.name)
aCoder.encode(photo, forKey: PropertyKey.photo)
aCoder.encode(rating, forKey: PropertyKey.rating)
}
required convenience init?(coder aDecoder: NSCoder) {
// The name is required if we cannot decode a name string, the init should fail
guard let name = aDecoder.decodeObject(forKey: PropertyKey.name) as? String else{
os_log("Unable to decode the name for a Match object", log: OSLog.default, type: .debug)
return nil
}
// Because the photo is an optional property of Match, just use conditional cast.
let photo = aDecoder.decodeObject(forKey: PropertyKey.photo) as? UIImage
let rating = aDecoder.decodeObject(forKey: PropertyKey.rating)
// Must call designated init
self.init(name: name, photo: photo, rating: rating as! Int)
}
}
RatingControl.swiift:
import UIKit
@IBDesignable class RatingControl: UIStackView {
// MARK: Properties
private var ratingButtons = [UIButton]()
var rating = 0 {
didSet {
updateButtonSelectionStates()
}
}
@IBInspectable var starSize: CGSize = CGSize(width: 44.0, height: 44.0) {// Defines size of buttons/
didSet{
setupButtons()
}
}
@IBInspectable var starCount: Int = 5 {// Defines number of buttons
didSet{
setupButtons()
}
}
// MARK: Initialization
override init(frame: CGRect) {
super.init(frame: frame)
setupButtons()
}
required init(coder: NSCoder) {
super.init(coder: coder)
setupButtons()
}
// MARK: Private Methods
private func setupButtons(){
// Clear any existing buttons
for button in ratingButtons{
removeArrangedSubview(button)
button.removeFromSuperview()
}
ratingButtons.removeAll()
// Load Button Images
let bundle = Bundle(for: type(of: self))
let filledStar = UIImage(named: "filledStar", in: bundle, compatibleWith: self.traitCollection)
let emptyStar = UIImage(named: "emptyStar", in: bundle, compatibleWith: self.traitCollection)
let highligtedStar = UIImage(named: "highlightedStar", in: bundle, compatibleWith: self.traitCollection)
for _ in 0..<starCount {
// Create the button
let button = UIButton()
// Set the button images
button.setImage(emptyStar, for: .normal)
button.setImage(filledStar, for: .selected)
button.setImage(highligtedStar, for: .highlighted)
button.setImage(highligtedStar, for: [.highlighted, .selected])
// Adding constraints
button.translatesAutoresizingMaskIntoConstraints = false // disables buttons automatically generated constraints
button.heightAnchor.constraint(equalToConstant: starSize.height).isActive = true // defines height
button.widthAnchor.constraint(equalToConstant: starSize.width).isActive = true // defines width
//Setup the button action
button.addTarget(self, action: #selector(RatingControl.ratingButtonTapped(button:)), for: .touchUpInside)
// Add button to stack
addArrangedSubview(button)
// Add the new button to the rating button Array
ratingButtons.append(button)
}
updateButtonSelectionStates()
}
// MARK: Button Action
@objc func ratingButtonTapped(button:UIButton){
guard let index = ratingButtons.index(of: button) else {
fatalError("The button, \(button), is not in the ratingButtons array: \(ratingButtons)")
}
// Calculate the rating of the selected button
let selectedRating = index + 1
if selectedRating == rating { // If the selected star represents the current rating, reset the rating to 0
rating = 0
} else{
// Otherwise set the rating to the selected star
rating = selectedRating
}
}
private func updateButtonSelectionStates() { // Update buttons appearance
for (index, button) in ratingButtons.enumerated() {
// If the index of a button is less than the rating, that button should be selected
button.isSelected = index < rating
}
}
}
答案 0 :(得分:0)
您错了。您的表视图不保存数据,而是显示它。您想要一个数据模型来保存从表视图中显示的值。这就是您的tableView dataSource方法的源头。通常它将是一个结构数组。
您要打印表视图数据模型的内容。
现在您已经提供了信息,我们可以为您提供帮助。
为数据模型添加CustomStringConvertible
一致性:
class Match: NSObject, NSCoding, CustomStringConvertible {
CustomStringConvertible
的唯一要求是您提供一个description
的计算属性String
:
var description: String {
return "Match(name:\(name),rating:\(rating))"
}
然后按按钮操作
@IBAction func logInfo(sender: UIButton) {
matching.forEach { print($0) }
}
由于您的Match
类现在符合CustomStringConvertible
,因此您可以直接打印Match
对象。
或者如果您想要索引:
@IBAction func logInfo(sender: UIButton) {
matching.enumerated()forEach { print(String(format:"%02l", $0.0) + ": " + $0.1) }
}