【问题标题】:needing to get count of the array in dictionary for my CollectionView需要为我的 CollectionView 获取字典中数组的计数
【发布时间】:2017-08-08 00:54:29
【问题描述】:

好的,我正在尝试使我的 CollectionView 的每个部分都有一个标题,并且每个部分中有 3 个带有相应标签的图像视图。我有与标签匹配的图像视图,但我无法返回正确的 numberOfItemsInSection。 我已经多次更改我的代码以试图解决这个问题,我什至不确定我的应用程序的其余部分是正确的,但本质上这是重要的部分:

var sectionsArrayDictionary : [String:Array<String>] = ["level 1" : ["item1", "item2", "item3"], "level 2" : ["item4","item5", "item6"], "level 3" : ["item7", "item8", "item9"]]

我想不出一种方法来访问这些值,以便我可以返回一个计数。 (如果有人知道如何修复,作为额外的帮助:我的图片在每个部分中显示相同的 3 张图片,而不是每个部分都显示自己的图片。我希望在上述部分得到修复后这将解决。)

更新: 我的代码一团糟,但既然你想要更多的代码在这里。目前有两个不同的教程组合在一起,所以可能会让您更加困惑。

import UIKit

let reuseIdentifier = "collCell"
let headerViewIdentifier = "headerView"
var sections: [Section] = SectionsData().getSectionsFromData()

class LayoutController: UICollectionViewController, UICollectionViewDelegateFlowLayout {
    let sectionInsets = UIEdgeInsets(top: 5.0, left: 5.0, bottom: 5.0, right: 5.0)
    var animalLabels = ["max", "roxy", "buster", "daisy", "charlie", "maggie", "buddy", "ruby", "lucky", "bella"]
    var animalImages = ["max", "roxy", "buster", "daisy", "charlie", "maggie", "buddy", "ruby", "lucky", "bella"]


    var section1 = ["max", "roxy", "buster"]
    var section2 = ["daisy","charlie", "maggie"]
    var section3 = ["buddy", "ruby", "lucky"]
    let sections: [String] = ["Section 1", "Section 2", "Section 3"]
    let s1Data: [String] = [item1, item2, item3]
    let s2Data: [String] = [item4, item5, item6]
    let s3Data: [String] = [item7, item8, item9]
    var sectionData: [Int: [String]] = [:]




    override func viewDidLoad() {
        super.viewDidLoad()

        sectionData = [0:s1Data, 1:s2Data, 2:s3Data]
    }


    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    // MARK: UICollectionViewDataSource

    override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
        return sections.count
    }

    override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 3
    }

    override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! CollectionViewCell
        let imgName = indexPath.row
        cell.animalImage.image = UIImage(named: self.animalImages[imgName])
        cell.animalLabel.text = self.animalLabels[imgName]
        return cell
    }

    func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets {
            return sectionInsets
    }


    //I don't think this is doing anything...tried to convert it from tableView code
    func collectionView(collectionView: UICollectionView, titleForHeaderInSection section:Int) -> String? {
        return sections[section]
    }

    override func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView {

        let headerView: Header = collectionView.dequeueReusableSupplementaryViewOfKind(kind, withReuseIdentifier: headerViewIdentifier, forIndexPath: indexPath) as! Header

        headerView.headerLabel.text = "Level"

        return headerView

    }

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        print(segue.identifier)
        print(sender)
        if(segue.identifier == "detail"){
            let cell = sender as! CollectionViewCell
            let indexPath = collectionView!.indexPathForCell(cell)
            let vc = segue.destinationViewController as! DetailViewController

            let imgName = animalImages[indexPath!.row]



            print(vc)
            vc.currImage = UIImage(named: imgName)
            vc.textHeading = animalLabels[indexPath!.row]
            //
            //            vc.heading.text = self.titles[0]
            //            vc.imageView.image = UIImage(named: imgName)
        }
    }
}

我正在尝试删除 sectionData(其上方有一段代码,其中包含 let 部分、let s1data 和 var 部分)。这根本没有帮助。 我正在尝试用

替换它
class SectionsData {

func getSectionsFromData() -> [Section] {

    // you could replace the contents of this function with an HTTP GET, a database fetch request,
    // or anything you like, as long as you return an array of Sections this program will
    // function the same way.

    var sectionsArray = [Section]()

    let level1 = Section(title: "Level 1", objects: ["max", "roxy", "buster"])
    let level2 = Section(title: "Level 2", objects: ["daisy","charlie", "maggie"])
    let level3 = Section(title: "Level 3", objects: ["buddy", "ruby", "lucky"])


    sectionsArray.append(level1)
    sectionsArray.append(level2)
    sectionsArray.append(level3)

    return sectionsArray
}

}

和 结构部分 {

    var heading : String
    var items : [String]

    init(title: String, objects : [String]) {

        heading = title
        items = objects

    }
}

不幸的是,我不能在主视图页面上将标题、项目、标题或对象称为成员......所以我现在卡住了

【问题讨论】:

  • 请出示您的代码。我们无法在没有看到它的情况下修复任何代码。
  • 您使用的是 Xcode 7/Swift 2 吗?
  • xcode7 是的,老实说我不知道​​什么版本的 swift
  • Xcode 7 附带 Swift 2.x,Swift 从 2 到 3 发生了许多变化。我建议您将 Xcode 更新到最新并找到适合更新后的 Xcode 的教程或示例代码.您可能需要升级 macOS,但您可以免费获得 Xcode 和 macOS 升级。 (你只需要足够的磁盘空间来升级。)虽然可能需要一些时间,所以我会尝试在 Swift 2 中写一个答案。

标签: arrays swift dictionary count uicollectionview


【解决方案1】:

首先,如何从字典中获取计数:

var sectionsArrayDictionary : [String:Array<String>] = ["level 1" : ["item1", "item2", "item3"], "level 2" : ["item4","item5", "item6"], "level 3" : ["item7", "item8", "item9"]]

let sectionIndex = 0
let sectionName = "level \(sectionIndex+1)" //->level 1
if let sectionItems = sectionsArrayDictionary[sectionName] {
    let count = sectionItems.count
    print(count)
} else {
    print("No entry for '\(sectionName)'")
}

几点:

  • 在实际代码中,键将作为从 0 开始的整数索引给出,上面的代码包括将整数转换为字典的字符串键
  • 在 Swift 中,下标 ([]) 到 Dictionary 的返回类型是 Optional,上面的代码使用 Optional Binding 来处理它
  • 在上面的true 代码块中,sectionItems 只是一个Array&lt;String&gt;,因此您只需使用count 属性来获取计数

但当您采用新的SectionsData 时,可能不需要以上所有内容。


在使您的代码适应这个新的SectionsData 之前,请稍作修改:

struct Item {
    var imageName: String
    var labelText: String
}

struct Section {

    var heading : String
    var items : [Item]

    init(title: String, objects : [String]) {

        heading = title
        items = objects.map {Item(imageName: $0, labelText: $0)}

    }
}

在您的代码中,您将每个项目的标签文本和图像名称分开处理,因此引入Item类型来分别保存它们。


Data在应用程序中使用的太频繁了,所以我把它改名为SectionsManager。也不建议在每次使用时创建一个实例,单例模式是当今的首选方式。

class SectionsManager {

    //### Singleton
    static let shared = SectionsManager()
    private init() {}

    func getSectionsFromData() -> [Section] {

        // you could replace the contents of this function with an HTTP GET, a database fetch request,
        // or anything you like, as long as you return an array of Sections this program will
        // function the same way.

        var sectionsArray = [Section]()

        let level1 = Section(title: "Level 1", objects: ["max", "roxy", "buster"])
        let level2 = Section(title: "Level 2", objects: ["daisy","charlie", "maggie"])
        let level3 = Section(title: "Level 3", objects: ["buddy", "ruby", "lucky"])


        sectionsArray.append(level1)
        sectionsArray.append(level2)
        sectionsArray.append(level3)

        return sectionsArray
    }

    func getSectionsFromDictionary(dictionary: [String: [String]]) -> [Section] {
        var sectionsArray = [Section]()

        //###  `.sort({$0.0 < $1.0})` sorts the dictionary by its key.
        for (title, objects) in dictionary.sort({$0.0 < $1.0}) {
            //print(title, objects) //See what is happening while debugging.
            let level = Section(title: title, objects: objects)

            sectionsArray.append(level)
        }

        return sectionsArray
    }
}

我还添加了一个方法来从您的sectionsArrayDictionary 创建一个Array&lt;Section&gt;


通过以上所有准备,你的LayoutController会变成这样:

class LayoutController: UICollectionViewController, UICollectionViewDelegateFlowLayout {
    var sectionsArrayDictionary : [String: [String]] = ["level 1" : ["item1", "item2", "item3"], "level 2" : ["item4","item5", "item6"], "level 3" : ["item7", "item8", "item9"]]

    let sectionInsets = UIEdgeInsets(top: 5.0, left: 5.0, bottom: 5.0, right: 5.0)

    //### With using an Array of Section, your code gets simplified.
    var sections: [Section] = []

    override func viewDidLoad() {
        super.viewDidLoad()

        //### Choose any one you prefer.
        //sections = SectionsManager.shared.getSectionsFromData()
        sections = SectionsManager.shared.getSectionsFromDictionary(sectionsArrayDictionary)
    }

    // MARK: UICollectionViewDataSource

    override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
        return sections.count
    }

    override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        //### Return the number of items in the specified section.
        return sections[section].items.count
    }

    override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! CollectionViewCell
        //### Your old code does not use `indexPath.section`, so all sections show the same contents.
        let sectionIndex = indexPath.section
        let itemIndex = indexPath.row
        let item = sections[sectionIndex].items[itemIndex]
        cell.animalImage.image = UIImage(named: item.imageName)
        cell.animalLabel.text = item.labelText
        return cell
    }

    func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets {
        return sectionInsets
    }

    func collectionView(collectionView: UICollectionView, titleForHeaderInSection section:Int) -> String? {
        //### Try this.
        return sections[section].heading
    }

    override func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView {
        //### Not sure what you really want to do here, so keeping it as is.

        let headerView: Header = collectionView.dequeueReusableSupplementaryViewOfKind(kind, withReuseIdentifier: headerViewIdentifier, forIndexPath: indexPath) as! Header

        headerView.headerLabel.text = "Level"

        return headerView

    }

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        print(segue.identifier)
        print(sender)
        if(segue.identifier == "detail"){
            let cell = sender as! CollectionViewCell
            //### Do nothing when `indexPath` cannot be gotten.
            guard let indexPath = collectionView!.indexPathForCell(cell) else {return}
            let vc = segue.destinationViewController as! DetailViewController

            //### You can retrieve the item in the same way as `collectionView(_:cellForItemAtIndexPath:)`.
            let sectionIndex = indexPath.section
            let itemIndex = indexPath.row
            let item = sections[sectionIndex].items[itemIndex]
            let imgName = item.imageName

            print(vc)
            vc.currImage = UIImage(named: imgName)
            vc.textHeading = item.labelText
            //...
        }
    }
}

您可能需要一些修复才能使此代码在您的项目中运行,但我希望它不会太多,您可以自己完成。

【讨论】:

  • 非常感谢,我的代码不再显示错误,我的 collectionView 现在在第一页上显示正确的图片 :)
  • 很高兴听到这个消息。希望您的进一步发展不会有任何问题。但是,如果您发现有困难,我很乐意提供帮助。祝你好运。
【解决方案2】:

给定一个部分字符串。

let count = sectionsArrayDictionary["level 1"].count

我知道肯定有更多内容,因此您需要发布更多代码以便我们更好地理解问题。

更新: 所以我们仍然缺少Section 的键声明,但假设您可以直接访问它的objects 属性;这就是你需要的。

let count = sections[1].objects.count

对于二级对象 daisy、charlie 和 maggie,count 变量现在应该为 3。展望未来,您应该只为 Swift 3 和很快 4 开发。不要在这个项目中切换,但 没有人 正在使用 Swift 2 开发。任何在线 Swift 2 教程都已过时。祝你好运。

【讨论】:

  • “使用未解析的标识符”如果我这样做的话。不过谢谢你。我发布了更多代码来提供帮助
【解决方案3】:

在这里使用这个获取你 sectionArrayDictionary 中的数组总数

var sectionsArrayDictionary : [String:Array<String>] = ["level 1" : ["item1", "item2", "item3"], "level 2" : ["item4","item5", "item6"], "level 3" : ["item7", "item8", "item9"]]

var keys = Array(sectionsArrayDictionary.keys)
print(keys)

print(keys.count) //Output - 3

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-09
    相关资源
    最近更新 更多