![](/img/trans.png)
[英]How to make UICollectionView class programmatically in iOS Swift 3 without using storyboard?
[英]How to optimise data inputs for my UIPicker and UICollectionView programmatically Swift iOS
我是个菜鸟,以编程方式学习 iOS 开发,而不是使用故事板。
我创建了两个测试控制器
我可能会在用户注册时使用 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"
}
}
}
我目前有以下屏幕,目前在调试窗口中它会打印出每个屏幕上选择的任何内容
关于故事板与代码,我通常发现使用代码更简洁、更快捷。 特别是当没有复杂的设计可以通过代码来解决时。 即使我想以图形方式设置我的整个应用程序,我通常使用附加到他们自己的 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
类型的名为jobRole
的JobRole
。 每当设置此属性时,标签和图像视图应自动更新。
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.