如何使用swift 3.0和CloudKit创建一个feed,该feed将来自不同其他记录的记录混合在一起,并限制为一个数字?
所以我一直在开发一款应用程序,它的工作原理基本上类似于facebook(简单得多),但更适合学校。它包含提要、带有帖子的类、带有帖子的组、带有帖子的朋友等等。我想要的是能够从我所在的朋友、团体和班级获取帖子,并将它们加载到新闻提要中的tableView中如何使用swift 3.0和CloudKit创建一个feed,该feed将来自不同其他记录的记录混合在一起,并限制为一个数字?,swift,database,xcode,cloudkit,Swift,Database,Xcode,Cloudkit,所以我一直在开发一款应用程序,它的工作原理基本上类似于facebook(简单得多),但更适合学校。它包含提要、带有帖子的类、带有帖子的组、带有帖子的朋友等等。我想要的是能够从我所在的朋友、团体和班级获取帖子,并将它们加载到新闻提要中的tableView中 数据库的结构: Post { (...) user: Reference likes: Reference list //users comments: Reference list //comments } User
数据库的结构:
Post {
(...)
user: Reference
likes: Reference list //users
comments: Reference list //comments
}
User {
(...)
name: String
surname: String
friends: Reference list
posts: Reference list
}
Class {
(...)
posts: Reference list
}
到目前为止,我的新闻提要(相关)代码:
// Class used for controlling CloudKit
class DatabaseController {
var publicDatabase = CKContainer.default().publicCloudDatabase
func reload() {
publicDatabase = CKContainer.default().publicCloudDatabase
}
func networkCheck() -> Bool {
var networkConnection = true
doesRecordExist(withRecordName: "test", withFieldName: "test", equalTo: "test") { _, _, error in
switch CKError(_nsError: error!) {
case CKError.networkFailure, CKError.networkUnavailable, CKError.serviceUnavailable: networkConnection = false
default: break
}
}
return networkConnection
}
//Q U E R I E S
func doesRecordExist(withRecordName: String, withFieldName: String, equalTo: String, completionHandler: @escaping (Bool?, CKRecord?, NSError?) -> Void) {
print(withFieldName,equalTo)
//this function checks if a record with specified value of a specified field exists.
//initiating the query
let predicate = NSPredicate(format: "\(withFieldName) == %@", equalTo)
let query = CKQuery(recordType: withRecordName, predicate: predicate)
publicDatabase.perform(query, inZoneWith: nil) {results, error in
if error != nil {
//if there is an error
completionHandler(nil, nil, error as NSError?)
return
}
guard let results = results else {
//if reults are nil
completionHandler(nil, nil, error as NSError?)
print("error 2")
return
}
if results.count == 1 {
//if found
completionHandler(true, results[0], nil)
print(results)
} else {
//if not found
completionHandler(false, nil, nil)
print("not found")
}
}
}
func getAllRecords(withRecordType: String, withDesiredKeys: [String], sortForkey: String, ascending: Bool, withResultLimit: Int, operations:Int, completionHandler: @escaping ([CKRecord], NSError?) -> Void) {
//prepare the variables to create a query for wanted records and retrieve them.
var records: [CKRecord] = []
let predicate = NSPredicate(value: true)
let sort = NSSortDescriptor(key: sortForkey, ascending: ascending)
let query = CKQuery(recordType: withRecordType, predicate: predicate)
query.sortDescriptors = [sort]
//limiting the query using operation
let operation = CKQueryOperation(query: query)
operation.desiredKeys = withDesiredKeys
operation.resultsLimit = withResultLimit
//completing the query
operation.recordFetchedBlock = { record in
records.append(record)
print(1)
}
//executing the operation
operation.queryCompletionBlock = { [unowned self] (cursor, error) in
var count = 0
//checking weather there is a need for more than one operations
if error != nil && count < operations {
count += 1
let newOperation = CKQueryOperation(cursor: cursor!)
newOperation.queryCompletionBlock = operation.queryCompletionBlock
self.publicDatabase.add(newOperation)
} else {
print(2)
completionHandler(records, nil)
}
}
publicDatabase.add(operation)
}
}
//用于控制CloudKit的类
类数据库控制器{
var publicDatabase=CKContainer.default().publicCloudDatabase
func reload(){
publicDatabase=CKContainer.default().publicCloudDatabase
}
func networkCheck()->Bool{
var networkConnection=true
doesRecordExist(记录名为“test”,字段名为“test”,相等于“test”){uu,u,错误在
开关CKError(\n错误:错误!){
案例CKError.networkFailure,CKError.networkUnavailable,CKError.serviceinavailable:networkConnection=false
默认值:中断
}
}
返回网络连接
}
//Q U E R I S
func doesRecordExist(withRecordName:String、withFieldName:String、equalTo:String、completionHandler:@escaping(Bool?、CKRecord?、NSError?)->Void){
打印(带字段名,等号)
//此函数用于检查是否存在具有指定字段的指定值的记录。
//启动查询
let predicate=NSPredicate(格式:“\(带字段名)=%@”,等号)
let query=CKQuery(记录类型:withRecordName,谓词:谓词)
perform(query,inZoneWith:nil){results,错误在
如果错误!=nil{
//如果有错误
completionHandler(nil,nil,错误为NSError?)
返回
}
guard let results=其他结果{
//如果reults为零
completionHandler(nil,nil,错误为NSError?)
打印(“错误2”)
返回
}
如果results.count==1{
//如果找到
completionHandler(true,结果[0],nil)
打印(结果)
}否则{
//如果找不到
completionHandler(false、nil、nil)
打印(“未找到”)
}
}
}
func getAllRecords(withRecordType:String,withDesiredKeys:[String],SortWorkey:String,升序:Bool,withResultLimit:Int,operations:Int,completionHandler:@escaping([CKRecord],NSError?)->Void){
//准备变量以创建所需记录的查询并检索它们。
变量记录:[CKRecord]=[]
let谓词=NSPredicate(值:true)
让sort=NSSortDescriptor(键:SortWorkey,升序:升序)
let query=CKQuery(记录类型:withRecordType,谓词:谓词)
query.sortDescriptors=[sort]
//使用操作限制查询
let operation=CKQueryOperation(查询:query)
operation.desiredKeys=带desiredKeys
operation.resultsLimit=withResultLimit
//完成查询
operation.recordFetchedBlock={中的记录
记录。追加(记录)
印刷品(1)
}
//执行操作
operation.queryCompletionBlock={[unowned self](光标,错误)位于
变量计数=0
//检查天气需要不止一次操作
如果错误!=nil&&count<操作{
计数+=1
让newOperation=CKQueryOperation(游标:游标!)
newOperation.queryCompletionBlock=operation.queryCompletionBlock
self.publicDatabase.add(newOperation)
}否则{
印刷品(2)
completionHandler(记录,无)
}
}
publicDatabase.add(操作)
}
}
及
类MyFeedTViewController:UITableViewController{
var posts:[CKRecord]!=[]
var database=DatabaseController()
变量定时器:定时器!
重写func viewDidLoad(){
super.viewDidLoad()
timer=timer.scheduledTimer(时间间隔:60.0,目标:self,选择器:#选择器(MyFeedTViewController.refresh),userInfo:nil,repeats:true)
计时器。火()
database.getAllRecords(带RecordType:“Post”,带DesiredKey:[“user”,“text”,“comments”,“Pluses”],SortWorkey:“creationDate”,升序:false,带ResultLimit:5,操作:1){记录,错误
如果错误==nil{
self.posts=记录
DispatchQueue.main.async{
self.tableView.reloadData()
}
}
}
}
func刷新(){
database.getAllRecords(带RecordType:“Post”,带DesiredKey:[“user”,“text”,“comments”,“Pluses”],SortWorkey:“creationDate”,升序:false,带ResultLimit:5,操作:1){记录,错误
如果错误==nil{
如果记录!=self.posts{
self.posts=记录
DispatchQueue.main.async{
self.tableView.reloadData()
self.refreshControl?.endRefreshing()
}
}
}
}
}
//标记:-表视图数据源
重写func numberOfSections(在tableView:UITableView中)->Int{
//#警告未完成执行,返回节数
返回1
}
重写func tableView(tableView:UITableView,numberofrowsinssection:Int)->Int{
打印(posts.count)
返回岗位数
}
重写func tableView(tableView:UITableView,cellForRowAt indexath:indexPath)->UITableViewCell{
设单元格=表v
class MyFeedTViewController: UITableViewController {
var posts: [CKRecord]! = []
var database = DatabaseController()
var timer: Timer!
override func viewDidLoad() {
super.viewDidLoad()
timer = Timer.scheduledTimer(timeInterval: 60.0, target: self, selector: #selector(MyFeedTViewController.refresh), userInfo: nil, repeats: true)
timer.fire()
database.getAllRecords(withRecordType: "Post", withDesiredKeys: ["user","text", "comments", "plusses"], sortForkey: "creationDate", ascending: false, withResultLimit: 5, operations: 1) { records, error in
if error == nil {
self.posts = records
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
}
}
func refresh() {
database.getAllRecords(withRecordType: "Post", withDesiredKeys: ["user","text", "comments", "plusses"], sortForkey: "creationDate", ascending: false, withResultLimit: 5, operations: 1) { records, error in
if error == nil {
if records != self.posts {
self.posts = records
DispatchQueue.main.async {
self.tableView.reloadData()
self.refreshControl?.endRefreshing()
}
}
}
}
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print(posts.count)
return posts.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Text Post", for: indexPath) as! PostCell
// Configure the cell...
let post = posts[indexPath.row]
cell.commentsNLabel.setTitle(String((post["comments"] as? Array<Any>)?.count ?? 0) + " comments", for: .normal)
var name: String!
var surname: String!
guard let recordReference: CKReference = (post["user"] as? CKReference) else {
print("error")
return cell
}
database.publicDatabase.fetch(withRecordID: recordReference.recordID ) { record, error in
if error == nil {
name = record!.value(forKey: "name") as? String ?? "null"
surname = record!.value(forKey: "surname") as? String ?? "null"
cell.usernameLabel.text = name + " " + surname
countOperations += 1
}
}
cell.whenPostedLabel.text = EdAppKit().returnStringTillNow(from: (post["creationDate"] as? NSDate) ?? NSDate())
cell.plusesNLabel.text = String((post["plusses"] as? Array<Any>)?.count ?? 0) + " plusses"
cell.postText.text = String((post["text"] as? String) ?? "null")
return cell
}
}