繁体   English   中英

如何以编程方式为我的 UIPicker 和 UICollectionView 优化数据输入 Swift iOS

[英]How to optimise data inputs for my UIPicker and UICollectionView programmatically Swift iOS

我是个菜鸟,以编程方式学习 iOS 开发,而不是使用故事板。

我创建了两个测试控制器

  1. 使用 UIPicker 允许使用滚轮选择工作角色
  2. 通过点击图标,使用 UICollectionView 选择所有工作角色

我可能会在用户注册时使用 UIPicker 和 UICollectionView 来选择一个角色以将其详细信息作为菜单查看

我在每个控制器中创建了数组来为每个控制器提供所需的数据

我想要做的是能够使用数据模型来保存保存两者使用的公共数据的 eNum。

我不确定如何为我的选择器和集合视图创建数组

我想在稍后用户进行选择时使用枚举,并将输出传递给我的下一个控制器以执行操作,我觉得在所选项目上进行切换会很好。

感谢任何指导,如果我完全生气并且一切都错了。

干杯

JobRoleMenuViewController.swift

   import UIKit

private let reuseIdentifier = "Cell"

class JobRoleMenuViewController: UICollectionViewController {
    
    // MARK: - Properties
    
    var jobRoleLabel: [String] = [
        "Doctor",
        "Teacher",
        "Student",
        "Shop Keeper",
        "Fire Fighter",
        "I'm So Lucky!"
    ]
    
    var jobRoleImage: [UIImage] = [
        UIImage(named: "doctor")!,
        UIImage(named: "teacher")!,
        UIImage(named: "student")!,
        UIImage(named: "retailer")!,
        UIImage(named: "firefighter")!,
        UIImage(named: "astronaut")!
    ]
    
    // MARK: - Lifecycle
    
    override func viewDidLoad() {
        super.viewDidLoad()
        collectionView.backgroundColor = .white
        self.collectionView.register(JobRoleCell.self, forCellWithReuseIdentifier: reuseIdentifier)
    }
    
    // MARK: -
    
    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return jobRoleImage.count
    }
    
    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! JobRoleCell
        cell.categoryLabel.text = jobRoleLabel[indexPath.item]
        cell.categoryImage = jobRoleImage[indexPath.row]
        return cell
    }
    
    override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        print("DEBUG: Tapped cell at: \(indexPath.row)")
    }
}

// MARK: -

extension JobRoleMenuViewController: UICollectionViewDelegateFlowLayout {
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
        return 1
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
        return 1
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let width = (view.frame.width - 2) / 3
        return CGSize(width: width, height: width)
    }
}

}

JobRoleCell.swift

请注意:在下面的代码中,centerX 和锚点是我在 Extensions.swfit 中创建的扩展,因此我可以在所有代码中重用

import UIKit

class JobRoleCell: UICollectionViewCell {
    
    // MARK: - Properties
    
    var categoryImage: UIImage? {
        didSet {
            guard let categoryImage = categoryImage else { return }
            imageView.image = categoryImage
        }
    }
    
    let categoryLabel: UILabel = {
        let label = UILabel()
        label.font = UIFont.boldSystemFont(ofSize: 16)
        label.tintColor = .black
        return label
    }()
    
    let imageView: UIImageView = {
        let iv = UIImageView()
        return iv
    }()
    
    // MARK: - Lifcycle
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        addSubview(imageView)
        imageView.anchor(top: topAnchor, left: leftAnchor, bottom: bottomAnchor, right: rightAnchor, paddingTop: 40, paddingLeft: 40, paddingBottom: 40, paddingRight: 40)
        
        addSubview(categoryLabel)
        categoryLabel.centerX(inView: self)
        categoryLabel.anchor(bottom: bottomAnchor)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }    
}

JobRolePicker.swift

import UIKit

class JobRolePickerController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
    
    // MARK: - Properties
    
    let jobRolePickerData: [String] = [
        "Doctor",
        "Teacher",
        "Student",
        "Shop Keeper",
        "Fire Fighter",
        "Astronaut"
    ]
    
    // MARK: - Lifecycle
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.backgroundColor = .white
        let picker: UIPickerView = UIPickerView()
        picker.delegate = self as UIPickerViewDelegate
        picker.dataSource = self as UIPickerViewDataSource
        self.view.addSubview(picker)
        picker.center = self.view.center
    }
    
    // MARK: - PickerController
    
    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 1
    }
    
    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        return jobRolePickerData.count
    }
    
    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        let row = jobRolePickerData[row]
        return row
    }
    
    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        
        //        let jobRoleSelected = jobRolePickerData[pickerView.selectedRow(inComponent: 0)]
        print("DEBUG: Tapped cell at: \(jobRolePickerData[row])")
    }
}

我想尝试使用它来保存数据并在所有需要它的人之间共享,并使用它来切换 JobRoleMenuView 和 JobRolePickerView 的输出

