void Run()
    {
        //var testDisposable = new TestDisposable();

        //Debug.Log("made dispasable: " + testDisposable);

        //StartCoroutine(WaitABit());
        var op = new CKModifyRecordsOperation(null, new CKRecordID[] {
            new CKRecordID("1CB545B1-7CA3-423E-A215-67DA56578270"),
            new CKRecordID("321A8AD3-0FA9-40C3-8D76-D76328A0A7F1")
        });

        database = CKContainer.DefaultContainer().PrivateCloudDatabase;

        Debug.Log("Setting callback");
        op.ModifyRecordsCompletionBlock = (records, recordIds, error) =>
        {
            Debug.Log("Modify records done");
        };

        //Debug.Log("Setting QoS");
        op.Configuration.QualityOfService = NSQualityOfService.Default;

        database.AddOperation(op);

        StartCoroutine(WaitABit());
    }
    private void OnQueryComplete(CKRecord[] records, NSError error)
    {
        Debug.Log("OnQueryComplete");

        if (error != null)
        {
            Debug.LogError(error.LocalizedDescription);
        }
        else
        {
            var result = records.FirstOrDefault();
            if (result != null)
            {
                Debug.Log(string.Format("found record: '{0}' with name: '{1}'",
                                        result.RecordID.RecordName, result.StringForKey("name")));
            }

            // Let's be tidy. Delete all the records we created
            // create an array of record id's from the records we saved
            var recordIds = recordsToSearch.Select(record => record.RecordID).ToArray();

            Debug.Log("Cleaning up, deleting the records we created....");
            var op = new CKModifyRecordsOperation(null, recordIds);

            op.ModifyRecordsCompletionBlock   = OnRecordsDeleted;
            op.Configuration.QualityOfService = NSQualityOfService.UserInitiated;

            database.AddOperation(op);
        }
    }
Пример #3
0
    private void Run()
    {
        Debug.Log("Example 6 - Per Record Progress");

        database = CKContainer.DefaultContainer().PrivateCloudDatabase;

        // Let's create 5 files at 1MB a piece
        // So we have enough data to see some upload progress

        // BTW CloudKit recommends that if your data exceeds 1MB you should put
        // it inside a CKAsset

        for (int i = 0; i < numFiles; i++)
        {
            var    record = new CKRecord("BigFile");
            byte[] bytes  = new byte[1000000];
            record.SetBuffer(bytes, "bytes");

            records[i] = record;
        }

        var op = new CKModifyRecordsOperation(records, null);

        op.Configuration.QualityOfService = NSQualityOfService.UserInitiated;

        op.PerRecordProgressBlock       = OnPerRecordProgress;
        op.PerRecordCompletionBlock     = OnPerRecordComplete;
        op.ModifyRecordsCompletionBlock = OnRecordsSaved;

        database.AddOperation(op);
    }
Пример #4
0
    private void OnQuery(CKRecord[] records, NSError error)
    {
        Debug.Log("query finished");

        if (error != null)
        {
            Debug.LogError(error.LocalizedDescription);
            return;
        }

        Debug.Log($"got {records.Length} records");
        DebugLogRecords(records);

        Debug.Log("cleaning up...deleting records");
        var deleteOp = new CKModifyRecordsOperation(null, records.Select(r => r.RecordID).ToArray());

        deleteOp.Configuration.QualityOfService = NSQualityOfService.UserInitiated;
        deleteOp.ModifyRecordsCompletionBlock   = (ckRecords, ids, arg3) =>
        {
            if (error != null)
            {
                Debug.LogError(error.LocalizedDescription);
            }
            else
            {
                Debug.Log("records deleted, you can exit the sample");
            }
        };
        database.AddOperation(deleteOp);
    }
 public void Can_access_group()
 {
     Assert.DoesNotThrow(() => {
         var op    = new CKModifyRecordsOperation();
         var group = op.Group;
     });
 }
 public void OperationIDTest()
 {
     Assert.DoesNotThrow(() => {
         var op = new CKModifyRecordsOperation();
         var id = op.OperationID;
     });
 }
    private void Run()
    {
        Debug.Log("Example 3 - Querying");
        database = CKContainer.DefaultContainer().PrivateCloudDatabase;

        // We need a bunch of records to search through
        names = new string[] {
            "Alice",
            "Bob",
            "Charles",
            "Danni",
            "Exavier"
        };

        // Make an array of CKRecords and set the name field to each of the
        // names in the array above...
        //
        recordsToSearch = names.Select(name => {
            var record = new CKRecord("Person");
            record.SetString(name, "name");
            return(record);
        }).ToArray();

        // CloudKit uses a CKModifyRecrodsOperation for both saving and deleting
        // (which is sorta wierd). The first parameter is records to save, the
        // second is record id's to delete
        //
        Debug.Log("Creating records");
        CKModifyRecordsOperation op = new CKModifyRecordsOperation(
            recordsToSearch,
            null
            );

        // Important to set quality of service to UserInitiated or cloudkit
        // may run your query a LONG time from now. Like minutes from now
        // (seriously). The default value of NSQualityOfServiceUtility is insane
        // You can read more about QoS here:
        // https://developer.apple.com/library/archive/documentation/Performance/Conceptual/EnergyGuide-iOS/PrioritizeWorkWithQoS.html
        op.Configuration.QualityOfService = NSQualityOfService.UserInitiated;

        // The modify records completion block is a callback function that's
        // invoked when the operation is complete
        op.ModifyRecordsCompletionBlock = OnRecordsSaved;

        database.AddOperation(op);

        var op2 = new CKFetchRecordsOperation(recordsToSearch.Select(x => x.RecordID).ToArray());

        op2.FetchRecordsCompletionHandler = (dictionary, error) =>
        {
            Debug.Log("Fetch records complete");
            //foreach (var kvp in dictionary)
            //{
            //    Debug.Log(string.Format("key:{0} value:{1}", kvp.Key.RecordName, kvp.Value));
            //}
        };
        database.AddOperation(op2);
    }
Пример #8
0
    private void DeleteRecords()
    {
        Debug.Log("Cleaning Up");
        var op = new CKModifyRecordsOperation(null, records.Select(r => r.RecordID).ToArray());

        op.Configuration.QualityOfService = NSQualityOfService.UserInitiated;
        op.ModifyRecordsCompletionBlock   = OnRecordsDeleted;
        database.AddOperation(op);
    }
    public void Adding_operation_sets_datbase_property_on_operation()
    {
        var op       = new CKModifyRecordsOperation();
        var database = CKContainer.DefaultContainer().PrivateCloudDatabase;

        database.AddOperation(op);

        Assert.AreEqual(op.Database, database);
    }
    public void Can_add_operation()
    {
        var op       = new CKModifyRecordsOperation();
        var database = CKContainer.DefaultContainer().PrivateCloudDatabase;

        TestDelegate sut = () => database.AddOperation(op);

        Assert.DoesNotThrow(sut);
    }
    public void Can_set_and_get_save_policy(
        [Values(CKRecordSavePolicy.SaveAllKeys, CKRecordSavePolicy.SaveChangedKeys, CKRecordSavePolicy.SaveIfServerRecordUnchanged)]
        CKRecordSavePolicy savePolicy
        )
    {
        var op = new CKModifyRecordsOperation();

        op.SavePolicy = savePolicy;

        Assert.AreEqual(op.SavePolicy, savePolicy);
    }
Пример #12
0
 public void Default()
 {
     // watchOS does not allow `init` so we need to ensure that our default .ctor
     // match the existing `init*` with null values (so we can remove it)
     using (var mro = new CKModifyRecordsOperation()) {
         Assert.That(op.Atomic, Is.EqualTo(mro.Atomic), "Atomic");
         Assert.That(op.RecordsToSave, Is.EqualTo(mro.RecordsToSave), "RecordsToSave");
         Assert.That(op.RecordIdsToDelete, Is.EqualTo(mro.RecordIdsToDelete), "RecordIdsToDelete");
         Assert.That(op.SavePolicy, Is.EqualTo(mro.SavePolicy), "SavePolicy");
         Assert.That(op.ClientChangeTokenData, Is.EqualTo(mro.ClientChangeTokenData), "ClientChangeTokenData");
         Assert.That(op.PerRecordProgress, Is.EqualTo(mro.PerRecordProgress), "PerRecordProgress");
         Assert.That(op.PerRecordCompletion, Is.EqualTo(mro.PerRecordCompletion), "PerRecordCompletion");
         Assert.That(op.Completed, Is.EqualTo(mro.Completed), "Completed");
     }
 }
Пример #13
0
    private void OnRecordZoneCreated(CKRecordZone zone, NSError error)
    {
        Debug.Log(string.Format("Created record zone with name {0}", zone.ZoneID.ZoneName));

        // records you want to save to a custom zone are initialized with the zoneId
        var save1 = new CKRecord("SaveGame", customZone.ZoneID);

        // or if you need a custom record name, initialize with a recordID with the zoneId
        var save2 = new CKRecord("SaveGame", new CKRecordID("MySave", customZone.ZoneID));

        var op = new CKModifyRecordsOperation(new CKRecord[] { save1, save2 }, null);

        op.Configuration.QualityOfService = NSQualityOfService.UserInitiated;
        op.ModifyRecordsCompletionBlock   = OnRecordsSaved;
        database.AddOperation(op);
    }
Пример #14
0
    // Start is called before the first frame update
    void Start()
    {
        Debug.Log("Example - NSSortDescriptor");

        Debug.Log("container is: " + CKContainer.DefaultContainer().ContainerIdentifier);

        database = CKContainer.DefaultContainer().PrivateCloudDatabase;

        var n = 10;

        Debug.Log($"making {n} records");
        var records = new CKRecord[n];

        for (var i = 0; i < records.Length; i++)
        {
            records[i] = new CKRecord(recordType);
        }

        // Make some records share the same field value
        // so we can test primary/secondary sorting
        for (var i = 1; i < n; i += 2)
        {
            var field = RandomString(8);
            records[i - 1].SetString(field, primaryFieldKey);
            records[i].SetString(field, primaryFieldKey);
        }

        for (var i = 0; i < n; i++)
        {
            var field = RandomString(4);
            Debug.Log(field);
            records[i].SetString(field, secondaryFieldKey);
        }

        Debug.Log("Saving records");
        var op = new CKModifyRecordsOperation(records, null);

        op.Configuration.QualityOfService = NSQualityOfService.UserInitiated;
        op.ModifyRecordsCompletionBlock   = OnRecordsSaved;
        database.AddOperation(op);
    }
Пример #15
0
 public void SetUp()
 {
     TestRuntime.AssertXcodeVersion(6, 0);
     op = new CKModifyRecordsOperation(null, null);
 }
 public void SetUp()
 {
     TestRuntime.AssertXcodeVersion(6, 0);
     TestRuntime.AssertSystemVersion(PlatformName.MacOSX, 10, 10, throwIfOtherPlatform: false);
     op = new CKModifyRecordsOperation(null, null);
 }
    public void Can_Create_CKModifyRecordsOperation_With_Records_To_Save_And_RecordsIds_To_Delete()
    {
        var sut = new CKModifyRecordsOperation(new CKRecord[] { }, new CKRecordID[] { });

        Assert.IsNotNull(sut);
    }
    public void Can_create_CKModifyRecordsOperation()
    {
        var sut = new CKModifyRecordsOperation();

        Assert.IsNotNull(sut);
    }
    public void Configuration_Exists()
    {
        var op = new CKModifyRecordsOperation();

        Assert.IsNotNull(op);
    }
