尝试填充NSManagedObjects数组的数组

时间:2019-01-12 16:36:10

标签: swift xcode core-data

我正在从CoreData模型中获取数据,并且效果很好。我得到了一个N​​SManagedObjects(NSMO)数组,每个都是具有其他属性的文档。

NSMO的属性之一是日期,为了填充TableView,我将日期中的“年”用作TableView中的部分。

要获得每年(部分)的NSMO,我必须过滤阵列。但是,如果我在“ cellForRowAtIndexPath”中进行过滤,则该应用程序效率将非常低下。所以我虽然有一个解决方案:

在将所有文档提取到一个数组中之后,我可以每年对数组进行过滤并填充一个NSMO数组。

var documentArray = [Document]()  // To fetch all the documents.
var documentArrayPerSection = [[Document]]()  // To filter per section.

“文档”是NSMO。

例如,对于第一部分,我们具有数组:

documentArrayPerSection[0]

以此类推。

var documentArray = [Document]()
var documentArrayPerSection = [[Document]]()
let yearSections = ["2005","2006","2007","2008","2009","2010","2011","2012","2013"]

func fetchDocuments() {

    // We make the request to the context to get the documents we want.

    do {

        documentArray = try context.fetchMOs(requestedEntity!, sortBy: requestedSortBy, predicate: requestedPredicate)

        // Arrange the documentArray per year using the variable documentArrayPerSection.
        for index in 0...yearSections.count - 1 {

            documentArrayPerSection[index] = documentArray.filter({ (document) -> Bool in
                let formatter = DateFormatter()
                formatter.dateFormat = "yyyy"
                let yearSection = formatter.string(from: document.date!)
                return yearSection == self.yearSections[index]
            })

        }

    } catch {

        print("Error fetching data from context \(error)")

    }

}

应用程序崩溃时总是说“索引超出范围”。而且我不知道该如何解决,因为该变量必须是全局变量,才能从“ cellForRowAtIndexPath”进行访问,并且必须初始化为空白。

2 个答案:

答案 0 :(得分:1)

我认为您可以采用其他方式来创建您的版块。这是一个简单的例子。在这种情况下,我将创建一个测试文档结构,一个Section结构和一个SectionManager,可以帮助您返回该部分以填充tableView。

文档结构,这几乎就是您已经拥有的Document对象。

=

然后,您可以创建一个部分结构

struct Document {
    let date : String
    let foo : String
    init(date: String!, foo: String!) {
        self.date = date
        self.foo = foo
    }
}

然后您的 sectionManager

struct Section {

    var title: String
    var items : [Document]

    init(title: String, documents : [Document]) {
        self.title = title
        items = documents
    }
}

请注意,我在那儿使用单例。

最后,您可以只使用该代码在viewController中创建您的部分。在这里,我使用collectionView是因为我更喜欢它们,但是您可以改用tableView。

class SectionsManager {
    // Singleton
    static let shared = SectionsManager()
    private init() {}
    func getSectionsFromDictionary(dictionary: [String: [Document]]) -> [Section] {
        var sectionsArray = [Section]()
        for (title, objects) in dictionary.sorted(by: {$0.0 > $1.0}) {
            let section = Section(title: title, documents: objects)
            sectionsArray.append(section)
        }
        return sectionsArray
    }
}

然后,您可以在应用程序中重复使用管理器以填充任何其他集合。如果复制粘贴所有代码,则可以检查其工作方式。

答案 1 :(得分:1)

Swift 4+提供了一种非常简单方便的方法来对数组进行分组:Dictionary(grouping:by:)

let calendar = Calendar.current
let groupedDictionary = Dictionary(grouping: documentArray, by: {calendar.component(.year, from: $0.date)})

分别返回以年份为键的字典(如Int和以值Document组成的数组。

如果您希望使用String键将闭包更改为

{ String(calendar.component(.year, from: $0.date)) }

然后您可以使用

来获取您的section数组
let yearSections = groupedDictionary.keys.sorted()

并使用

获得相应的数组
let yearArrays = yearSections.map{ groupedDictionary[$0]! }

不需要Dateformatter