Skip to content

Instantly share code, notes, and snippets.

@mingsai
Created February 12, 2016 17:48
Show Gist options
  • Select an option

  • Save mingsai/35d10e434a97584bab23 to your computer and use it in GitHub Desktop.

Select an option

Save mingsai/35d10e434a97584bab23 to your computer and use it in GitHub Desktop.
A Swift class to help manage cloud events using Apple's CloudKit platform. This is the experimental version.
// MNGCloudManager.swift
//
//
// Created by Tommie N. Carter, Jr., MBA on 7/25/15.
// Copyright © 2015 MING Technology. All rights reserved.
//
import Foundation
import CloudKit
import CoreData
import UIKit
enum StoryType {
case Audio, Text, Picture, Video
static let allValues = [Audio, Text, Picture, Video]
}
struct MNGCloudKitEvents {
static let AccessError = "Cloud Access Error"
static let SaveError = "Save Error"
static let SaveSuccess = "Success"
static let NoMatchFound = "No Match Found"
static let MatchFound = "Match Found"
static let ErrorOccurred = "Error Occurred"
static let DeleteSuccess = "Delete Success"
static let DeleteError = "Delete Error"
static let ProcessCompleted = "ProcessCompleted"
static let ProcessError = "Process Error"
}
struct MNGCloudAssetsRecord {
static let RecordName = "Assets"
static let AssetColumn = "asset"
}
struct MNGCloudSharedStoriesRecord {
static let RecordName = "SharedStories"
static let DateExpiresColumn = "dateExpires"
static let LocationColumn = "location"
static let StorySharedToListReferenceColumn = "sharedTo"
static let StoryAssetColumn = "storyAsset"
static let StoryTypeColumn = "type" //W|V|P|T
static let StoryStatusColumn = "status" //use for public, private
}
struct MNGCloudInvitesRecord {
static let RecordName = "Invites"
static let DateJoinedColumn = "dateJoined"
static let EmailColumn = "email"
static let FamilyNameColumn = "familyName"
static let GivenNameColumn = "givenName"
static let PhoneColumn = "phone"
static let StatusColumn = "status"
static let NewUserIdReferenceColumn = "newUserId"
}
struct MNGCloudUserInfoRecord {
static let RecordName = "Users"
static let AppUserIdColumn = "appUserId"
static let LocationColumn = "location"
static let ProfilePhotoAssetColumn = "profilePhoto"
}
//Status = P(ending), R(egistered), F(ailed), B(locked)
struct MNGCloudUserRegisterationRecord {
static let RecordName = "Registered"
static let DateExpiresColumn = "dateExpires"
static let EmailColumn = "email"
static let FamilyNameColumn = "familyName"
static let GivenNameColumn = "givenName"
static let PhoneColumn = "phone"
static let SecretColumn = "secret"
static let StatusColumn = "status"
}
@objc protocol MNGCloudManagerDelegate {
optional func cloudManagerDidReturnKnownContacts(objects:[NSDictionary])
optional func cloudManagerDidReturnInvitesInfo(objects:[NSDictionary])
optional func cloudManagerDidReturnSharedStoryInfo(objects:[NSDictionary])
optional func cloudManagerDidReturnUser(id:String)
optional func cloudManagerDidSaveStoryInfo(recordId:String)
optional func cloudManagerDidFailToSaveStoryInfo(error:NSError)
optional func cloudManagerDidSaveUserInfo(recordId:String)
optional func cloudManagerDidSaveUserRegistrationInfo(recordId:String)
optional func cloudManagerDidFailToSaveUserRegistrationInfo(error:NSError)
optional func cloudManagerDidSaveInvitationInfo(recordId:String)
optional func cloudManagerDidFailToSaveInvitationInfo(error:NSError)
optional func cloudManagerDidFailWithCloudError (error: NSError)
}
class MNGCloudManager:NSObject {
var delegate:MNGCloudManagerDelegate? = nil
static let sharedInstance = MNGCloudManager()
private struct Constants {
static let CloudUserSubscribed = "CloudUserSubscribed"
static let CloudUserSubscriptionID = "CloudUserScriptionID"
static let SelectorCloudEventObserved = Selector ("cloudEventObserved:")
}
lazy var isSubscribed: Bool = {
let keyfound = NSUserDefaults.standardUserDefaults().objectForKey(Constants.CloudUserSubscribed) != nil
if !keyfound {
//add default key value
NSUserDefaults.standardUserDefaults().setBool(false, forKey: Constants.CloudUserSubscribed)
} else if keyfound && NSUserDefaults.standardUserDefaults().boolForKey(Constants.CloudUserSubscribed) == true {
return true
} else {
return false
}
return false
}()
let container = CKContainer.defaultContainer()
lazy var publicDatabase:CKDatabase? = {
return self.container.publicCloudDatabase
}()
lazy var privateDatabase:CKDatabase? = {
return self.container.privateCloudDatabase
}()
deinit{
unregisterEventObservations()
}
override init(){
super.init()
registerEventObservations()
}
//MARK: Shared Stories Methods
func unshareStory(sharedID:CKRecordID){
}
/* Saves the object graph to a CKAsset (fileURL) on the cloud 10 gb limit */
func shareStory(rootObject:AnyObject?, properties: [String: AnyObject?])
{
//properties to set other than Story are Owner, SharedTo, Type
guard rootObject != nil && properties.count != 0 else {return}
let tmpPath = NSTemporaryDirectory() + NSUUID().UUIDString
let tmpURL = NSURL(fileURLWithPath: tmpPath)
let record = CKRecord(recordType: MNGCloudSharedStoriesRecord.RecordName)
if NSKeyedArchiver.archiveRootObject(rootObject!, toFile: tmpPath) {
let storyAsset = CKAsset(fileURL: tmpURL)
record[MNGCloudSharedStoriesRecord.StoryAssetColumn] = storyAsset
}
for (key, value) in properties {
record.setObject(value as? CKRecordValue, forKey: key)//(value, forKey: key)
}
publicDatabase!.saveRecord(record, completionHandler:
({returnRecord, error in
if let err = error {
self.notifyUser(MNGCloudKitEvents.SaveError, message:
err.localizedDescription)
} else {
dispatch_async(dispatch_get_main_queue()) {
//tell the delegate that the record was saved
// self.notifyUser(MNGCloudKitEvents.CloudKitSavedSuccessTitle,
// message: MNGCloudKitEvents.CloudKitSavedSuccessMessage)
self.cleanupTempFile(tmpPath)
}
}
}))
}
func share(story:AnyObject, user:String) {
}
func findSharedStoriesForUser(id:String) {
}
private func cleanupTempFile(atPath:String) {
//cleanup the tmp file
if NSFileManager.defaultManager().fileExistsAtPath(atPath) {
do {
try NSFileManager.defaultManager().removeItemAtPath(atPath)
} catch let e as NSError {
print(e.localizedDescription)
}
}
}
private func uploadAssetWithURL (assetURL:NSURL, completionHandler:(record:CKRecord)->()) {
let assetRecord = CKRecord(recordType: MNGCloudAssetsRecord.RecordName)
let asset = CKAsset(fileURL: assetURL)
assetRecord[MNGCloudAssetsRecord.AssetColumn] = asset
//TODO:Add properties to function call and loop to assign
self.publicDatabase?.saveRecord(assetRecord, completionHandler: { (record, error) -> Void in
if (( error ) != nil) {
print(error!.localizedDescription)
} else {
dispatch_async (dispatch_get_main_queue(), { () -> Void in
//post notification with recordInfo
//completionHandler(record);
})
}
})
}
//MARK: Notification Methods
func notifyUser(title: String, message: String) -> Void
{
let alert = UIAlertController(title: title,
message: message,
preferredStyle: UIAlertControllerStyle.Alert)
let cancelAction = UIAlertAction(title: "OK",
style: .Cancel, handler: nil)
alert.addAction(cancelAction)
//TODO: Create a listener to pick this up
defaultCenter.postNotificationName(MNGCloudKitEvents.ProcessCompleted, object: alert)
//send this as a notification object to a UIVC
//self.presentViewController(alert, animated: true, completion: nil)
}
//MARK: Invite Methods
func postInviteByPhone(phone:String){
}
func postInviteByEmail(email:String){
}
func updateInvite(record:CKRecord, status:String){
}
//MARK: Registration Methods
func postRegisteredUser(userID:String) {
// call the function above in the following way:
// (userID is the string you are intersted in!)
findCurrentCKUser({ (instance, error) -> () in
if let userID = instance?.recordName {
print("received iCloudID \(userID)")
} else {
print("Fetched iCloudID was nil")
}
})
}
//MARK: User Methods
func configureCurrentCKUser (userInfo:NSDictionary) {
if let container:CKContainer? = CKContainer.defaultContainer() {
container!.fetchUserRecordIDWithCompletionHandler() {
recordID, error in
if error != nil {
self.delegate?.cloudManagerDidFailWithCloudError!(error!)
return
}
if let record:CKRecord? = CKRecord(recordType: "Users", recordID: recordID!) {
//process user info
if let photoAsset = userInfo[MNGCloudUserInfoRecord.ProfilePhotoAssetColumn] {
record!.setObject(photoAsset as? CKAsset, forKey: MNGCloudUserInfoRecord.ProfilePhotoAssetColumn)
}
if let location = userInfo[MNGCloudUserInfoRecord.LocationColumn] {
record!.setObject(location as? CLLocation, forKey: MNGCloudUserInfoRecord.LocationColumn)
}
if let appUserId = userInfo[MNGCloudUserInfoRecord.AppUserIdColumn] {
record!.setObject(appUserId as? String, forKey: MNGCloudUserInfoRecord.AppUserIdColumn)
}
//save to cloud db
self.publicDatabase?.saveRecord(record!, completionHandler: { (record, error) -> Void in
if error != nil {
//print(error!.localizedDescription)
NSOperationQueue.mainQueue().addOperationWithBlock ({ Void in
self.delegate?.cloudManagerDidFailWithCloudError!(error!)
})
return
}
NSOperationQueue.mainQueue().addOperationWithBlock ({ Void in
//print( self.delegate )
self.delegate?.cloudManagerDidSaveUserInfo!(record!.recordID.recordName)
})
})
}
}
}
}
/// async gets iCloud record name of logged-in user
func findCurrentCKUser(complete: (instance: CKRecordID?, error: NSError?) -> ()) {
let container = CKContainer.defaultContainer()
container.fetchUserRecordIDWithCompletionHandler() {
recordID, error in
if error != nil {
print(error!.localizedDescription)
complete(instance: nil, error: error)
} else {
print("fetched ID \(recordID?.recordName)")
self.delegate?.cloudManagerDidReturnUser!(recordID!.recordName)
complete(instance: recordID, error: nil)
}
}
}
func findUserByEmail (email:String) {
}
func findUserByPhone (phone:String) {
}
func findUsersInContactBook () {
}
func findContactsRelatedToUser() {
let discoverOperation = CKDiscoverAllContactsOperation()
discoverOperation.qualityOfService = NSQualityOfService.Background
//discoverOperation.usesBackgroundSession = true
discoverOperation.queuePriority = NSOperationQueuePriority.Normal
discoverOperation.discoverAllContactsCompletionBlock = {
(userInfos, error) in
if (( error ) != nil) {
print(error!.localizedDescription)
} else {
//deal with the userInfos returned
dispatch_async(dispatch_get_main_queue()) { [weak self] () -> Void in
self?.notifyUser(MNGCloudKitEvents.MatchFound,
message: MNGCloudKitEvents.MatchFound)
//do something with the users' matching contacts
//defaultCenter.postNotificationName(MNGCloudKitEvents.CloudKitMatchFound, object: userInfos.map{ ( $0 ) } )
}
}
}
self.container.addOperation(discoverOperation)
}
func findSharedRecords <T> (typeIndicator:String!) -> [T]?{
guard typeIndicator != "" else { return nil }
var typedResults: [T]?
let format = "%K = %@"
let predicate = NSPredicate(format: format, argumentArray: [MNGCloudSharedStoriesRecord.StoryTypeColumn,typeIndicator])//NSPredicate(value: true)
let query = CKQuery(recordType: MNGCloudSharedStoriesRecord.RecordName, predicate: predicate)
publicDatabase!.performQuery(query, inZoneWithID: nil) { (results, error ) -> Void in
if error != nil {
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.notifyUser(MNGCloudKitEvents.AccessError, message: (error?.localizedDescription)!)
})
} else if results?.count > 0 {
typedResults = [T]()
for record in results! {
if let tmp = record[MNGCloudSharedStoriesRecord.StoryAssetColumn] as?
CKAsset {
let story = NSKeyedUnarchiver.unarchiveObjectWithFile(tmp.fileURL.absoluteString) as! T
typedResults!.append(story)
}
}
}
}
if typedResults?.count > 0 {
return typedResults!
} else {
return nil
}
}
func findPrivateShareRecords <T> (typeIndicator:String!, toUser:String!) -> [T]?{
guard typeIndicator != "" && toUser != "" else { return nil }
var typedResults: [T]?
let format = "%K contains %@"
//TODO: Wrap id as CKReference
let predicate = NSPredicate(format: format, argumentArray: [MNGCloudSharedStoriesRecord.StoryTypeColumn,typeIndicator,MNGCloudSharedStoriesRecord.StorySharedToListReferenceColumn, toUser] ) //NSPredicate(value: true)
let query = CKQuery(recordType: MNGCloudSharedStoriesRecord.RecordName, predicate: predicate)
publicDatabase!.performQuery(query, inZoneWithID: nil) { (results, error ) -> Void in
if error != nil {
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.notifyUser(MNGCloudKitEvents.AccessError, message: (error?.localizedDescription)!)
})
} else if results?.count > 0 {
typedResults = [T]()
for record in results! {
if let tmp = record[MNGCloudSharedStoriesRecord.StoryAssetColumn] as?
CKAsset {
let story = NSKeyedUnarchiver.unarchiveObjectWithFile(tmp.fileURL.absoluteString) as! T
typedResults!.append(story)
}
}
}
}
if typedResults?.count > 0 {
return typedResults!
} else {
return nil
}
}
//MARK: Cloud Management Methods
func requestDiscoverabilityPermission(completionHandler: (discoverable:Bool!)->()) {
self.container.requestApplicationPermission(CKApplicationPermissions.UserDiscoverability, completionHandler: { (status, error) -> Void in
if ((error) != nil) {
print(error!.localizedDescription)
} else {
dispatch_async(dispatch_get_main_queue(), { () -> Void in
//check status == CKApplicationPermissionStatus.Granted
})
}
})
}
func discoverUserInfo( completionHandler:( user:CKDiscoveredUserInfo!)->() ) {
self.container.fetchUserRecordIDWithCompletionHandler ({ userID, error -> Void in
if (( error ) != nil) {
print(error!.localizedDescription)
} else {
self.container.discoverUserInfoWithUserRecordID (userID!, completionHandler: { (userInfo, error) -> Void in
if (( error ) != nil) {
print(error!.localizedDescription)
} else {
dispatch_async (dispatch_get_main_queue(), { () -> Void in
//post notification with userInfo
})
}
})
}
})
}
func saveRecord(aRecord:CKRecord, recordId:CKRecordID?){
self.publicDatabase?.saveRecord(aRecord, completionHandler: { (record, error) -> Void in
if error != nil {
//print(error!.localizedDescription)
NSOperationQueue.mainQueue().addOperationWithBlock ({ Void in
self.delegate?.cloudManagerDidFailWithCloudError!(error!)
})
return
}
//print("Saved Registration Record:\(record!.recordID.recordName)")
NSOperationQueue.mainQueue().addOperationWithBlock ({ Void in
//print( self.delegate )
self.delegate?.cloudManagerDidSaveUserRegistrationInfo!(aRecord.recordID.recordName)
})
})
}
func saveRecord (type:String, object:AnyObject?, id:CKRecordID?) {
var record:CKRecord? = nil
if id != nil {
record = CKRecord(recordType: type, recordID: id!)
} else {
record = CKRecord(recordType: type)
}
self.publicDatabase?.saveRecord(record!, completionHandler: { (record, error) in
//
if (( error ) != nil) {
print(error!.localizedDescription)
self.delegate?.cloudManagerDidFailWithCloudError!(error!)
} else {
dispatch_async (dispatch_get_main_queue(), { () -> Void in
//post notification with recordInfo
//completionHandler(record);
})
}
})
}
func saveRecordWithMetadata (record:CKRecord, properties:[String:AnyObject]) {
//save metadata
for (key, value) in properties {
record[key] = value as! String
}
self.publicDatabase?.saveRecord(record, completionHandler: { (record, error) in
//
if (( error ) != nil) {
print(error!.localizedDescription)
} else {
dispatch_async (dispatch_get_main_queue(), { () -> Void in
//post notification with recordInfo
//completionHandler(record);
})
}
})
}
func deleteRecord (record:CKRecord) {
self.publicDatabase?.deleteRecordWithID(record.recordID, completionHandler: { (record, error) -> Void in
//
if (( error ) != nil) {
print(error!.localizedDescription)
} else {
dispatch_async (dispatch_get_main_queue(), { () -> Void in
//post notification with recordInfo
//completionHandler(record);
})
}
})
}
//MARK: Insert Modify Methods
func insertSharedStoryRecord(storyInfo:NSDictionary){
let assetURL = NSURL()
//make two dependent operations here?
uploadAssetWithURL(assetURL) { (record) -> () in
if let storyAssetReference:CKReference? = CKReference(record: record, action: .DeleteSelf) {
//save to story record reference field
}
}
}
func modifySharedStoryRecord(storyInfo:NSDictionary, usingRecordID recordID: String){
}
func insertInviteRecord(inviteInfo:NSDictionary) {
if let inviteRecord:CKRecord? = CKRecord(recordType: MNGCloudInvitesRecord.RecordName) {
if let joined = inviteInfo[MNGCloudInvitesRecord.DateJoinedColumn] as? NSDate {
inviteRecord?.setObject(joined, forKey: MNGCloudInvitesRecord.DateJoinedColumn)
}
if let email = inviteInfo[MNGCloudInvitesRecord.EmailColumn] as? String {
inviteRecord?.setObject(email, forKey: MNGCloudInvitesRecord.EmailColumn)
}
if let first = inviteInfo[MNGCloudInvitesRecord.GivenNameColumn] as? String {
inviteRecord?.setObject(first, forKey: MNGCloudInvitesRecord.GivenNameColumn)
}
if let last = inviteInfo[MNGCloudInvitesRecord.FamilyNameColumn] as? String {
inviteRecord?.setObject(last, forKey: MNGCloudInvitesRecord.FamilyNameColumn)
}
if let newUserId = inviteInfo[MNGCloudInvitesRecord.NewUserIdReferenceColumn] as? String {
let _tmp = CKRecordID(recordName: newUserId) //record id for newly registered user
let ckRef = CKReference(recordID: _tmp, action: .None)
inviteRecord?.setObject(ckRef, forKey: MNGCloudInvitesRecord.NewUserIdReferenceColumn)
}
if let phone = inviteInfo[MNGCloudInvitesRecord.PhoneColumn] as? String {
inviteRecord?.setObject(phone, forKey: MNGCloudInvitesRecord.PhoneColumn)
}
if let status = inviteInfo[MNGCloudInvitesRecord.StatusColumn] as? String {
inviteRecord?.setObject(status, forKey: MNGCloudInvitesRecord.StatusColumn)
}
self.publicDatabase?.saveRecord(inviteRecord!, completionHandler: { (record, error) -> Void in
if error != nil {
//print(error!.localizedDescription)
NSOperationQueue.mainQueue().addOperationWithBlock ({ Void in
self.delegate?.cloudManagerDidFailToSaveInvitationInfo!(error!)
})
return
}
//print("Saved Registration Record:\(record!.recordID.recordName)")
NSOperationQueue.mainQueue().addOperationWithBlock ({ Void in
//print( self.delegate )
self.delegate?.cloudManagerDidSaveInvitationInfo!(inviteRecord!.recordID.recordName)
})
})
}
}
func modifyInviteRecord(inviteInfo:NSDictionary, usingRecordIDName recordName: String){
if let inviteRecord:CKRecord? = CKRecord(recordType: MNGCloudInvitesRecord.RecordName, recordID: CKRecordID(recordName: recordName)) {
if let joined = inviteInfo[MNGCloudInvitesRecord.DateJoinedColumn] as? NSDate {
inviteRecord?.setObject(joined, forKey: MNGCloudInvitesRecord.DateJoinedColumn)
}
if let email = inviteInfo[MNGCloudInvitesRecord.EmailColumn] as? String {
inviteRecord?.setObject(email, forKey: MNGCloudInvitesRecord.EmailColumn)
}
if let first = inviteInfo[MNGCloudInvitesRecord.GivenNameColumn] as? String {
inviteRecord?.setObject(first, forKey: MNGCloudInvitesRecord.GivenNameColumn)
}
if let last = inviteInfo[MNGCloudInvitesRecord.FamilyNameColumn] as? String {
inviteRecord?.setObject(last, forKey: MNGCloudInvitesRecord.FamilyNameColumn)
}
if let newUserId = inviteInfo[MNGCloudInvitesRecord.NewUserIdReferenceColumn] as? String {
let _tmp = CKRecordID(recordName: newUserId) //record id for newly registered user
let ckRef = CKReference(recordID: _tmp, action: .None)
inviteRecord?.setObject(ckRef, forKey: MNGCloudInvitesRecord.NewUserIdReferenceColumn)
}
if let phone = inviteInfo[MNGCloudInvitesRecord.PhoneColumn] as? String {
inviteRecord?.setObject(phone, forKey: MNGCloudInvitesRecord.PhoneColumn)
}
if let status = inviteInfo[MNGCloudInvitesRecord.StatusColumn] as? String {
inviteRecord?.setObject(status, forKey: MNGCloudInvitesRecord.StatusColumn)
}
}
}
func insertRegistrationRecord(regInfo:NSDictionary){
//Configure User Reference
// if let currentCKUserID:CKRecordID? = CKRecordID(recordName: MNGAUSManager.sharedInstance.cloudUserId()) {
// if let currentCKUserReference:CKReference? = CKReference(recordID: currentCKUserID!, action: CKReferenceAction.DeleteSelf) {
//Configure Record
if let registrationRecord:CKRecord? = CKRecord(recordType: MNGCloudUserRegisterationRecord.RecordName) {
//registrationRecord!.setObject(currentCKUserReference, forKey: MNGCloudUserRegisterationRecord.UserIDReferenceColumn)
if let email = regInfo[MNGCloudUserRegisterationRecord.EmailColumn] as? String{
registrationRecord?.setObject(email, forKey: MNGCloudUserRegisterationRecord.EmailColumn)
}
if let given = regInfo[MNGCloudUserRegisterationRecord.GivenNameColumn] as? String {
registrationRecord?.setObject(given, forKey: MNGCloudUserRegisterationRecord.GivenNameColumn)
}
if let family = regInfo[MNGCloudUserRegisterationRecord.FamilyNameColumn] as? String {
registrationRecord?.setObject(family, forKey: MNGCloudUserRegisterationRecord.FamilyNameColumn)
}
if let phone = regInfo[MNGCloudUserRegisterationRecord.PhoneColumn] as? String {
registrationRecord?.setObject(phone, forKey: MNGCloudUserRegisterationRecord.PhoneColumn)
}
// if let appId = dictionary[MNGCloudUserRegisterationRecord.AppUserIDColumn] as? String {
// registrationRecord!.setObject(appId, forKey: MNGCloudUserRegisterationRecord.AppUserIDColumn)
// }
if let dateExpires = regInfo[MNGCloudUserRegisterationRecord.DateExpiresColumn] as? NSDate {
registrationRecord?.setObject(dateExpires, forKey: MNGCloudUserRegisterationRecord.DateExpiresColumn)
}
if let code = regInfo[MNGCloudUserRegisterationRecord.SecretColumn] as? String {
registrationRecord?.setObject(code, forKey: MNGCloudUserRegisterationRecord.SecretColumn)
}
//Set active status
if let status = regInfo[MNGCloudUserRegisterationRecord.StatusColumn] as? String {
registrationRecord?.setObject(status, forKey: MNGCloudUserRegisterationRecord.StatusColumn)
}
self.publicDatabase?.saveRecord(registrationRecord!, completionHandler: { (record, error) -> Void in
if error != nil {
//print(error!.localizedDescription)
NSOperationQueue.mainQueue().addOperationWithBlock ({ Void in
self.delegate?.cloudManagerDidFailToSaveUserRegistrationInfo!(error!)
})
return
}
//print("Saved Registration Record:\(record!.recordID.recordName)")
NSOperationQueue.mainQueue().addOperationWithBlock ({ Void in
//print( self.delegate )
self.delegate?.cloudManagerDidSaveUserRegistrationInfo!(registrationRecord!.recordID.recordName)
})
})
}
// }
// }
}
func modifyRegistrationRecord(dictionary:NSDictionary, usingRecordID recordID: String){
}
//MARK: Cloud Fetch Methods
func fetchRecordWithID (recordID:String, completionHandler:(record:CKRecord)->()) {
let current = CKRecordID(recordName: recordID)
self.publicDatabase?.fetchRecordWithID(current, completionHandler: {(record, error) -> Void in
if (( error ) != nil) {
print(error!.localizedDescription)
} else {
dispatch_async (dispatch_get_main_queue(), { () -> Void in
//post notification with recordInfo
//completionHandler(record);
})
}
})
}
func fetchRecordsWithType (recordType:String, completionHandler:(records:[CKRecord]) ->() ) {
//let containsPredicate = NSPredicate(format: "%K CONTAINS %@", argumentArray: [MNGCloudSharedStories.StorySharedToColumn, "*"])
let truePredicate = NSPredicate(value: true)
let query = CKQuery(recordType: recordType, predicate: truePredicate) //test containsPredicate
let queryOperation = CKQueryOperation (query: query)
//columns to retrieve
queryOperation.desiredKeys = [MNGCloudSharedStoriesRecord.StoryAssetColumn]
var results = [CKRecord]()
// Add results to the results array as they come back.
queryOperation.recordFetchedBlock = { (record:CKRecord) -> Void in
results.append(record)
}
// The query completion block will be called after all records are fetched.
queryOperation.queryCompletionBlock = { (cursor,error) in
if (( error ) != nil) {
print(error!.localizedDescription)
} else {
dispatch_async (dispatch_get_main_queue(), { () in
//post notification with recordInfo
completionHandler(records: results);
})
}
}
// Add the operation to the database. The operation will be executed immediately.
self.publicDatabase?.addOperation(queryOperation)
}
func fetchPrivateShareRecordsWithType (recordType:String, completionHandler:(records:[CKRecord]) ->() ) {
//TODO: Wrap UserID as a CKReference
let containsPredicate = NSPredicate(format: "%K CONTAINS %@", argumentArray: [MNGCloudSharedStoriesRecord.StorySharedToListReferenceColumn, defaultUserID])
let query = CKQuery(recordType: recordType, predicate: containsPredicate)
let queryOperation = CKQueryOperation (query: query)
//columns to retrieve
queryOperation.desiredKeys = [MNGCloudSharedStoriesRecord.StoryAssetColumn]
var results = [CKRecord]()
// Add results to the results array as they come back.
queryOperation.recordFetchedBlock = { (record:CKRecord) -> Void in
results.append(record)
}
// The query completion block will be called after all records are fetched.
queryOperation.queryCompletionBlock = { (cursor,error) in
if (( error ) != nil) {
print(error!.localizedDescription)
} else {
dispatch_async (dispatch_get_main_queue(), { () in
//post notification with recordInfo
completionHandler(records: results);
})
}
}
// Add the operation to the database. The operation will be executed immediately.
self.publicDatabase?.addOperation(queryOperation)
}
//MARK: Cloud Subscription Methods
private var uRecordID:CKRecordID? = nil
lazy var currentUserRecordID:CKRecordID? = {
if self.uRecordID != nil {
return self.uRecordID!
}
let operation = CKFetchRecordsOperation.fetchCurrentUserRecordOperation()
operation.fetchRecordsCompletionBlock = { (records:[CKRecordID: CKRecord]?, error:NSError?) -> Void in
// Code never reached
if ((error) != nil) {
print(error!.localizedDescription)
} else {
debugPrint("fetchRecordsCompletionBlock")
}
for (userRecordID, userRecord) in records! {
self.uRecordID = userRecordID
}
}
self.publicDatabase?.addOperation(operation)
return nil
}()
func subscribe () {
if self.isSubscribed == false {
let containsPredicate = NSPredicate(format: "%K CONTAINS %@", argumentArray: [MNGCloudSharedStoriesRecord.StorySharedToListReferenceColumn, defaultUserID])
let userSubscription = CKSubscription(recordType: MNGCloudSharedStoriesRecord.RecordName, predicate: containsPredicate, options: [CKSubscriptionOptions.FiresOnRecordCreation,CKSubscriptionOptions.FiresOnRecordUpdate, CKSubscriptionOptions.FiresOnRecordUpdate] )
let notification = CKNotificationInfo()
notification.alertBody = "RecordsChanged"
userSubscription.notificationInfo = notification
self.publicDatabase?.saveSubscription(userSubscription, completionHandler: { (subscription, error) -> Void in
if (( error ) != nil) {
print(error!.localizedDescription)
} else {
//dispatch_async (dispatch_get_main_queue(), { () -> Void in
//post notification with recordInfo
//completionHandler(record);
NSUserDefaults.standardUserDefaults().setBool(true, forKey: Constants.CloudUserSubscribed)
NSUserDefaults.standardUserDefaults().setObject(userSubscription.subscriptionID, forKey: Constants.CloudUserSubscriptionID)
//})
}})
}
}
func unsubscribe () {
if self.isSubscribed == true {
let subscriptionID:String = (NSUserDefaults.standardUserDefaults().objectForKey(Constants.CloudUserSubscriptionID) as? String)!
// Create an operation to modify the subscription with the subscriptionID.
let modifyOperation = CKModifySubscriptionsOperation()
modifyOperation.subscriptionIDsToDelete = [subscriptionID]
modifyOperation.modifySubscriptionsCompletionBlock = {
(savedSubcriptions, deletedSubscriptions, error) in
if (( error ) != nil) {
print(error!.localizedDescription)
} else {
NSUserDefaults.standardUserDefaults().removeObjectForKey(Constants.CloudUserSubscriptionID)
}
}
// Add the operation to the database. The operation will be executed immediately.
self.publicDatabase?.addOperation(modifyOperation)
}
}
//MARK: Cloud Manager Event Methods
override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
//
if keyPath == NSUbiquityIdentityDidChangeNotification {
print("iCloud Account Status Change", object, change, context)
}
}
func registerEventObservations () {
defaultCenter.addObserver(self, selector: Constants.SelectorCloudEventObserved, name: NSUbiquityIdentityDidChangeNotification, object: nil)
}
func unregisterEventObservations () {
defaultCenter.removeObserver(self, name: NSUbiquityIdentityDidChangeNotification, object: nil)
}
func cloudEventObserved(notification:NSNotification) {
print(notification)
//NSUbiquityIdentityDidChangeNotification
// NSURLRelationship
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment