private void OnRecordFetched(CKRecord record, NSError error) { if (error != null) { Debug.LogError(error.LocalizedDescription); } else { Debug.Log(string.Format("Record fetched")); // CKRecords have a bunch of useful metadata Debug.Log("CreationDate: " + record.CreationDate); Debug.Log("ModificationDate: " + record.ModificationDate); // The record change tag is an id that helps you keep track of the // most up to date version Debug.Log("RecordChangeTag: " + record.RecordChangeTag); // The parent of this record (if any). Parent child relationships // can be created using SetRefereneceForKey Debug.Log("Parent: " + record.Parent); Debug.Log("Type: " + record.RecordType); Debug.Log("Share: " + record.Share); // The user id of the account to create/modify this record // in a private DB I think this is just always the current user Debug.Log("CreatorUserRecordID: " + record.CreatorUserRecordID); Debug.Log("Last Modified User Record Id: " + record.LastModifiedUserRecordID); ModifyRecord(); } }
void Init(CKRecord record, bool onServer) { IsOnServer = onServer; Record = record; Thumbnail = LoadImage(ThumbnailKey); FullImage = LoadImage(FullsizeKey); }
public void Cant_create_CKShare_with_no_record() { CKRecord record = null; TestDelegate sut = () => new CKShare(record); Assert.Throws <CloudKitException>(sut); }
async void SaveSearchRequest(string searchRequestValue) { var newRecord = new CKRecord("SearchRequest"); newRecord ["value"] = (NSString)searchRequestValue; await cloudManager.SaveAsync(newRecord); }
void Init (CKRecord record, bool onServer) { IsOnServer = onServer; Record = record; Thumbnail = LoadImage (ThumbnailKey); FullImage = LoadImage (FullsizeKey); }
public void Can_create_CKShare() { var record = new CKRecord("root_record_type"); var share = new CKShare(record); Assert.AreEqual(share.RecordID, record.RecordID); }
partial void TakePhoto(NSObject sender) { var imagePicker = new UIImagePickerController(); var sourceType = UIImagePickerControllerSourceType.PhotoLibrary; if (UIImagePickerController.IsSourceTypeAvailable(UIImagePickerControllerSourceType.Camera)) { sourceType = UIImagePickerControllerSourceType.Camera; } imagePicker.SourceType = sourceType; imagePicker.FinishedPickingMedia += async(picker, e) => { var spinner = ActivityIndicator; spinner.Hidden = false; imagePicker.View.AddSubview(spinner); spinner.StartAnimating(); UIImage image = e.Info [UIImagePickerController.OriginalImage] as UIImage; var newSize = new SizeF(512, 512); if (image.Size.Width > image.Size.Height) { newSize.Height = (int)(newSize.Width * image.Size.Height / image.Size.Width); } else { newSize.Width = (int)(newSize.Height * image.Size.Width / image.Size.Height); } UIGraphics.BeginImageContext(newSize); image.Draw(new RectangleF(0, 0, newSize.Width, newSize.Height)); var data = UIGraphics.GetImageFromCurrentImageContext().AsJPEG(0.75f); UIGraphics.EndImageContext(); NSError error; var cachesDirectory = NSFileManager.DefaultManager.GetUrl(NSSearchPathDirectory.CachesDirectory, NSSearchPathDomain.User, null, true, out error); var temporaryName = new NSUuid().AsString() + "jpeg"; var localUrl = cachesDirectory.Append(temporaryName, false); data.Save(localUrl, true, out error); CKRecord record = await CloudManager.UploadAssetAsync(localUrl); if (record == null) { return; } spinner.RemoveFromSuperview(); assetRecordName = record.RecordId.RecordName; var alert = new UIAlertView("CloudKitAtlas", "Successfully Uploaded", null, "OK", null); alert.Show(); DismissViewController(true, null); }; imagePicker.Canceled += (picker, e) => DismissViewController(true, null); PresentViewController(imagePicker, true, null); }
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); }
void Run() { Debug.Log("Example 4 - CKAsset"); database = CKContainer.DefaultContainer().PrivateCloudDatabase; var record = new CKRecord("MyType"); // CloudKit recommends if your data is larger than 1MB that you store // it as an asset... // our example won't be anything close to 1MB, but it'll illustrate the // technique #if UNITY_TVOS string path = Path.Combine(Application.temporaryCachePath, "Asset.bytes"); #else string path = Path.Combine(Application.persistentDataPath, "Asset.bytes"); #endif byte[] bytes = Encoding.ASCII.GetBytes("AssetData"); File.WriteAllBytes(path, bytes); // Assets have to be files, so you pass it the filepath to something // in the user's data directory // the asset will be stored in cloudkit, with a URL for retrieval var fileurl = NSURL.FileURLWithPath(path); record.SetAsset(new CKAsset(fileurl), "MyAsset"); database.SaveRecord(record, OnRecordSaved); }
// Creates an Image from a UIImage (photo was taken from camera or photo library) public Image(UIImage image) { if (image == null) { throw new ArgumentNullException("image"); } CGImage rawImage = image.CGImage; using (CGImage cropped = Crop(rawImage)) { // Resizes image to be 1500 x 1500 px and saves it to a temporary file UIImage fullImage = Resize(cropped, image.CurrentScale, image.Orientation, new CGSize(1500, 1500)); var fullUrl = SaveToTmp(fullImage, "toUploadFull.tmp"); // Resizes thumbnail to be 200 x 200 px and then saves to different temp file UIImage thumbImage = Resize(cropped, image.CurrentScale, image.Orientation, new CGSize(200, 200)); var thumbURL = SaveToTmp(thumbImage, "toUploadThumb.tmp"); // Creates Image record type with two assets, full sized image and thumbnail sized image CKRecord newImageRecord = new CKRecord(RecordType); newImageRecord [FullsizeKey] = new CKAsset(fullUrl); newImageRecord [ThumbnailKey] = new CKAsset(thumbURL); // Calls designated initalizer, this is a new image so it is not on the server Init(newImageRecord, false); } }
Results ProcessResult (CKRecord record) { var results = new Results (); if (record != null) results.Items.Add (new CKRecordWrapper (record)); return results; }
public async Task DeleteAsync (CKRecord record) { try { await privateDatabase.DeleteRecordAsync (record.Id); } catch (Exception e) { Console.WriteLine ("An error occured: {0}", e.Message); } }
public async Task<CKRecord> UploadAssetAsync (NSUrl assetUrl) { var assetRecord = new CKRecord (PhotoAssetRecordType); var photo = new CKAsset (assetUrl); assetRecord [PhotoAssetField] = photo; return await publicDatabase.SaveRecordAsync (assetRecord); }
public void Can_create_record_of_a_type() { var recordType = "record_type"; var record = new CKRecord(recordType); Assert.AreEqual(record.RecordType, recordType); }
public async Task DeleteAsync(CKRecord record) { try { await privateDatabase.DeleteRecordAsync(record.Id); } catch (Exception e) { Console.WriteLine("An error occured: {0}", e.Message); } }
public void RecordName_is_automatically_generated_if_not_set() { var recordType = "record_type"; var record = new CKRecord(recordType); Assert.IsFalse(string.IsNullOrEmpty(record.RecordID.RecordName)); }
public void Record_added_to_share_has_share() { var rootRecord = new CKRecord("root_record_type"); var share = new CKShare(rootRecord); Assert.AreEqual(rootRecord.Share, share); }
public async Task<CKRecord> AddRecordAsync (string name, CLLocation location) { var newRecord = new CKRecord (ItemRecordType); newRecord [NameField] = (NSString)name; newRecord [LocationField] = location; return await publicDatabase.SaveRecordAsync (newRecord); }
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath) { var cell = TableView.DequeueReusableCell(new NSString("cell"), indexPath); CKRecord record = records[indexPath.Row]; cell.TextLabel.Text = (NSString)record["name"]; return(cell); }
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); }
public void Can_set_parent_reference_on_record_using_the_record() { var parent = new CKRecord("parent_record_type"); var child = new CKRecord("child_record_type"); child.SetParentReferenceFromRecord(parent); Assert.AreEqual(child.Parent.RecordID, parent.RecordID); }
public void AddImageFromRecord(CKRecord toAdd) { Image fetchedImage = new Image (toAdd); // Ensures that only one object will be added to the imageRecords array at a time updateArrayQueue.DispatchAsync (() => { imageRecords.Add (fetchedImage); InvokeOnMainThread (ReloadData); }); }
public void Cant_create_CKShare_with_null_share_id() { CKRecordID shareId = null; var rootRecord = new CKRecord("rootRecord"); TestDelegate sut = () => new CKShare(rootRecord, shareId); Assert.Throws <CloudKitException>(sut); }
public void Cant_encode_system_fields_without_coder() { NSCoder coder = null; var record = new CKRecord("record_type"); TestDelegate sut = () => record.EncodeSystemFieldsWithCoder(coder); Assert.Throws <CloudKitException>(sut); }
public async Task <CKRecord> UploadAssetAsync(NSUrl assetUrl) { var assetRecord = new CKRecord(PhotoAssetRecordType); var photo = new CKAsset(assetUrl); assetRecord [PhotoAssetField] = photo; return(await publicDatabase.SaveRecordAsync(assetRecord)); }
public async Task <CKRecord> AddRecordAsync(string name, CLLocation location) { var newRecord = new CKRecord(ItemRecordType); newRecord [NameField] = (NSString)name; newRecord [LocationField] = location; return(await publicDatabase.SaveRecordAsync(newRecord)); }
public void MarkRecordAsModified(CKRecord record) { var index = IndexOfRecordByRecordID(record.Id); if (index >= 0) { Results.Modified.Add(index); } }
public void Can_create_CKShare_with_root_record_and_share_id() { var shareId = new CKRecordID("shareId"); var rootRecord = new CKRecord("root_record_type"); var share = new CKShare(rootRecord, shareId); Assert.AreEqual(share.RecordID, shareId); }
// Creates an Image from a CKRecord that has been fetched public Image(CKRecord record, bool onServer = true) { if (record == null) throw new ArgumentNullException ("record"); if (record.RecordType != RecordType) throw new ArgumentException ("Wrong type for image record"); Init (record, onServer); }
public void Can_create_record_of_a_type_in_a_zone() { var recordType = "record_type"; var zoneName = "zone_name"; var recordZone = new CKRecordZone(zoneName); var record = new CKRecord(recordType, recordZone.ZoneID); Assert.AreEqual(record.RecordID.ZoneID, recordZone.ZoneID); }
private void OnRecordSaved(CKRecord record, NSError error) { Debug.Log("OnRecordSaved"); if (error != null) { Debug.LogError("Could not save record: " + error.LocalizedDescription); } database.FetchRecordWithID(record.RecordID, OnRecordFetched); }
public void Can_set_and_retrieve_asset_by_key() { var record = new CKRecord("record_type"); var asset = new CKAsset(NSURL.URLWithString("file:///someasset.bytes")); var assetKey = "asset_key"; record.SetAsset(asset, assetKey); Assert.AreEqual(record.AssetForKey(assetKey), asset); }
public void Can_set_and_retrieve_reference_by_key() { var record = new CKRecord("record_type"); var reference = new CKReference(new CKRecord("record_type"), CKReferenceAction.DeleteSelf); var referenceKey = "reference_key"; record.SetReference(reference, referenceKey); Assert.AreEqual(record.ReferenceForKey(referenceKey), reference); }
public void Can_set_parent_reference_on_record() { var parent = new CKRecord("parent_record_type"); var child = new CKRecord("child_record_type"); var parentReference = new CKReference(parent, CKReferenceAction.None); child.Parent = parentReference; Assert.AreEqual(child.Parent.RecordID, parent.RecordID); }
public async Task SaveAsync(CKRecord record) { try { await publicDatabase.SaveRecordAsync(record); Console.WriteLine("Successfuly saved record!"); } catch (Exception e) { Console.WriteLine("An error occured: {0}", e.Message); } }
public void Cant_create_record_with_an_invalid_type( [Values(null, "", "type with spaces", "_underscore", "2number")] string recordType) { TestDelegate sut = () => { var record = new CKRecord(recordType); }; Assert.Throws <Exception>(sut); }
public void AddImageFromRecord(CKRecord toAdd) { Image fetchedImage = new Image(toAdd); // Ensures that only one object will be added to the imageRecords array at a time updateArrayQueue.DispatchAsync(() => { imageRecords.Add(fetchedImage); InvokeOnMainThread(ReloadData); }); }
async partial void Add (UIButton sender) { if (string.IsNullOrEmpty (nameTextField.Text)) nameTextField.ResignFirstResponder (); else { var newRecord = new CKRecord (ReferenceItemRecordName); newRecord ["name"] = (NSString)nameTextField.Text; await CloudManager.SaveAsync (newRecord); records.Insert (0, newRecord); var indexPath = NSIndexPath.FromRowSection (0, 0); TableView.InsertRows (new [] { indexPath }, UITableViewRowAnimation.Automatic); nameTextField.ResignFirstResponder (); nameTextField.Text = string.Empty; } }
// Creates an Image from a UIImage (photo was taken from camera or photo library) public Image (UIImage image) { if (image == null) throw new ArgumentNullException ("image"); CGImage rawImage = image.CGImage; using (CGImage cropped = Crop (rawImage)) { // Resizes image to be 1500 x 1500 px and saves it to a temporary file UIImage fullImage = Resize (cropped, image.CurrentScale, image.Orientation, new CGSize (1500, 1500)); var fullUrl = SaveToTmp (fullImage, "toUploadFull.tmp"); // Resizes thumbnail to be 200 x 200 px and then saves to different temp file UIImage thumbImage = Resize (cropped, image.CurrentScale, image.Orientation, new CGSize (200, 200)); var thumbURL = SaveToTmp (thumbImage, "toUploadThumb.tmp"); // Creates Image record type with two assets, full sized image and thumbnail sized image CKRecord newImageRecord = new CKRecord (RecordType); newImageRecord [FullsizeKey] = new CKAsset (fullUrl); newImageRecord [ThumbnailKey] = new CKAsset (thumbURL); // Calls designated initalizer, this is a new image so it is not on the server Init (newImageRecord, false); } }
void OnPostFetched(CKRecord record) { // When we get a record, use it to create an Post Post fetchedPost = new Post (record); downloadingBatchStorage.Add (fetchedPost); fetchedPost.LoadImage (new string[]{ Image.FullsizeKey }, () => { // Once image is loaded, tell the tableview to reload DispatchQueue.MainQueue.DispatchAsync (reloadHandler); }); }
void OnLoadNewPostFetchRecord(CKRecord record, List<Post> newPosts, ref Post lastRecordInOperation) { // If the record we just fetched doesn't match recordIDs to any item in our newPosts array, let's make an Post and add it var matchingRecord = newPosts.FindIndex (p => p.PostRecord.Id.Equals(record.Id)); if (matchingRecord == -1) { Post fetchedPost = new Post (record); newPosts.Add (fetchedPost); fetchedPost.LoadImage(new string[] { Image.FullsizeKey }, reloadHandler); lastRecordInOperation = fetchedPost; } else { // If we already have this record we don't have to fetch. We'll still update lastRecordInOperation because we did see it on the server lastRecordInOperation = newPosts[matchingRecord]; } }
public async Task SaveAsync (CKRecord record) { try { await publicDatabase.SaveRecordAsync (record); Console.WriteLine ("Successfuly saved record!"); } catch (Exception e) { Console.WriteLine ("An error occured: {0}", e.Message); } }
public CKRecordWrapper (CKRecord record) { Record = record; }
public void AddRecord (CKRecord record) { Results.Items.Add (new CKRecordWrapper (record)); recordsByID [record.Id] = record; Results.Added.Add (Results.Items.Count - 1); }
async void SaveSearchRequest (string searchRequestValue) { var newRecord = new CKRecord ("SearchRequest"); newRecord ["value"] = (NSString)searchRequestValue; await cloudManager.SaveAsync (newRecord); }
public Post (CKRecord postRecord) { PostRecord = postRecord; }
public PatronSubscription (CKRecord record) { Record = record; }
public void MarkRecordAsModified (CKRecord record) { var index = IndexOfRecordByRecordID (record.Id); if (index >= 0) Results.Modified.Add (index); }
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); }