亲爱的编码员,请帮助我。我2个月前开始学习Swift,如果我能够完成,这将是我的第一个应用程序。 首先,我不使用情节提要。在我的应用程序中,主窗口中有集合视图。当您点击单元格中的图像(例如,cat单元格中的cat图像)时,应打开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
}
}
}
我不会在视图控制器之间传输数据。我计划为单元中的每只动物制作特定的快速文件,然后当您点按它们的图标时,我希望这些快速文件显示出来。当然,我正在使用导航控制器,并在应用程序委托中进行设置。
请帮助我。谢谢大家。
答案 0 :(得分:0)
通常,我会警告不要将数据和代码紧密耦合,但是您可以通过在数据模型中存储对视图控制器类的引用来完成所需的操作;您在注释的代码中几乎正确无误。您只需在()
之后不需要self
。
如果您不需要可变性,则最好使用结构,因此Animal
和AnimalCategory
对象可以是结构。您也可以避免所有这些可选选项。
struct Animal {
let name: String
let category: String
let imageName: String
let dvc: AnimalDetailController.Type
}
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 dogs = AnimalCategory(name: "Dog Family")
dogs.addAnimal(Animal(name: "Dog", category: "Friendly", imageName: "dog", dvc: DogDetailViewController.self))
var cats = AnimalCategory(name: "Cat Family")
cats.addAnimal(Animal(name: "Cat", category: "Lovely", imageName: "cat", dvc: CatDetailViewController.self))
let categories = [dogs,cats]
return categories
}()
mutating func addAnimal(_ animal: Animal) {
self._animals.append(animal)
}
}
然后您的showAnimalDetailForAnimal
类似于:
func showAnimalDetailFor(_ animal: Animal) {
let dvc = animal.dvc.init()
self.show(dvc, sender: self)
}
在使用可选组件方面,您还可以进行很多清理工作。例如,animals
和animalCategories
都可以隐式地包装为可选。
由于无法使用布局进行初始化,因此您将无法拥有AnimalDetailViewController
子类UICollectionViewController
。您将需要子类UIViewController
并将集合视图添加到您的viewDidLoad