Skip to content

Instantly share code, notes, and snippets.

@ezfe
Created August 22, 2016 19:01
Show Gist options
  • Save ezfe/61305097eb70a9f56bca60f39d744845 to your computer and use it in GitHub Desktop.
Save ezfe/61305097eb70a9f56bca60f39d744845 to your computer and use it in GitHub Desktop.
ConnectorKit
//
// CKManager.swift
// Connector
//
// Created by Ezekiel Elin on 8/20/16.
// Copyright © 2016 Ezekiel Elin. All rights reserved.
//
import Foundation
import CloudKit
public class CKManager {
public static let shared = CKManager()
let container = CKContainer(identifier: "iCloud.com.ezekielelin.Connector")
let publicDB = CKContainer(identifier: "iCloud.com.ezekielelin.Connector").publicCloudDatabase
public var conversations = [Conversation]()
public var messages = [Message]()
public var loadedConversation: Conversation? = nil
public var currentUserID: CKRecordID? = nil
public var newMessageCompletionHandler: ((_ message: [CKRecord]) -> Void)? = nil
init() {
currentUser(completion: {_, _ in})
DispatchQueue.main.async {
self.testTimer()
}
}
public func sendMessage(_ message: Message, completion: @escaping (Void) -> Void) {
publicDB.save(message) { (message, error) in
guard let message = message else {
print(error)
return
}
self.messages.append(message)
completion()
}
}
public func refreshConversations(completion: @escaping ([Conversation]) -> Void) {
currentUser { (user, error) in
guard let user = user else {
print(error)
return
}
let predicate = NSPredicate(format: "participants CONTAINS %@", user)
let query = CKQuery(recordType: "Conversation", predicate: predicate)
self.publicDB.perform(query, inZoneWith: nil, completionHandler: { (records, error) in
guard let records = records else {
print(error)
return
}
let conversations = records.map({ (record) -> Conversation in
return Conversation(record: record)!
})
self.conversations = conversations
completion(conversations)
})
}
}
public func loadConversation(conversation: Conversation, completion: @escaping ([CKRecord]) -> Void) {
let predicate = NSPredicate(format: "conversation == %@", conversation.record)
let query = CKQuery(recordType: "Message", predicate: predicate)
self.publicDB.perform(query, inZoneWith: nil) { (records, error) in
guard let records = records else {
print(error)
return
}
let messages = records.map({ (record) -> Message in
return Message(record: record)!
})
self.messages = messages.sorted(by: { $0.creationDate < $1.creationDate })
self.loadedConversation = conversation
completion(records)
}
}
@objc func testTimer() {
print("Refresh...")
self.refreshCurrentConversation { (messages) in
print("Loaded messages")
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
self.testTimer()
}
if let completion = self.newMessageCompletionHandler {
completion(messages)
}
}
}
public func refreshCurrentConversation(completion: @escaping ([CKRecord]) -> Void) {
guard let conversation = self.loadedConversation else {
print("No loaded conversation")
completion([]) //TODO: Send error?
return
}
loadConversation(conversation: conversation, completion: completion)
}
public func currentUser(completion: @escaping (_ record: CKRecord?, _ error: Error?) -> Void) {
if let id = currentUserID {
self.publicDB.fetch(withRecordID: id, completionHandler: completion)
} else {
container.fetchUserRecordID { (id, error) in
guard let id = id else {
completion(nil, error)
return
}
self.publicDB.fetch(withRecordID: id, completionHandler: completion)
}
}
}
func subscribe() {
guard let _ = loadedConversation else {
print("No conversation")
return
}
//let predicate = NSPredicate(format: "conversation == %@", conversation)
let predicate = NSPredicate(value: true)
let subscription = CKSubscription(recordType: "Message", predicate: predicate, options: .firesOnRecordCreation)
let notificationInfo = CKNotificationInfo()
notificationInfo.shouldBadge = true
notificationInfo.shouldSendContentAvailable = true
subscription.notificationInfo = notificationInfo
publicDB.save(subscription) { (subscription, error) in
guard let _ = subscription else {
print(error)
return
}
}
}
}
//
// Conversation.swift
// Connector
//
// Created by Ezekiel Elin on 8/22/16.
// Copyright © 2016 Ezekiel Elin. All rights reserved.
//
import Foundation
import CloudKit
public class Conversation: RecordAbstractable {
public var record: CKRecord
public let recordType = "Conversation"
public required init?(record: CKRecord) {
if record.recordType != recordType {
return nil
} else {
self.record = record
}
}
}
//
// Message.swift
// Connector
//
// Created by Ezekiel Elin on 8/22/16.
// Copyright © 2016 Ezekiel Elin. All rights reserved.
//
import Foundation
import CloudKit
public class Message: RecordAbstractable {
public var record: CKRecord
public let recordType = "Message"
public let textKey = "text"
public let conversationKey = "conversation"
public init(conversation: Conversation, text: String) {
let conversationReference = CKReference(record: conversation.record, action: .none)
record = CKRecord(recordType: recordType)
record.setValue(text, forKey: textKey)
record.setValue(conversationReference, forKey: conversationKey)
}
public required init?(record: CKRecord) {
if record.recordType != recordType {
return nil
} else {
self.record = record
}
}
public var text: String {
return self.record.value(forKey: textKey) as? String ?? ""
}
}
//
// RecordAbstract.swift
// Connector
//
// Created by Ezekiel Elin on 8/22/16.
// Copyright © 2016 Ezekiel Elin. All rights reserved.
//
import Foundation
import CloudKit
public protocol RecordAbstractable: class {
var record: CKRecord { get set }
var recordType: String { get }
init?(record: CKRecord)
var creationDate: Date { get }
}
public extension CKDatabase {
func save<T: RecordAbstractable>(_ abstract: T, completionHandler: @escaping (T?, Error?) -> Void) {
self.save(abstract.record) { (record, error) in
if let record = record {
abstract.record = record
completionHandler(abstract, error)
} else {
completionHandler(nil, error)
}
}
}
}
public extension RecordAbstractable {
public var creationDate: Date {
return self.record.creationDate ?? Date()
}
public var creatorUserRecordID: CKRecordID? {
return self.record.creatorUserRecordID
}
}
//
// Utility.swift
// Connector
//
// Created by Ezekiel Elin on 8/20/16.
// Copyright © 2016 Ezekiel Elin. All rights reserved.
//
import Foundation
public func print(_ e: Error?) {
print(e?.localizedDescription ?? "Unknown Error")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment