- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我有一个简单的 CloudKit 记录,它有两个字段,Name 和 Grade。我希望能够对 CloudKit 进行查询,返回所有记录,但按等级分组。我知道我可以用 NSFetchResultsController 做到这一点,但似乎找不到用 CKQuery 做到这一点的简单方法。
当前获取代码:
func fetchTeachers(_ completion: @escaping (_ teachers: [CKRecord]?, _ error: NSError?) -> () ) {
let query = CKQuery(recordType: TeacherType, predicate: NSPredicate(value: true))
query.sortDescriptors = [NSSortDescriptor(key:"Grade",ascending:true)]
publicDB.perform(query, inZoneWith: nil) { results, error in
completion(results, error as NSError?)
}
}
最佳答案
要将检索到的 CKRecords 数组拆分为多个部分以便在 UITableView 中显示,您可以使用下面的帮助程序类。
(CKQuery 本身不提供进行这种分段的能力——它只是使您能够检索记录数组,可以选择排序。)
SectionedCKRecords
类:首先,使用 CKQuery 从 CloudKit 获取所需的记录。 (您的示例代码已经这样做了。)这将为您提供一组 CKRecords。
让我们假设这些记录(根据您的示例代码)包含存储字符串值的“Grade”键,并且您希望根据“”将记录拆分为多个部分成绩”。
简单地:
1.) 使用 CKRecords 数组和所需的 sectionNameKey 初始化一个 SectionedCKRecords:
let sectionedRecords = SectionedCKRecords(records: records, sectionNameKey: "Grade")
2.) 实现您的 UITableViewDataSource 以在 sectionedRecords 上调用适当的方法:
SectionedCKRecords exposes methods similar to those of NSFetchedResultsController.
class YourDataSource: UITableViewDataSource {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let record = sectionedRecords.record(at: indexPath)
// TODO: construct a UITableViewCell based on the record
// ...
}
func numberOfSections(in tableView: UITableView) -> Int {
return sectionedRecords.sections.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return sectionedRecords.sections[section].numberOfRecords
}
func sectionIndexTitles(for tableView: UITableView) -> [String]? {
return sectionedRecords.sectionIndexTitles
}
// etc...
}
sectionIndexTitle
行为:如果您想自定义 sectionIndexTitles 的生成方式,您可以将 sectionIndexTitleForSectionName
闭包传递给 SectionedCKRecords 初始化程序。
By default, SectionedCKRecords matches the behavior of NSFetchedResultsController for generating
sectionIndexTitles
, using the capitalized first letter of the section name.
闭包将字符串(sectionName)作为输入,并返回 sectionIndexTitle。
SectionIndexTitleForSectionName 结构中提供了一些示例闭包。
例子:
let sectionedRecords = SectionedCKRecords(records: records, sectionNameKey: "Grade", sectionIndexTitleForSectionName: SectionIndexTitleForSectionName.firstLetterOfString)
// SectionedCKRecords.swift (Swift 3)
// © 2016 @breakingobstacles (http://stackoverflow.com/users/57856/breakingobstacles)
// Source: http://stackoverflow.com/a/39737583/57856
//
// License: The MIT License (https://opensource.org/licenses/MIT)
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
import UIKit
import CloudKit
// MARK: - SectionedCKRecords
class SectionedCKRecords {
private let sectionNameToSection: [String: Int]
private let sectionIndex: [String]
private let sectionIndexTitleToFirstSection: [String: Int]
init(records: [CKRecord], sectionNameKey: String, sectionIndexTitleForSectionName: (String) -> String? = SectionIndexTitleForSectionName.firstLetterOfString) {
self.records = records
self.sectionNameKey = sectionNameKey
// split records into sections
let splitResults = split(records: records, bySectionNameKey: sectionNameKey)
self.sections = splitResults.sections
self.sectionNameToSection = splitResults.sectionNameToSection
// build section index
var sectionIndex: [String] = []
var sectionIndexTitleToFirstSection: [String: Int] = [:]
for (index, section) in splitResults.sections.enumerated() {
guard let sectionIndexTitle = sectionIndexTitleForSectionName(section.name) else {
continue
}
section.indexTitle = sectionIndexTitle
if sectionIndexTitleToFirstSection.index(forKey: sectionIndexTitle) == nil {
sectionIndex.append(sectionIndexTitle)
sectionIndexTitleToFirstSection[sectionIndexTitle] = index
}
}
self.sectionIndex = sectionIndex
self.sectionIndexTitleToFirstSection = sectionIndexTitleToFirstSection
}
/// MARK: - Configuring Information
// The input array of records.
let records: [CKRecord]
// The key on the CKRecords used to determine the section they belong to. Assumes that record[sectionNameKey] returns a String value.
let sectionNameKey: String
/// MARK: - Accessing Results
// Returns the record at the given index path in the sectioned records.
func record(at indexPath: IndexPath) -> CKRecord {
return sections[indexPath.section].records[indexPath.row]
}
/// MARK: - Querying Section Information
// The sections for the fetch results.
private(set) var sections: [SectionInfo]
// Returns the section number for a given section title and index in the section index.
func section(forSectionIndexTitle sectionIndexTitle: String, at: Int) -> Int {
return sectionIndexTitleToFirstSection[sectionIndexTitle] ?? -1
}
// The array of section index titles.
var sectionIndexTitles: [String] {
get {
return sectionIndex
}
}
}
class SectionInfo: CustomStringConvertible {
var numberOfRecords: Int { return records.count }
let name: String
fileprivate(set) var indexTitle: String?
private(set) var records: [CKRecord]
init(name: String, indexTitle: String? = nil, records: [CKRecord] = []) {
self.name = name
self.indexTitle = indexTitle
self.records = records
}
fileprivate func add(record: CKRecord) {
records.append(record)
}
// MARK: - CustomStringConvertible
var description: String {
return "SectionInfo(name: \"\(name)\", indexTitle: \(indexTitle), numberOfRecords: \(numberOfRecords), records: \(records))"
}
}
// Example options for mapping section names to section index titles:
struct SectionIndexTitleForSectionName {
static let firstLetterOfString = { (string: String) -> String? in
guard let firstCharacter = (string as String).characters.first else {
return ""
}
return String(firstCharacter).uppercased()
}
static let fullString = { (string: String) -> String? in
return string as String
}
static let fullStringUppercased = { (string: String) -> String? in
return (string as String).uppercased()
}
}
/// split(records:bySectionNameKey)
///
/// Takes an input array of CKRecords, and splits them into sections using the (String) value retrieved from each record's "sectionNameKey".
///
/// The relative ordering of the records in the input array is maintained in each section.
///
/// - parameter records: An array of records to be split into sections.
/// - parameter bySectionNameKey: The key on the CKRecords used to determine the section they belong to.
/// Assumes that record[sectionNameKey] returns a String value.
///
/// - returns: An array of sections, and a dictionary mapping sectionName -> the index in the sections array.
func split(records: [CKRecord], bySectionNameKey sectionNameKey: String) -> (sections: [SectionInfo], sectionNameToSection: [String: Int])
{
func sectionName(forRecord record: CKRecord, withSectionNameKey sectionNameKey: String) -> String? {
guard let sectionNameValue = record.object(forKey: sectionNameKey) else {
assertionFailure("Record is missing expected sectionNameKey (\(sectionNameKey)): \(record)")
return nil
}
guard let sectionName = sectionNameValue as? String else {
assertionFailure("Record[\(sectionNameKey)] contains a value that cannot be converted directly to String. Record: \(record)")
return nil
}
return sectionName
}
var sections: [SectionInfo] = []
var sectionNameToSection: [String: Int] = [:]
var currentSection: SectionInfo? = nil
for record in records {
guard let sectionName = sectionName(forRecord: record, withSectionNameKey: sectionNameKey) else {
assertionFailure("Unable to obtain expected sectionNameKey (\(sectionNameKey)) for record: \(record)")
continue
}
if let currentSection = currentSection, currentSection.name == sectionName {
currentSection.add(record: record)
}
else {
// find existing section, if present
if let desiredSectionIndex = sectionNameToSection[sectionName] {
sections[desiredSectionIndex].add(record: record)
}
else {
// create new section
let newSection = SectionInfo(name: sectionName, records: [record])
sections.append(newSection)
sectionNameToSection[sectionName] = sections.count - 1
currentSection = newSection
}
}
}
return (sections: sections, sectionNameToSection: sectionNameToSection)
}
关于ios - 来自 CloudKit 查询的 UITableView 部分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39623839/
我坚持我的项目(用 Swift 编写) 我有一个 UITableView,它有一个字符串,它提供了表格中的十个类别。我想做的是选择这些类别中的一个来触摸它,然后打开一个包含其他类别的 secondTa
好的,这从 iOS 7 Beta 6 开始就被打破了。 在启动时,我将表格 View 的背景更改为图像(如果我将其设置为颜色,它会做同样的事情)并且表格单元格是白色的...... 当我选择一个单元格时
我有一个包含不同部分的 UITableView,每个单元格上都有一个图像。因为图像是为每个单元格单独下载的,所以我正在寻找一种延迟加载解决方案。 在 iOS Developer Library 上,它
关闭。这个问题不满足Stack Overflow guidelines .它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。 7年前关闭。 Improve thi
可以在UIRefreshControl的底部添加UITableView吗? 我会用它来加载更多数据。 拜托,有什么建议吗? 最佳答案 我相信不会有任何简单的解决方案来解决这个问题。可能有人可以编写一个
我有一个 UITableView 和一个使用 Swift 的自定义 UITableViewCell。当我设置 self.MyTable.editing = true 时,我看到该行上有删除图标,并且似
我为 iPhone 创建了一个下载器应用程序。我有用于显示主动/被动下载的表格 View 。在 tableview 的自定义单元格中有进度条,它显示 %XX 下载状态。现在我正在使用 NSTimer
我正在编写 UITableView 的自定义子类。我需要这个对象本身成为它自己的数据源和委托(delegate),然后这个子类将有它自己的数据源和委托(delegate)。这主要是为了让我可以拦截对数
我有一个问题已经困扰我几天了。 我有一个名为 countries 的数组。该数组包含一个自定义对象,其中包含国家、城市、IP、状态等数据。 我需要在按属性“国家/地区”划分的表格 View 中显示这些
我有一个 UITableViewController,目前显示 4 个将始终显示的单元格,并且想将它们组合在一起,但我不知道如何操作。当在 UIViewController 或类似的东西上插入标准 U
我以编程方式创建了一个 UITableView,现在我想向它添加一个固定的标题。 正如我下面的代码一样,标题也随着我的 tableview 滚动。 UILabel *label = [[[UI
我正在创建一个 UITableViewController(在 UINavigationController 的根部)并在另一个 View Controller 之上以模态方式呈现它。我让它在一定程度
我有问题。我有动态 TableView 。所以我需要在我的 textLabel 中更改文本大小。我试过: 一个: cell.textLabel.font = [UIFont systemFontOfS
iOS 8 中的新功能是 separatorEffect属性,您可以为其分配 UIVisualEffect。有没有人知道这是做什么用的?我试过了,我不认为它有任何,呃,视觉效果。 最佳答案 我想知道完
今天早上,我刚刚安装了包含iOS 6的新Xcode。 我有一个加载了包含章节和行的plist文件的表格 View 。各章定义各节。 用户选择章节和行,并将tableview自动滚动到正确的位置(在vi
我在iOS 7上启动VoiceOver时遇到了一些麻烦。我确实在UITableViewHeaderFooterView中注册了viewDidLoad子类的实例,但是当我用-[tableView deq
我在 UITableView 中添加了一些数据,我想更改单元格中显示的文本的颜色。 是否有委托(delegate)方法可以执行此操作,或者有其他方式吗? 最佳答案 无需标签 您只需要编码: cell.
是否可以在滚动 UITableView 时动态更改单元格的高度? 当用户将其向下拖动到顶部时,滚动位置到达某个点时,我需要更改多个单元格的高度。我可以通过发出 reloadData 成功地做到这一点,
我正在使用 iOS 5,并在表格中动态生成单元格(2 个部分,每个部分 3 行)。每个部分都有一个标题,该标题也是使用 titleForHeaderInSection 调用动态生成的。 我还设置了一个
我正在寻找 UITableView 的回调函数当我使用 Apple Remote 导航并按向上或向下键选择行时(而不是按 Enter 键时),当该行聚焦时。 在 iOS 上,我们有 didSelect
我是一名优秀的程序员,十分优秀!