Пример #20
0
        void PublishPost(NSObject sender)
        {
            // Prevents multiple posting, locks as soon as a post is made
            PostButton.Enabled = false;
            UIActivityIndicatorView indicator = new UIActivityIndicatorView(UIActivityIndicatorViewStyle.Gray);

            indicator.StartAnimating();
            PostButton.CustomView = indicator;

            // Hides the keyboards and dispatches a UI update to show the upload progress
            HiddenText.EndEditing(true);
            TagField.EndEditing(true);
            ProgressBar.Hidden = false;

            // Creates post record type and initizalizes all of its values
            CKRecord newRecord = new CKRecord(Post.RecordType);

            newRecord [Post.FontKey]     = (NSString)ImageLabel.Font.Name;
            newRecord [Post.ImageRefKey] = new CKReference(ImageRecord.Record.Id, CKReferenceAction.DeleteSelf);
            newRecord [Post.TextKey]     = (NSString)HiddenText.Text;
            string[] tags = TagField.Text.ToLower().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
            newRecord [Post.TagsKey] = NSArray.FromObjects(tags);

            Post newPost = new Post(newRecord);

            newPost.ImageRecord = ImageRecord;

            // Only upload image record if it is not on server, otherwise just upload the new post record
            CKRecord[] recordsToSave = ImageRecord.IsOnServer
                                ? new CKRecord[] { newRecord }
                                : new CKRecord[] { newRecord, ImageRecord.Record };
            // TODO: https://trello.com/c/A9T8Spyp second param is null
            CKModifyRecordsOperation saveOp = new CKModifyRecordsOperation(recordsToSave, new CKRecordID[0]);

            saveOp.PerRecordProgress = (CKRecord record, double progress) => {
                // Image record type is probably going to take the longest to upload. Reflect it's progress in the progress bar
                if (record.RecordType == Image.RecordType)
                {
                    InvokeOnMainThread(() => {
                        var val = (float)(progress * 0.95);
                        ProgressBar.SetProgress(val, true);
                    });
                }
            };

            // When completed it notifies the tableView to add the post we just uploaded, displays error if it didn't work
            saveOp.Completed = (CKRecord[] savedRecords, CKRecordID[] deletedRecordIDs, NSError operationError) => {
                Error errorResponse = HandleError(operationError);
                switch (errorResponse)
                {
                case Error.Success:
                    // Tells delegate to update so it can display our new post
                    InvokeOnMainThread(() => {
                        DismissViewController(true, null);
                        MainController.Submit(newPost);
                    });
                    break;

                case Error.Retry:
                    CKErrorInfo errorInfo  = new CKErrorInfo(operationError.UserInfo);
                    nint        retryAfter = errorInfo.RetryAfter.HasValue ? errorInfo.RetryAfter.Value : 3;
                    Console.WriteLine("Error: {0}. Recoverable, retry after {1} seconds", operationError.Description, retryAfter);
                    Task.Delay((int)retryAfter * 1000).ContinueWith(_ => PublishPost(sender));
                    break;

                case Error.Ignore:
                    Console.WriteLine("Error saving record: {0}", operationError.Description);

                    string errorTitle    = "Error";
                    string dismissButton = "Okay";
                    string errorMessage  = operationError.Code == (long)CKErrorCode.NotAuthenticated
                                                        ? "You must be logged in to iCloud in order to post"
                                                        : "Unrecoverable error with the upload, check console logs";

                    InvokeOnMainThread(() => {
                        UIAlertController alert = UIAlertController.Create(errorTitle, errorMessage, UIAlertControllerStyle.Alert);
                        alert.AddAction(UIAlertAction.Create(dismissButton, UIAlertActionStyle.Cancel, null));

                        PostButton.Enabled = true;
                        PresentViewController(alert, true, null);
                        ProgressBar.Hidden    = true;
                        PostButton.CustomView = null;
                    });
                    break;

                default:
                    throw new NotImplementedException();
                }
            };
            CKContainer.DefaultContainer.PublicCloudDatabase.AddOperation(saveOp);
        }
		void PublishPost (NSObject sender)
		{
			// Prevents multiple posting, locks as soon as a post is made
			PostButton.Enabled = false;
			UIActivityIndicatorView indicator = new UIActivityIndicatorView (UIActivityIndicatorViewStyle.Gray);
			indicator.StartAnimating ();
			PostButton.CustomView = indicator;

			// Hides the keyboards and dispatches a UI update to show the upload progress
			HiddenText.EndEditing (true);
			TagField.EndEditing (true);
			ProgressBar.Hidden = false;

			// Creates post record type and initizalizes all of its values
			CKRecord newRecord = new CKRecord (Post.RecordType);
			newRecord [Post.FontKey] = (NSString)ImageLabel.Font.Name;
			newRecord [Post.ImageRefKey] = new CKReference (ImageRecord.Record.Id, CKReferenceAction.DeleteSelf);
			newRecord [Post.TextKey] = (NSString)HiddenText.Text;
			string[] tags = TagField.Text.ToLower ().Split (new char[]{ ' ' }, StringSplitOptions.RemoveEmptyEntries);
			newRecord [Post.TagsKey] = NSArray.FromObjects (tags);

			Post newPost = new Post (newRecord);
			newPost.ImageRecord = ImageRecord;

			// Only upload image record if it is not on server, otherwise just upload the new post record
			CKRecord[] recordsToSave = ImageRecord.IsOnServer
				? new CKRecord[] { newRecord }
				: new CKRecord[] { newRecord, ImageRecord.Record };
			// TODO: https://trello.com/c/A9T8Spyp second param is null
			CKModifyRecordsOperation saveOp = new CKModifyRecordsOperation (recordsToSave, new CKRecordID[0]);
			saveOp.PerRecordProgress = (CKRecord record, double progress) => {
				// Image record type is probably going to take the longest to upload. Reflect it's progress in the progress bar
				if (record.RecordType == Image.RecordType)
					InvokeOnMainThread (() => {
						var val = (float)(progress * 0.95);
						ProgressBar.SetProgress (val, true);
					});
			};

			// When completed it notifies the tableView to add the post we just uploaded, displays error if it didn't work
			saveOp.Completed = (CKRecord[] savedRecords, CKRecordID[] deletedRecordIDs, NSError operationError) => {
				Error errorResponse = HandleError (operationError);
				switch (errorResponse) {
					case Error.Success:
						// Tells delegate to update so it can display our new post
						InvokeOnMainThread (() => {
							DismissViewController (true, null);
							MainController.Submit (newPost);
						});
						break;

					case Error.Retry:
						CKErrorInfo errorInfo = new CKErrorInfo (operationError.UserInfo);
						nint retryAfter = errorInfo.RetryAfter.HasValue ? errorInfo.RetryAfter.Value : 3;
						Console.WriteLine ("Error: {0}. Recoverable, retry after {1} seconds", operationError.Description, retryAfter);
						Task.Delay ((int)retryAfter * 1000).ContinueWith (_ => PublishPost (sender));
						break;

					case Error.Ignore:
						Console.WriteLine ("Error saving record: {0}", operationError.Description);

						string errorTitle = "Error";
						string dismissButton = "Okay";
						string errorMessage = operationError.Code == (long)CKErrorCode.NotAuthenticated
							? "You must be logged in to iCloud in order to post"
							: "Unrecoverable error with the upload, check console logs";

						InvokeOnMainThread (() => {
							UIAlertController alert = UIAlertController.Create (errorTitle, errorMessage, UIAlertControllerStyle.Alert);
							alert.AddAction (UIAlertAction.Create (dismissButton, UIAlertActionStyle.Cancel, null));

							PostButton.Enabled = true;
							PresentViewController (alert, true, null);
							ProgressBar.Hidden = true;
							PostButton.CustomView = null;
						});
						break;

					default:
						throw new NotImplementedException ();
				}
			};
			CKContainer.DefaultContainer.PublicCloudDatabase.AddOperation (saveOp);
		}