【发布时间】:2018-12-09 17:03:10
【问题描述】:
亲爱的程序员,请帮助我。我 2 个月前开始学习 Swift,如果我能完成的话,这将是我的第一个应用程序...... 首先,我不使用情节提要。在我的应用程序中,主窗口中有集合视图。当您点击单元格中的图像时,例如猫单元格中的猫图像,Cat.swift 文件应该打开。但我还不能实现它。同样,如果您点击狗图像,应该会查看 Dog.swift 文件。这是代码。
这是您打开应用程序时的主屏幕:
import UIKit
class FeaturedAnimalsController: UICollectionViewController, UICollectionViewDelegateFlowLayout {
var animalCategories: [AnimalCategory]?
private let cellId = "cellId"
override func viewDidLoad() {
super.viewDidLoad()
animalCategories = AnimalCategory.sampleAnimalCategories()
collectionView?.backgroundColor = .white
collectionView?.register(CategoryCell.self, forCellWithReuseIdentifier: cellId)
}
func showAnimalDetailForAnimal(animal: Animal) {
let layout = UICollectionViewFlowLayout()
let animalDetailController = AnimalDetailController(collectionViewLayout: layout)
animalDetailController.animal = animal
navigationController?.pushViewController(animalDetailController, animated: true)
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if let count = animalCategories?.count {
return count
}
return 0
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! CategoryCell
cell.featuredAnimalsController = self
cell.animalCategory = animalCategories?[indexPath.item]
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: view.frame.width, height: 230)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
这是 CategoryCell:
import UIKit
class CategoryCell: UICollectionViewCell, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
var featuredAnimalsController: FeaturedAnimalsController?
var animalCategory: AnimalCategory? {
didSet {
if let name = animalCategory?.name {
nameLabel.text = name
}
}
}
private let cellId = "animalCellId"
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if let count = animalCategory?.animals?.count {
return count
}
return 0
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! AnimalCell
cell.animal = animalCategory?.animals?[indexPath.item]
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 100, height: frame.height - 32)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: 0, left: 14, bottom: 0, right: 14)
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if let animal = animalCategory?.animals![indexPath.item] {
featuredAnimalsController?.showAnimalDetailForAnimal(animal: animal)
}
}
override init(frame: CGRect) {
super.init(frame: frame)
setupViews()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
let nameLabel: UILabel = {
let label = UILabel()
label.text = "Cardiology"
label.font = UIFont.systemFont(ofSize: 16)
//label.numberOfLines = 1 --> DEFAULT
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
let animalsCollectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
collectionView.backgroundColor = .clear
collectionView.translatesAutoresizingMaskIntoConstraints = false
return collectionView
}()
func setupViews() {
backgroundColor = .clear
animalsCollectionView.dataSource = self
animalsCollectionView.delegate = self
animalsCollectionView.register(AnimalCell.self, forCellWithReuseIdentifier: cellId)
addSubview(nameLabel)
addSubview(animalsCollectionView)
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-14-[v0]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0": nameLabel]))
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[v0]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0": animalsCollectionView]))
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[nameLabel(30)][v0]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0": animalsCollectionView, "nameLabel": nameLabel]))
}
}
class AnimalCell: UICollectionViewCell {
var animal: Animal? {
didSet {
if let name = animal?.name {
nameLabel.text = name
}
categoryLabel.text = animal?.category
if let imageName = animal?.imageName {
imageView.image = UIImage(named: imageName)
}
}
}
override init(frame: CGRect) {
super.init(frame: frame)
setupViews()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setupViews() {
backgroundColor = .clear
addSubview(categoryLabel)
addSubview(imageView)
addSubview(nameLabel)
categoryLabel.frame = CGRect(x: 0, y: frame.width + 38, width: frame.width, height: 20)
imageView.frame = CGRect(x: 0, y: 0, width: frame.width, height: frame.width)
nameLabel.frame = CGRect(x: 0, y: frame.width + 2, width: frame.width, height: 40)
}
let imageView: UIImageView = {
let iv = UIImageView()
//iv.image = UIImage(named: "cat")
iv.contentMode = .scaleAspectFill
iv.translatesAutoresizingMaskIntoConstraints = false
iv.layer.cornerRadius = 16
iv.layer.masksToBounds = true
return iv
}()
let nameLabel: UILabel = {
let label = UILabel()
label.text = ""
label.font = UIFont.systemFont(ofSize: 14)
label.numberOfLines = 2
return label
}()
let categoryLabel: UILabel = {
let label = UILabel()
label.text = ""
label.font = UIFont.systemFont(ofSize: 13)
label.numberOfLines = 2
return label
}()
}
这是动物类别模型:
import UIKit
class AnimalCategory: NSObject {
var name: String?
var animals: [Animal]?
static func sampleAnimalCategories() -> [AnimalCategory] {
let catFamilyCategory = AnimalCategory()
catFamilyCategory.name = "Cat Family"
var catFamilyAnimals = [Animal]()
let catAnimal = Animal()
catAnimal.name = "Cat"
catAnimal.imageName = "cat"
catAnimal.category = "Lovely"
//catAnimal.dvcName = Cat.self()
catFamilyAnimals.append(catAnimal)
catFamilyCategory.animals = catFamilyAnimals
let dogFamilyCategory = AnimalCategory()
dogFamilyCategory.name = "Dog Family"
var dogFamilyAnimals = [Animal]()
let dogAnimal = Animal()
dogAnimal.name = "Dog"
dogAnimal.imageName = "dog"
dogAnimal.category = "Friendly"
//dogAnimal.dvcName = Dog.self
dogFamilyAnimals.append(dogAnimal)
dogFamilyCategory.animals = dogFamilyAnimals
return [catFamilyCategory, dogFamilyCategory]
}
}
这是动物模型:
import UIKit
class Animal: NSObject {
//var id: NSNumber?
var name: String?
var category: String?
var imageName: String?
//var dvc: AnimalDetailController?
}
这是动物细节控制器和示例 cat.swift:
import UIKit
class AnimalDetailController: UICollectionViewController, UICollectionViewDelegateFlowLayout {
var animal: Animal? {
didSet {
navigationItem.title = animal?.name
}
}
}
class Cat: AnimalDetailController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .brown
}
}
感谢@Paulw11,在进行了一些更改后,这里是为每个动物呈现特定细节视图控制器的代码:
func showAnimalDetailFor(_ animal: Animal) {
let layout = UICollectionViewFlowLayout()
var dvc = animal.dvc
dvc = AnimalDetailController(collectionViewLayout: layout)
self.show(dvc, sender: self)
}
这里是动物和动物类别模型:
struct Animal {
let name: String
let category: String
let imageName: String
let dvc: AnimalDetailController
}
struct AnimalCategory {
var name: String
private var _animals = [Animal]()
var animals: [Animal] {
get {
return self._animals
}
}
init(name: String) {
self.name = name
}
static var sampleAnimalCategories: [AnimalCategory] = {
var dogFamily = AnimalCategory(name: "Dog Family")
dogFamily.addAnimal(Animal(name: "Dog", category: "Friendly", imageName: "dog", dvc: DogDetailViewController()))
var catFamily = AnimalCategory(name: "Cat Family")
catFamily.addAnimal(Animal(name: "Cat", category: "Lovely", imageName: "cat", dvc: CatDetailViewController()))
let categories = [dogFamily,catFamily]
return categories
}()
mutating func addAnimal(_ animal: Animal) {
self._animals.append(animal)
}
}
和动物细节控制器类:
class AnimalDetailController: UICollectionViewController, UICollectionViewDelegateFlowLayout {
var animal: Animal? {
didSet {
navigationItem.title = animal?.name
}
}
}
我不会在视图控制器之间传输数据。我计划为牢房中的每只动物制作特定的 swift 文件,然后当你点击它们的图标时,我希望这些 swift 文件显示出来。当然,我正在使用导航控制器并将其设置在应用程序委托中。
请帮助我。谢谢大家。
【问题讨论】:
-
你为什么要为每一种动物制作特定的课程?一般来说,您会尝试尽可能多地从数据中抽象代码。
-
这段代码可以正常工作...例如,当我点击 cat 图像时,我想看到一个包含 5 个单元格的集合视图;但如果我点击狗图像,我想看到 3 个单元格。在这些单元格中,数据将是无关紧要的。所以我认为我无法从单个数据库中导航。这就是为什么我选择为每只动物制作不同的 swift 文件。顺便说一下,类别单元格是主页中不同的集合视图。
-
长话短说,我要求代码算法在点击名为“cat”的图像或点击单元格后查看 Cat.swift(这是一个单独的集合视图)猫
-
您可以在数据模型中存储对
Cat.self和Dog.self的引用,然后在该属性上调用init()以获取视图控制器的实例,例如let catVC = Cat.self然后let catVCInstance = catVC.init()但是,正如我所说,这种数据和代码之间的紧密耦合是糟糕的设计
标签: ios swift uicollectionview uinavigationcontroller swift4