Ios 集合视图单元格导航

Ios 集合视图单元格导航,ios,swift,uicollectionview,uinavigationcontroller,swift4,Ios,Swift,Uicollectionview,Uinavigationcontroller,Swift4,亲爱的同事们,请帮助我。我两个月前开始学习Swift,如果我能够完成,这将是我的第一个应用程序。。。 首先,我不使用故事板。在我的应用程序中,主窗口中有收藏视图。当您点击单元格中的图像(例如cat单元格中的cat图像)时,应打开cat.swift文件。但我还不能实现它。同样,如果您点击狗图像,应该会查看dog.swift文件。这是代码 这是打开应用程序时的主屏幕: import UIKit class FeaturedAnimalsController: UICollectionViewCon

亲爱的同事们,请帮助我。我两个月前开始学习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.
    } 
}
这是分类单元:

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

}
这是动物模型:

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)
    }
以下是动物和动物类别模型:

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]
    }
}
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文件显示出来。当然,我正在使用导航控制器,并在app delegate中进行设置


请帮帮我。谢谢大家。

一般来说,我会提醒大家不要将数据和代码紧密耦合,但您可以通过在数据模型中存储对view controller类的引用来实现自己的目的;在你的注释代码中,它几乎是正确的;您不需要在
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
都可以隐式展开选项

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

}

您将无法使用
AnimalDetailViewController
子类
UICollectionViewController
,因为您无法使用布局进行初始化。您需要将
UIViewController
子类化,并将集合视图添加到
viewdiload

为什么要为每种动物创建特定的类?一般来说,您会尽可能多地从数据中提取代码。。。例如,当我点击cat图像时,我希望看到一个包含5个单元格的集合视图;但若我点击狗的图像,我想看到3个单元格。在这些细胞中,数据将是不相关的。所以我想我不能从一个数据库中导航。这就是为什么ı选择为每种动物制作不同的swift文件。分类单元格是主页中不同的集合视图。长话短说,我要求代码算法在点击名为“Cat”的图像后查看Cat.swift(这是一个单独的集合视图),或者点击CATV的单元格,您可以在数据模型中存储对
Cat.self
Dog.self
的引用,然后在该属性上调用
init()
,以获取视图控制器的实例,例如
让catVC=Cat.self
然后
让catVCInstance=catVC.init()
,但是,正如我所说,数据和代码之间的这种紧密耦合是很糟糕的,谢谢你,但是在完成了所有编写的工作之后,我也遇到了同样的问题。问题是,当我点击cat图像时,会显示AnimalDetailController,而不是CatDetailViewController(特定于cat的swift文件)。我在给AnimalDetailController键入背景色后意识到了这一点。在我的项目中,CatDVC和DogDVC是CollectionViewController,它们是AnimalDetailController的子类。但我还不能超越动物细节控制器。。。谢谢你的回答。如果有人想键入他们自己的解决方案,我还有以前的***版本作为备份编辑你的问题以显示你的
showAnimalDetailFor
代码或任何你用来实例化和展示细节视图控制器的函数。你的
showAnimalDetailFor
正在实例化
AnimalDetailController
-我的代码不是这样做的。使用我的
showAnimalDetailFor
我尝试了:func showAnimalDetailFor(animal:animal){let dvc=animal.dvc self.show(dvc,sender:self)}这是因为一开始我甚至无法启动它,但当我使用此代码启动时,它在点击一个图像后崩溃,因为我试图实例化一个集合视图,而我没有它的任何布局。这就是为什么我试图在ShowAnimalDetail中为函数设置布局