工作.swift

import Foundation

enum JobRole: Int {
    //enum TradeType: CaseIterable {
    case doctor
    case teacher
    case student
    case retailer
    case fireFighter
    case astronaut
    
    var JobTitle: String {
        switch self {
        
        case .doctor:
            return "Doctor"
        case .teacher:
            return "Teacher"
        case .student:
            return "Student"
        case .retailer:
            return "Shop Keeper"
        case .fireFighter:
            return "Fire Fighter"
        case .astronaut:
            return "Fly me to the Moon"
        }
    }
    
    var JobImage: String? {
        switch self {
        
        case .doctor:
            return "doctor"
        case .teacher:
            return "teacher"
        case .student:
            return "student"
        case .retailer:
            return "retailer"
        case .fireFighter:
            return "firefighter"
        case .astronaut:
            return "astronaut"
        }
    }
}

我目前有以下屏幕,目前在调试窗口中它会打印出每个屏幕上选择的任何内容

JobRoleMenuScreenShot

JobRolePickerScreenShot

关于故事板与代码,我通常发现使用代码更简洁、更快捷。 特别是当没有复杂的设计可以通过代码来解决时。 即使我想以图形方式设置我的整个应用程序,我通常使用附加到他们自己的 Xib 文件的视图控制器,以避免拥有一个超大的故事板,因为它变得太大而变得烦人。

关于您的问题,如果我理解正确,您只想使用枚举来获取选择器和集合视图的来源,而不必每次都手动设置信息。 您非常接近(您注释掉了对CaseIterable协议的一致性)。

我对您的代码进行了一些调整:对于枚举,我符合CaseIterable ,它允许您访问枚举上名为allCases的属性。 这只是返回数组中的所有案例。 我还在枚举中添加了一个变量,直接为您提供保存的图像。 我强制打开它(!),因为图像应该 100% 的时间都在那里。 所以我不担心它永远为零。 我还添加了一个numberOfItems变量,但这可以很容易地替换为allCases.count 无论如何,其中任何一个都将允许您的numberOfItemsInSection自动反映您拥有的 JobRoles 数量。

enum JobRole: Int, CaseIterable {

    case doctor
    case teacher
    case student
    case retailer
    case fireFighter
    case astronaut

    static var numberOfItems: Int {
        return allCases.count
    }

    var image: UIImage {
        return UIImage(named: imageString)!
    }

    var jobTitle: String {
        switch self {
        case .doctor:
            return "Doctor"
        case .teacher:
            return "Teacher"
        case .student:
            return "Student"
        case .retailer:
            return "Shop Keeper"
        case .fireFighter:
            return "Fire Fighter"
        case .astronaut:
            return "Fly me to the Moon"
        }
    }

    var imageString: String {
        switch self {
        case .doctor:
            return "doctor"
        case .teacher:
            return "teacher"
        case .student:
            return "student"
        case .retailer:
            return "retailer"
        case .fireFighter:
            return "firefighter"
        case .astronaut:
            return "astronaut"
        }
    }
}

对于单元格,我只是更改了图像视图的名称并添加了一个jobRole类型的名为jobRoleJobRole 每当设置此属性时,标签和图像视图应自动更新。

class JobRoleCell: UICollectionViewCell {

    // MARK: - Properties
    var jobRole: JobRole! {
        didSet {
            categoryLabel.text = jobRole.jobTitle
            categoryImageView.image = jobRole.image
        }
    }

    private let categoryLabel: UILabel = {
        let label = UILabel()
        label.font = UIFont.boldSystemFont(ofSize: 16)
        label.tintColor = .black
        return label
    }()

    private let categoryImageView: UIImageView = {
        let iv = UIImageView()
        return iv
    }()

    // MARK: - Lifcycle
    override init(frame: CGRect) {
        super.init(frame: frame)

        addSubview(categoryImageView)
        categoryImageView.anchor(top: topAnchor, left: leftAnchor, bottom: bottomAnchor, right: rightAnchor, paddingTop: 40, paddingLeft: 40, paddingBottom: 40, paddingRight: 40)

        addSubview(categoryLabel)
        categoryLabel.centerX(inView: self)
        categoryLabel.anchor(bottom: bottomAnchor)
    }

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

然后对于您的数据源提供程序(我只做了集合视图,但对于选择器视图应该很容易理解):

func numberOfSections(in collectionView: UICollectionView) -> Int {
    return 1
}

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return JobRole.numberOfItems
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! JobRoleCell
    cell.jobRole = JobRole.allCases[indexPath.row]
    return cell
}

因此,每当您为选择器出列单元格或行时,您只需使用 indexPath 即可检索要分配给该单元格的工作角色。 然后您可以删除您所做的手动声明,并让枚举为您提供单元格的所有必要信息(即标题和必要的图像)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM