Created
August 22, 2016 19:01
-
-
Save ezfe/61305097eb70a9f56bca60f39d744845 to your computer and use it in GitHub Desktop.
ConnectorKit
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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 | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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 | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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 ?? "" | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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 | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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