我正在从CoreData模型中获取数据,并且效果很好。我得到了一个NSManagedObjects(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”进行访问,并且必须初始化为空白。
答案 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