集合视图单元格导航

时间:2018-07-01 01:20:27

标签: ios swift uicollectionview uinavigationcontroller swift4

亲爱的编码员,请帮助我。我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
        }
    }
}

我不会在视图控制器之间传输数据。我计划为单元中的每只动物制作特定的快速文件,然后当您点按它们的图标时,我希望这些快速文件显示出来。当然,我正在使用导航控制器,并在应用程序委托中进行设置。

请帮助我。谢谢大家。

1 个答案:

答案 0 :(得分:0)

通常,我会警告不要将数据和代码紧密耦合,但是您可以通过在数据模型中存储对视图控制器类的引用来完成所需的操作;您在注释的代码中几乎正确无误。您只需在()之后不需要self

如果您不需要可变性,则最好使用结构,因此AnimalAnimalCategory对象可以是结构。您也可以避免所有这些可选选项。

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)
}

在使用可选组件方面,您还可以进行很多清理工作。例如,animalsanimalCategories都可以隐式地包装为可选。

由于无法使用布局进行初始化,因此您将无法拥有AnimalDetailViewController子类UICollectionViewController。您将需要子类UIViewController并将集合视图添加到您的viewDidLoad