From ff987665b10ea56761e150396940a75e3fe5f1e1 Mon Sep 17 00:00:00 2001 From: Nathan Kellert Date: Wed, 24 Jul 2019 18:09:18 -0500 Subject: [PATCH 01/18] Adding 'Deleting Files' header and updating information. --- _includes/ios/files.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/_includes/ios/files.md b/_includes/ios/files.md index d70e5039a..f9a3f7d49 100644 --- a/_includes/ios/files.md +++ b/_includes/ios/files.md @@ -142,6 +142,8 @@ file?.saveInBackground({ (success: Bool, error: Error?) in ``` -You can delete files that are referenced by objects using the [REST API]({{ site.baseUrl }}/rest/guide/#deleting-files). You will need to provide the master key in order to be allowed to delete a file. +##Deleting Files -If your files are not referenced by any object in your app, it is not possible to delete them through the REST API. You may request a cleanup of unused files in your app's Settings page. Keep in mind that doing so may break functionality which depended on accessing unreferenced files through their URL property. Files that are currently associated with an object will not be affected. +You can delete files using the [REST API]({{site.baseUrl}}/rest/guide/#deleting-files) using the files name. You will need to provide the master key in order to be allowed to delete a file. + +Note: Reguardless of the Parse Server storage configuration, deleting a `PFObject` with a `PFFileObject` does not delete the file itself meerly its reference. Additionally, Parse does **NOT** provide a way to find unreferenced file names in storage. From e1f3f847027ff2f846d544a115d2dea45e8c12b3 Mon Sep 17 00:00:00 2001 From: Nathan Kellert Date: Wed, 24 Jul 2019 19:36:30 -0500 Subject: [PATCH 02/18] Updating objects documentation. *Changed PFObject fetch example to use fetchInBackground and updated documentation to reflect example used. *Removed Local Datastore documentation instructing to unnecessarily add a dynamic library. --- _includes/ios/objects.md | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/_includes/ios/objects.md b/_includes/ios/objects.md index 8be4805dd..34f5b41b9 100644 --- a/_includes/ios/objects.md +++ b/_includes/ios/objects.md @@ -123,22 +123,35 @@ let acl = gameScore.acl If you need to refresh an object you already have with the latest data that - is in the Parse Cloud, you can call the `fetch` method like so: +is in the Parse Cloud, you can use the `fetch` or `fetchInBackgroundWithTarget:selector:` methods to provide additional logic which will run after fetching the object. +
```objective_c -[myObject fetch]; +[myObject fetchInBackgroundWithBlock:^(PFObject * _Nullable object, NSError * _Nullable error) { + if (!error) { + // Success! + } else { + // Failure! + } + }]; ``` ```swift -myObject.fetch() +myObject.fetchInBackground { (object, error) in + if error == nil { + // Success! + } else { + // Failure! + } +} ```
-Note: In a similar way to the `save` methods, you can use the `fetchInBackgroundWithBlock` or `fetchInBackgroundWithTarget:selector:` methods to provide additional logic which will run after fetching the object. +Note: In a similar way to the `save` methods, you can use the throwable `fetch` or `fetchIfNeeded` methods, or asyncronous task without completion. `fetchInBackground` ## The Local Datastore -Parse also lets you store objects in a [local datastore](#local-datastore) on the device itself. You can use this for data that doesn't need to be saved to the cloud, but this is especially useful for temporarily storing data so that it can be synced later. To enable the datastore, add `libsqlite3.dylib` and add `isLocalDatastoreEnabled = true` to the `ParseClientConfiguration` block in your `AppDelegate` `application:didFinishLaunchWithOptions:` before calling `Parse.initialize()`. Once the local datastore is enabled, you can store an object by pinning it. +Parse also lets you store objects in a [local datastore](#local-datastore) on the device itself. You can use this for data that doesn't need to be saved to the cloud, but this is especially useful for temporarily storing data so that it can be synced later. To enable the datastore, add `isLocalDatastoreEnabled = true` to the `ParseClientConfiguration` block in your `AppDelegate` `application:didFinishLaunchWithOptions:`, or call `Parse.enableLocalDatastore()` before calling `Parse.initialize()`. Once the local datastore is enabled, you can store an object by pinning it.
```objective_c From c75f249298bd447dc553d039120e6ecb476a063b Mon Sep 17 00:00:00 2001 From: Nathan Kellert Date: Wed, 24 Jul 2019 21:01:43 -0500 Subject: [PATCH 03/18] Update Local Datastore Documentation. *Removed unnecessary instructions to manually add dynamic library *Updated Objective-C AppDelegate example to be more in line with the Swift example. *Added documentation to include Parse.enableLocalDatastore() *Updating examples for Retrieving Objects in Local Data Store to use PFObjectResultBlock rather than a BFTask completion in order to reduce confusion. --- _includes/ios/local-datastore.md | 37 ++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/_includes/ios/local-datastore.md b/_includes/ios/local-datastore.md index 530bf0e04..b69642b63 100644 --- a/_includes/ios/local-datastore.md +++ b/_includes/ios/local-datastore.md @@ -1,14 +1,19 @@ # Local Datastore -The Parse iOS/OS X SDK provides a local datastore which can be used to store and retrieve `PFObject`s, even when the network is unavailable. To enable this functionality, add `libsqlite3.dylib` and add `isLocalDatastoreEnabled = true` to the `ParseClientConfiguration` block used in `Parse.initialize()`. +The Parse iOS/OS X SDK provides a local datastore which can be used to store and retrieve `PFObject`s, even when the network is unavailable. To enable this functionality add `isLocalDatastoreEnabled = true` to the `ParseClientConfiguration` block used in `Parse.initialize()` or call `Parse.enableLocalDatastore()` prior to initializing Parse.
```objective_c @implementation AppDelegate - (void)application:(UIApplication *)application didFinishLaunchWithOptions:(NSDictionary *)options { - [Parse enableLocalDatastore]; - [Parse setApplicationId:@"parseAppId" clientKey:@"parseClientKey"]; + ParseClientConfiguration *configuration = [ParseClientConfiguration configurationWithBlock:^(id configuration) { + configuration.applicationId = @"parseAppId"; + configuration.clientKey = @"parseClientKey"; + configuration.server = @"parseServerUrlString"; + configuration.localDatastoreEnabled = YES; + }]; + [Parse initializeWithConfiguration:configuration]; } @end @@ -74,28 +79,28 @@ Storing objects is great, but it's only useful if you can then get the objects b ```objective_c PFQuery *query = [PFQuery queryWithClassName:@"GameScore"]; [query fromLocalDatastore]; -[[query getObjectInBackgroundWithId:@"xWMyZ4YE"] continueWithBlock:^id(BFTask *task) { - if (task.error) { - // Something went wrong. - return task; - } +[query getObjectInBackgroundWithId:"" block:^(PFObject * _Nullable object, NSError * _Nullable error) { + if (!error) { + // Success + } else { + // Fail! + } +} // task.result will be your game score return task; }]; ``` + ```swift let query = PFQuery(className: "GameScore") query.fromLocalDatastore() -query.getObjectInBackgroundWithId("xWMyZ4YE").continueWithBlock { - (task: BFTask!) -> AnyObject in - if let error = task.error { - // Something went wrong. - return task; +query.getObjectInBackground(withId: "string") { (object, error) in + if error == nil { + // Success! + } else { + // Failure! } - - // task.result will be your game score - return task; } ```
From 9ac5eedccd8ca4ad0197d4198c43dbc95238c844 Mon Sep 17 00:00:00 2001 From: Nathan Kellert Date: Wed, 24 Jul 2019 22:08:54 -0500 Subject: [PATCH 04/18] Correcting Getting Started Example for initialization --- _includes/ios/getting-started.md | 1 + 1 file changed, 1 insertion(+) diff --git a/_includes/ios/getting-started.md b/_includes/ios/getting-started.md index f0657de5d..1536bbd61 100644 --- a/_includes/ios/getting-started.md +++ b/_includes/ios/getting-started.md @@ -64,6 +64,7 @@ func application(application: UIApplication, didFinishLaunchingWithOptions launc $0.server = "parseServerUrlString" } Parse.initialize(with: parseConfig) + return true } ```
From 6c38d6b656f4930d2028efc2d4d4f13d501da76e Mon Sep 17 00:00:00 2001 From: Nathan Kellert Date: Thu, 25 Jul 2019 04:40:50 -0500 Subject: [PATCH 05/18] Major Updates to objects. *Updated Swift and Objective-C examples to reflect current version of Parse iOS SDK and language changes as well as to make more consistent between language examples. *Updated verbiage document wide to improve comprehention and remove documentation that is no longer relevant or helpful by todays standard. --- _includes/ios/objects.md | 195 +++++++++++++++++++-------------------- 1 file changed, 93 insertions(+), 102 deletions(-) diff --git a/_includes/ios/objects.md b/_includes/ios/objects.md index 34f5b41b9..6ce281224 100644 --- a/_includes/ios/objects.md +++ b/_includes/ios/objects.md @@ -2,7 +2,7 @@ ## The PFObject -Storing data on Parse is built around the `PFObject`. Each `PFObject` contains key-value pairs of JSON-compatible data. This data is schemaless, which means that you don't need to specify ahead of time what keys exist on each `PFObject`. You simply set whatever key-value pairs you want, and our backend will store it. +Storing data on Parse is built around the `PFObject`. Each `PFObject` contains key-value pairs of JSON-compatible data. This data is schemeless, which means that you don't need to specify ahead of time what keys exist on each `PFObject`. You simply set whatever key-value pairs you want, and our backend will store it. For example, let's say you're tracking high scores for a game. A single `PFObject` could contain: @@ -16,7 +16,7 @@ Each `PFObject` has a class name that you can use to distinguish different sorts ## Saving Objects -Let's say you want to save the `GameScore` described above to the Parse Cloud. The interface is similar to a `NSMutableDictionary`, plus the `saveInBackground` method: +Let's say you want to save the `GameScore` described above to a Parse Server. The interface is similar to a `NSMutableDictionary`. The `saveInBackgroundWithBlock` function:
```objective_c @@ -24,7 +24,7 @@ PFObject *gameScore = [PFObject objectWithClassName:@"GameScore"]; gameScore[@"score"] = @1337; gameScore[@"playerName"] = @"Sean Plott"; gameScore[@"cheatMode"] = @NO; -[gameScore saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) { +[gameScore saveInBackgroundWithBlock:^(BOOL succeeded, NSError * _Nullable error) { if (succeeded) { // The object has been saved. } else { @@ -37,18 +37,17 @@ let gameScore = PFObject(className:"GameScore") gameScore["score"] = 1337 gameScore["playerName"] = "Sean Plott" gameScore["cheatMode"] = false -gameScore.saveInBackground { - (success: Bool, error: Error?) in - if (success) { - // The object has been saved. - } else { - // There was a problem, check error.description - } +gameScore.saveInBackground { (succeeded, error) in + if (succeeded) { + // The object has been saved. + } else { + // There was a problem, check error.description + } } ```
-After this code runs, you will probably be wondering if anything really happened. To make sure the data was saved, you can look at the Data Browser in your app on Parse. You should see something like this: +After this code runs, you will probably be wondering if anything really happened. If [Parse Dashboard](https://github.com/parse-community/parse-dashboard) is implemented for your server, you can verify the data was saved in the data browser. You should see something like this: ```js objectId: "xWMyZ4YEGZ", score: 1337, playerName: "Sean Plott", cheatMode: false, @@ -57,9 +56,7 @@ createdAt:"2011-06-10T18:33:42Z", updatedAt:"2011-06-10T18:33:42Z" There are two things to note here. You didn't have to configure or set up a new Class called `GameScore` before running this code. Your Parse app lazily creates this Class for you when it first encounters it. -There are also a few fields you don't need to specify that are provided as a convenience. `objectId` is a unique identifier for each saved object. `createdAt` and `updatedAt` represent the time that each object was created and last modified in the Parse Cloud. Each of these fields is filled in by Parse, so they don't exist on a `PFObject` until a save operation has completed. - -Note: You can use the `saveInBackgroundWithBlock` method to provide additional logic to run after the save completes. +There are also a few fields you don't need to specify that are provided and set by the system as a convenience. `objectId` is a unique identifier for each saved object. `createdAt` and `updatedAt` represent the time that each object was created or last modified and saved to the Parse Server. Each of these fields is filled in by Parse, so they don't exist on a `PFObject` until the first save operation has been completed. ## Retrieving Objects @@ -69,22 +66,20 @@ Saving data to the cloud is fun, but it's even more fun to get that data out aga ```objective_c PFQuery *query = [PFQuery queryWithClassName:@"GameScore"]; [query getObjectInBackgroundWithId:@"xWMyZ4YEGZ" block:^(PFObject *gameScore, NSError *error) { - // Do something with the returned PFObject in the gameScore variable. - NSLog(@"%@", gameScore); + if (!error) { + // Success! + } else { + // Failure! + } }]; -// The InBackground methods are asynchronous, so any code after this will run -// immediately. Any code that depends on the query result should be moved -// inside the completion block above. ``` ```swift let query = PFQuery(className:"GameScore") -query.getObjectInBackground(withId: "xWMyZEGZ") { (gameScore: PFObject?, error: Error?) in - if let error = error { - //The query returned an error - print(error.localizedDescription) +query.getObjectInBackground(withId: "xWMyZEGZ") { (object, error) in + if error == nil { + // Success! } else { - //The object has been retrieved - print(gameScore) + // Fail! } } ``` @@ -123,7 +118,7 @@ let acl = gameScore.acl If you need to refresh an object you already have with the latest data that -is in the Parse Cloud, you can use the `fetch` or `fetchInBackgroundWithTarget:selector:` methods to provide additional logic which will run after fetching the object. +is in the cloud, you can use the `fetchInBackgroundWithBlock:` or `fetchInBackgroundWithTarget:selector:` methods to provide additional logic which will run after fetching the object.
@@ -134,7 +129,7 @@ is in the Parse Cloud, you can use the `fetch` or `fetchInBackgroundWithTarget:s } else { // Failure! } - }]; +}]; ``` ```swift myObject.fetchInBackground { (object, error) in @@ -174,7 +169,7 @@ As with saving, this recursively stores every object and file that `gameScore` p ### Retrieving Objects from the Local Datastore -Storing an object is only useful if you can get it back out. To get the data for a specific object, you can use a `PFQuery` just like you would while on the network, but using the `fromLocalDatastore` method to tell it where to get the data. +Storing an object is only useful if you can get it back out. To get the data for a specific object, you can use a `PFQuery` just like you would while on the network, but using the `fromLocalDatastore:` method to tell it where to get the data.
```objective_c @@ -205,7 +200,7 @@ query.getObjectInBackground(withId: "xWMyZEGZ").continueWith { (task: BFTask -If you already have an instance of the object, you can instead use the `fetchFromLocalDatastoreInBackground` method. +If you already have an instance of the object, you can instead use the `fetchFromLocalDatastoreInBackground:` method.
```objective_c @@ -236,7 +231,7 @@ object.fetchFromLocalDatastoreInBackground().continueWith { (task: BFTask ```objective_c @@ -362,7 +357,7 @@ Note that it is not currently possible to atomically add and remove items from a ## Deleting Objects -To delete an object from the cloud: +To delete an object from Parse Server:
```objective_c @@ -382,14 +377,14 @@ You can delete a single field from an object with the `removeObjectForKey` metho // After this, the playerName field will be empty [gameScore removeObjectForKey:@"playerName"]; -// Saves the field deletion to the Parse Cloud +// Saves the field deletion to the Parse Server [gameScore saveInBackground]; ``` ```swift // After this, the playerName field will be empty gameScore.remove(forKey: "playerName") -// Saves the field deletion to the Parse Cloud +// Saves the field deletion to the Parse Server. gameScore.saveInBackground() ```
@@ -435,16 +430,19 @@ myComment.saveInBackground() ```
-You can also link objects using just their `objectId`s like so: +Note: Saving an object with a relational pointer to another object will save both objects. However, two new objects with pointers to each other will cause a error for having a circular dependency. + +### Object Relationships With Minimal Data + +You can link objects without even fetching data by initializing `PFObjects` with only the class name and the objects `objectId` like so:
```objective_c -// Add a relation between the Post with objectId "1zEcyElZ80" and the comment -myComment[@"parent"] = [PFObject objectWithoutDataWithClassName:@"Post" objectId:@"1zEcyElZ80"]; +myComment[@"post"] = [PFObject objectWithoutDataWithClassName:@"Post" objectId:@"1zEcyElZ80"]; ``` ```swift // Add a relation between the Post with objectId "1zEcyElZ80" and the comment -myComment["parent"] = PFObject(withoutDataWithClassName:"Post", objectId:"1zEcyElZ80") +myComment["post"] = PFObject(withoutDataWithClassName: "Post", objectId: "1zEcyElZ80") ```
@@ -452,17 +450,20 @@ By default, when fetching an object, related `PFObject`s are not fetched. These
```objective_c -PFObject *post = fetchedComment[@"parent"]; -[post fetchIfNeededInBackgroundWithBlock:^(PFObject *post, NSError *error) { - NSString *title = post[@"title"]; - // do something with your title variable +PFObject *post = myComment[@"post"]; +[post fetchInBackgroundWithBlock:^(PFObject * _Nullable object, NSError * _Nullable error) { + NSString *title = post[@"title"]; + if (title) { // do something with title } }]; ``` ```swift let post = myComment["parent"] as! PFObject -post.fetchIfNeededInBackground { (post: PFObject?, error: Error?) in - let title = post?["title"] as? String - // do something with your title variable +post.fetchIfNeededInBackground { (object, error) in + if let title = post["title"] as? String { + // do something with your title variable + } else if let errorString = error?.localizedDescription { + print(errorString) + } } ```
@@ -474,78 +475,75 @@ You can also model a many-to-many relation using the `PFRelation` object. This PFUser *user = [PFUser currentUser]; PFRelation *relation = [user relationForKey:@"likes"]; [relation addObject:post]; -[user saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) { - if (succeeded) { - // The post has been added to the user's likes relation. - } else { - // There was a problem, check error.description - } +[user saveInBackgroundWithBlock:^(BOOL succeeded, NSError * _Nullable error) { + if (succeeded) { + // The post has been added to the user's likes relation. + } else { + // There was a problem, check error.description + } }]; ``` ```swift -let user = PFUser.current() -let relation = user?.relation(forKey: "likes") -relation?.add(post) -user?.saveInBackground(block: { (success: Bool, error: Error?) in - if (success) { +guard let user = PFUser.current() else { return } +let relation = user.relation(forKey: "likes") +relation.add(post) +user.saveInBackground { (succeeded, error) in + if (succeeded) { // The post has been added to the user's likes relation. } else { // There was a problem, check error.description } -}) - +} ```
-You can remove a post from the `PFRelation` with something like: - -
-```objective_c -[relation removeObject:post]; -``` -```swift -relation?.remove(post) -``` -
+You can remove a post from the `PFRelation` similarly using the `removeObject:` function followed by saving the parent object. By default, the list of objects in this relation are not downloaded. You can get the list of `Post`s by using calling `findObjectsInBackgroundWithBlock:` on the `PFQuery` returned by `query`. The code would look like:
```objective_c -[[relation query] findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) { - if (error) { - // There was an error - } else { - // objects has all the Posts the current user liked. - } +[[relation query] findObjectsInBackgroundWithBlock:^(NSArray * _Nullable objects, NSError * _Nullable error) { + if (error) { + // There was an error + } else { + // objects has all the Posts the current user liked. + } }]; ``` ```swift -relation?.query().findObjectsInBackground(block: { (objects: [PFObject]?, error: Error?) in - if let error = error { - // There was an error - print(error.localizedDescription) +relation.query().findObjectsInBackground { (object, error) in + if error == nil { + // Success } else { - // objects has all the Posts the current user liked. + // Failure! } }) ```
-If you want only a subset of the `Post`s you can add extra constraints to the `PFQuery` returned by `query` like this: +You can add constraints to a `PFRelation`'s query by adding constraints to the `PFQuery` returned by its `query` parameter as demonstrated below:
```objective_c PFQuery *query = [relation query]; -// Add other query constraints. +[query whereKey:"category" equalTo:@"development"]; +PFObject *object = [query getFirstObject]; // Query first object found +if (object) { + // Do something with object +} ``` ```swift -var query = relation?.query() -// Add other query constraints. -``` +var query = relation.query() +query.whereKey("category", equalTo: "development") + +// Query first object found +if let object = try? query.getFirstObject() { + // Do something with object +} ```
-For more details on `PFQuery` please look at the query portion of this guide. A `PFRelation` behaves similar to an `NSArray` of `PFObject`, so any queries you can do on arrays of objects (other than `includeKey:`) you can do on `PFRelation`. +You can learn more queries by visiting the [PFQuery](#queries) section. A `PFRelation` behaves similarly to an array of `PFObject` yet has a built in query that's capable of everything a standard `PFQuery` is other than `includeKey:`. ## Data Types @@ -609,7 +607,7 @@ bigObject.saveInBackground() ```
-We do not recommend storing large pieces of binary data like images or documents on `PFObject`. `PFObject`s should not exceed 128 kilobytes in size. We recommend you use `PFFileObject`s to store images, documents, and other types of files. You can do so by instantiating a `PFFileObject` object and setting it on a field. See [Files](#files) for more details. +We do not recommend storing large pieces of binary data like images or documents on `PFObject`. We recommend you use `PFFileObject`s to store images, documents, and other types of files. You can do so by instantiating a `PFFileObject` object and setting it on a field. See [Files](#files) for more details. For more information about how Parse handles data, check out our documentation on [Data](#data). @@ -625,7 +623,7 @@ shield[@"fireProof"] = @NO; shield[@"rupees"] = @50; ``` ```swift -var shield = PFObject(className:"Armor") +var shield = PFObject(className: "Armor") shield["displayName"] = "Wooden Shield" shield["fireProof"] = false shield["rupees"] = 50 @@ -651,20 +649,12 @@ shield.rupees = 50 ### Subclassing PFObject -To create a `PFObject` subclass: - -1. Declare a subclass which conforms to the `PFSubclassing` protocol. -2. Implement the class method `parseClassName`. This is the string you would pass to `initWithClassName:` and makes all future class name references unnecessary. -3. Import `PFObject+Subclass` in your .m file. This implements all methods in `PFSubclassing` beyond `parseClassName`. -4. Call `[YourClass registerSubclass]` before Parse `setApplicationId:clientKey:`. +To create a subclass: -An easy way to do this is with your class' [+load](https://developer.apple.com/reference/objectivec/nsobject/1418815-load?language=objc) (Obj-C only) or with [initialize](https://developer.apple.com/reference/objectivec/nsobject/1418639-initialize) (both Obj-C and Swift) methods. +1. Declare a subclass of `PFObject` which conforms to the `PFSubclassing` protocol. +2. Implement the static method `parseClassName` and return the string you would pass to `initWithClassName:`. This makes all future class name references unnecessary. -Please note that the `initialize` method is not called until the class receives its first message, meaning that you need to call any instance or class method on your subclass before it will be registered with Parse SDK. - -The following code successfully declares, implements, and registers the `Armor` subclass of `PFObject`: - - +Note: Objective-C developers should Import `PFObject+Subclass` in your .m file. This implements all methods in `PFSubclassing` beyond `parseClassName`. ### Properties & Methods @@ -672,8 +662,6 @@ Adding custom properties and methods to your `PFObject` subclass helps encapsula `PFObject` supports dynamic synthesizers just like `NSManagedObject`. Declare a property as you normally would, but use `@dynamic` rather than `@synthesize` in your .m file. The following example creates a `displayName` property in the `Armor` class: - - You can access the displayName property using `armor.displayName` or `[armor displayName]` and assign to it using `armor.displayName = @"Wooden Shield"` or `[armor setDisplayName:@"Wooden Sword"]`. Dynamic properties allow Xcode to provide autocomplete and catch typos. `NSNumber` properties can be implemented either as `NSNumber`s or as their primitive counterparts. Consider the following example: @@ -701,16 +689,19 @@ If you need more complicated logic than simple property access, you can declare PFImageView *view = [[PFImageView alloc] initWithImage:kPlaceholderImage]; view.file = self.iconFile; [view loadInBackground]; + return view; } ``` + ```swift -@NSManaged var iconFile: PFFileObject +@NSManaged var iconFile: PFFileObject! func iconView() -> UIImageView { let view = PFImageView(imageView: PlaceholderImage) view.file = iconFile view.loadInBackground() + return view } ``` @@ -718,4 +709,4 @@ func iconView() -> UIImageView { ### Initializing Subclasses -You should create new objects with the `object` class method. This constructs an autoreleased instance of your type and correctly handles further subclassing. To create a reference to an existing object, use `objectWithoutDataWithObjectId:`. +You should initialize new instances of subclassses with standard initialization methods. To create a new instance to an existing Parse object, use the inherited `PFObject` class function `objectWithoutDataWithObjectId:`, or create a new object and set the objectId property manually. From 81cdd28ae017cd6ae6932d984e8eb7a47b128096 Mon Sep 17 00:00:00 2001 From: Nathan Kellert Date: Thu, 25 Jul 2019 05:52:49 -0500 Subject: [PATCH 06/18] Updating object deletion documention. *Removed irrelevant documention for deleting individual relational pointer data. *Replaced basic single line "deleteInBackground" example in favor of demonstrating multi-object deletion using PFObject's static deleteAllInBackground:block function. --- _includes/ios/objects.md | 43 ++++++++++++++++++---------------------- 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/_includes/ios/objects.md b/_includes/ios/objects.md index 6ce281224..3f5387d85 100644 --- a/_includes/ios/objects.md +++ b/_includes/ios/objects.md @@ -352,43 +352,38 @@ gameScore.saveInBackground() ``` -Note that it is not currently possible to atomically add and remove items from an array in the same save. - You will have to call `save` in between every different kind of array operation. +Note that it is not currently possible to atomically add and remove items from an array in the same save using. You will have to call `save` in between every different kind of array operation. ## Deleting Objects -To delete an object from Parse Server: +There are a few ways to delete a `PFObject`. For basic asynchronous deletion of a single object call the objects `deleteInBackground` function. If you prefer to recieve a callback you can use the `deleteInBackgroundWithBlock:` or `deleteInBackgroundWithTarget:selector:` methods. If you want to block the calling thread, you can use the `delete` method. Lastly, `deleteEventually` network consious solution that deletes when possible but does not guarantee a timeframe for the tasks completion. -
-```objective_c -[gameScore deleteInBackground]; -``` -```swift -gameScore.deleteInBackground() -``` -
- -If you want to run a callback when the delete is confirmed, you can use the `deleteInBackgroundWithBlock:` or `deleteInBackgroundWithTarget:selector:` methods. If you want to block the calling thread, you can use the `delete` method. +For deleting multiple objects use the `PFObject` static function `deleteAllInBackground` to delete an array of objects asynchronous. The same can be done while blocking the calling thread using `deleteAll`. Lastly, to recieve a callback after deleting objects asyncronously use `deleteAllInBackground:block:` as demonstrated below. -You can delete a single field from an object with the `removeObjectForKey` method:
```objective_c -// After this, the playerName field will be empty -[gameScore removeObjectForKey:@"playerName"]; - -// Saves the field deletion to the Parse Server -[gameScore saveInBackground]; +[PFObject deleteAllInBackground:objectArray block:^(BOOL succeeded, NSError * _Nullable error) { + if (succeeded) { + // The array of objects was successfully deleted. + } else { + // There was an error. Check the errors localizedDescription. + } +}]; ``` ```swift -// After this, the playerName field will be empty -gameScore.remove(forKey: "playerName") - -// Saves the field deletion to the Parse Server. -gameScore.saveInBackground() +PFObject.deleteAll(inBackground: objectArray) { (succeeded, error) in + if (succeeded) { + // The array of objects was successfully deleted. + } else { + // There was an error. Check the errors localizedDescription. + } +} ```
+Note: Deleting an object from the server that contains a `PFFileObject` does **NOT** delete the file from storage. Instead, an objects deletion only deletes the data referencing the stored file. To delete the data from storage you must use the [REST API]({{site.baseUrl}}/rest/guide/#deleting-files). For more info about `PFFileObject`, please see the [Files](#files) section. + ## Relational Data Objects can have relationships with other objects. To model this behavior, any `PFObject` can be used as a value in other `PFObject`s. Internally, the Parse framework will store the referred-to object in just one place, to maintain consistency. From be2ea237270cc6ebecd13b12aec586895f5cd6fa Mon Sep 17 00:00:00 2001 From: Nathan Kellert Date: Thu, 25 Jul 2019 06:12:11 -0500 Subject: [PATCH 07/18] Simplifying saveEventually explanation. --- _includes/ios/objects.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_includes/ios/objects.md b/_includes/ios/objects.md index 3f5387d85..a877fabdc 100644 --- a/_includes/ios/objects.md +++ b/_includes/ios/objects.md @@ -244,7 +244,7 @@ gameScore.unpinInBackground() ## Saving Objects Offline -Most save functions execute immediately, and inform your app when the save is complete. If you don't need to know when the save has finished, you can use `saveEventually` instead. The advantage is that if the user currently doesn't have a network connection, `saveEventually` will store the update on the device until a network connection is re-established. If your app is closed before the connection is back, Parse will try again the next time the app is opened. All calls to `saveEventually` (and `deleteEventually`) are executed in the order they are called, so it is safe to call `saveEventually` on an object multiple times. +Most save functions execute immediately, and inform your app when the save is complete. For a network consious soltion on non-priority save requests use `saveEventually`. Not only does it retry saving upon regaining network connection, but If your app is closed prior to save completion Parse will try the next time the app is opened. Additionally, all calls to `saveEventually` (and `deleteEventually`) are executed in the order they are called, making it safe to call `saveEventually` on an object multiple times.
```objective_c From 3d812d8544980d7ac5da33790a9002b04514ba43 Mon Sep 17 00:00:00 2001 From: Nathan Kellert Date: Thu, 25 Jul 2019 08:09:04 -0500 Subject: [PATCH 08/18] Update _includes/ios/objects.md Co-Authored-By: Tom Fox --- _includes/ios/objects.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_includes/ios/objects.md b/_includes/ios/objects.md index a877fabdc..c6cf6a9d6 100644 --- a/_includes/ios/objects.md +++ b/_includes/ios/objects.md @@ -118,7 +118,7 @@ let acl = gameScore.acl
If you need to refresh an object you already have with the latest data that -is in the cloud, you can use the `fetchInBackgroundWithBlock:` or `fetchInBackgroundWithTarget:selector:` methods to provide additional logic which will run after fetching the object. +is in the database, you can use the `fetchInBackgroundWithBlock:` or `fetchInBackgroundWithTarget:selector:` methods to provide additional logic which will run after fetching the object.
From cfccc1150745cfe906b0e127be76f2763e09a561 Mon Sep 17 00:00:00 2001 From: Nathan Kellert Date: Thu, 25 Jul 2019 11:11:05 -0500 Subject: [PATCH 09/18] Update _includes/ios/files.md Co-Authored-By: Tom Fox --- _includes/ios/files.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_includes/ios/files.md b/_includes/ios/files.md index f9a3f7d49..c98b6d9c5 100644 --- a/_includes/ios/files.md +++ b/_includes/ios/files.md @@ -144,6 +144,6 @@ file?.saveInBackground({ (success: Bool, error: Error?) in ##Deleting Files -You can delete files using the [REST API]({{site.baseUrl}}/rest/guide/#deleting-files) using the files name. You will need to provide the master key in order to be allowed to delete a file. +If you know the name of a file you can delete it using the [REST API]({{site.baseUrl}}/rest/guide/#deleting-files). Your master key is required for this operation. Note: Reguardless of the Parse Server storage configuration, deleting a `PFObject` with a `PFFileObject` does not delete the file itself meerly its reference. Additionally, Parse does **NOT** provide a way to find unreferenced file names in storage. From 1c88f4ebaeee538e8bc812e35baa0f602f9d120c Mon Sep 17 00:00:00 2001 From: Nathan Kellert Date: Thu, 25 Jul 2019 11:18:56 -0500 Subject: [PATCH 10/18] Correcting spelling fo schemaless --- _includes/ios/objects.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_includes/ios/objects.md b/_includes/ios/objects.md index c6cf6a9d6..fbd2888bb 100644 --- a/_includes/ios/objects.md +++ b/_includes/ios/objects.md @@ -2,7 +2,7 @@ ## The PFObject -Storing data on Parse is built around the `PFObject`. Each `PFObject` contains key-value pairs of JSON-compatible data. This data is schemeless, which means that you don't need to specify ahead of time what keys exist on each `PFObject`. You simply set whatever key-value pairs you want, and our backend will store it. +Storing data on Parse is built around the `PFObject`. Each `PFObject` contains key-value pairs of JSON-compatible data. This data is schemaless, which means that you don't need to specify ahead of time what keys exist on each `PFObject`. You simply set whatever key-value pairs you want, and our backend will store it. For example, let's say you're tracking high scores for a game. A single `PFObject` could contain: From b4af90feae410c46ec49ae34ace317fa65640cb4 Mon Sep 17 00:00:00 2001 From: Nathan Kellert Date: Thu, 25 Jul 2019 11:22:20 -0500 Subject: [PATCH 11/18] Update _includes/ios/objects.md Co-Authored-By: Tom Fox --- _includes/ios/objects.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_includes/ios/objects.md b/_includes/ios/objects.md index fbd2888bb..691784de7 100644 --- a/_includes/ios/objects.md +++ b/_includes/ios/objects.md @@ -56,7 +56,7 @@ createdAt:"2011-06-10T18:33:42Z", updatedAt:"2011-06-10T18:33:42Z" There are two things to note here. You didn't have to configure or set up a new Class called `GameScore` before running this code. Your Parse app lazily creates this Class for you when it first encounters it. -There are also a few fields you don't need to specify that are provided and set by the system as a convenience. `objectId` is a unique identifier for each saved object. `createdAt` and `updatedAt` represent the time that each object was created or last modified and saved to the Parse Server. Each of these fields is filled in by Parse, so they don't exist on a `PFObject` until the first save operation has been completed. +There are also a few fields you don't need to specify that are provided and set by the system as a convenience. `objectId` is a unique identifier for each saved object. `createdAt` and `updatedAt` represent the time that each object was created or last modified and saved to the Parse Server. Each of these fields is filled in by Parse Server, so they don't exist on a `PFObject` until the first save operation has been completed. ## Retrieving Objects From a25e0252e4ba741138d2e90d358ae2d8525f7aa2 Mon Sep 17 00:00:00 2001 From: Nathan Kellert Date: Thu, 25 Jul 2019 11:32:22 -0500 Subject: [PATCH 12/18] Update _includes/ios/objects.md Co-Authored-By: Tom Fox --- _includes/ios/objects.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/_includes/ios/objects.md b/_includes/ios/objects.md index 691784de7..803f839d2 100644 --- a/_includes/ios/objects.md +++ b/_includes/ios/objects.md @@ -356,7 +356,8 @@ Note that it is not currently possible to atomically add and remove items from a ## Deleting Objects -There are a few ways to delete a `PFObject`. For basic asynchronous deletion of a single object call the objects `deleteInBackground` function. If you prefer to recieve a callback you can use the `deleteInBackgroundWithBlock:` or `deleteInBackgroundWithTarget:selector:` methods. If you want to block the calling thread, you can use the `delete` method. Lastly, `deleteEventually` network consious solution that deletes when possible but does not guarantee a timeframe for the tasks completion. + +There are a few ways to delete a `PFObject`. For basic asynchronous deletion of a single object call the objects `deleteInBackground` function. If you prefer to recieve a callback you can use the `deleteInBackgroundWithBlock:` or `deleteInBackgroundWithTarget:selector:` methods. If you want to block the calling thread, you can use the `delete` method. Lastly, `deleteEventually` network conscious solution that deletes when possible but does not guarantee a timeframe for the tasks completion. For deleting multiple objects use the `PFObject` static function `deleteAllInBackground` to delete an array of objects asynchronous. The same can be done while blocking the calling thread using `deleteAll`. Lastly, to recieve a callback after deleting objects asyncronously use `deleteAllInBackground:block:` as demonstrated below. From 09113df4cc7427296cee435fc1ea4dd6a3048b65 Mon Sep 17 00:00:00 2001 From: Nathan Kellert Date: Thu, 25 Jul 2019 12:17:12 -0500 Subject: [PATCH 13/18] Update _includes/ios/objects.md Co-Authored-By: Tom Fox --- _includes/ios/objects.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_includes/ios/objects.md b/_includes/ios/objects.md index 803f839d2..058595f26 100644 --- a/_includes/ios/objects.md +++ b/_includes/ios/objects.md @@ -359,7 +359,7 @@ Note that it is not currently possible to atomically add and remove items from a There are a few ways to delete a `PFObject`. For basic asynchronous deletion of a single object call the objects `deleteInBackground` function. If you prefer to recieve a callback you can use the `deleteInBackgroundWithBlock:` or `deleteInBackgroundWithTarget:selector:` methods. If you want to block the calling thread, you can use the `delete` method. Lastly, `deleteEventually` network conscious solution that deletes when possible but does not guarantee a timeframe for the tasks completion. -For deleting multiple objects use the `PFObject` static function `deleteAllInBackground` to delete an array of objects asynchronous. The same can be done while blocking the calling thread using `deleteAll`. Lastly, to recieve a callback after deleting objects asyncronously use `deleteAllInBackground:block:` as demonstrated below. +For deleting multiple objects use the `PFObject` static function `deleteAllInBackground` to delete an array of objects asynchronously. The same can be done while blocking the calling thread using `deleteAll`. Lastly, to recieve a callback after deleting objects asyncronously use `deleteAllInBackground:block:` as demonstrated below.
From 5380974afc7091ca4b3daf66b538c7a0f93b171c Mon Sep 17 00:00:00 2001 From: Nathan Kellert Date: Tue, 30 Jul 2019 16:49:20 -0500 Subject: [PATCH 14/18] Update _includes/ios/objects.md Co-Authored-By: Tom Fox --- _includes/ios/objects.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_includes/ios/objects.md b/_includes/ios/objects.md index 058595f26..d21643158 100644 --- a/_includes/ios/objects.md +++ b/_includes/ios/objects.md @@ -75,7 +75,7 @@ PFQuery *query = [PFQuery queryWithClassName:@"GameScore"]; ``` ```swift let query = PFQuery(className:"GameScore") -query.getObjectInBackground(withId: "xWMyZEGZ") { (object, error) in +query.getObjectInBackground(withId: "xWMyZEGZ") { (gameScore, error) in if error == nil { // Success! } else { From bd68ea4fb16c7f83e1d9eb526473009e7330e086 Mon Sep 17 00:00:00 2001 From: Nathan Kellert Date: Tue, 30 Jul 2019 16:49:40 -0500 Subject: [PATCH 15/18] Update _includes/ios/objects.md Co-Authored-By: Tom Fox --- _includes/ios/objects.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_includes/ios/objects.md b/_includes/ios/objects.md index d21643158..d756ccedc 100644 --- a/_includes/ios/objects.md +++ b/_includes/ios/objects.md @@ -539,7 +539,7 @@ if let object = try? query.getFirstObject() { } ```
-You can learn more queries by visiting the [PFQuery](#queries) section. A `PFRelation` behaves similarly to an array of `PFObject` yet has a built in query that's capable of everything a standard `PFQuery` is other than `includeKey:`. +You can learn more about queries by visiting the [PFQuery](#queries) section. A `PFRelation` behaves similarly to an array of `PFObject` yet has a built in query that's capable of everything a standard `PFQuery` is other than `includeKey:`. ## Data Types From 2591ef6668b49f2f34c131394c59f53e8c2a31ac Mon Sep 17 00:00:00 2001 From: Nathan Kellert Date: Tue, 30 Jul 2019 17:14:51 -0500 Subject: [PATCH 16/18] Update _includes/ios/objects.md Co-Authored-By: Tom Fox --- _includes/ios/objects.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_includes/ios/objects.md b/_includes/ios/objects.md index d756ccedc..9b53121b8 100644 --- a/_includes/ios/objects.md +++ b/_includes/ios/objects.md @@ -705,4 +705,4 @@ func iconView() -> UIImageView { ### Initializing Subclasses -You should initialize new instances of subclassses with standard initialization methods. To create a new instance to an existing Parse object, use the inherited `PFObject` class function `objectWithoutDataWithObjectId:`, or create a new object and set the objectId property manually. +You should initialize new instances of subclassses with standard initialization methods. To create a new instance of an existing Parse object, use the inherited `PFObject` class function `objectWithoutDataWithObjectId:`, or create a new object and set the objectId property manually. From e044869c87debb526ecde5b5e92bc9dea644cae7 Mon Sep 17 00:00:00 2001 From: Nathan Kellert Date: Tue, 30 Jul 2019 17:15:21 -0500 Subject: [PATCH 17/18] Update _includes/ios/objects.md Co-Authored-By: Tom Fox --- _includes/ios/objects.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_includes/ios/objects.md b/_includes/ios/objects.md index 9b53121b8..a21af2cce 100644 --- a/_includes/ios/objects.md +++ b/_includes/ios/objects.md @@ -357,7 +357,7 @@ Note that it is not currently possible to atomically add and remove items from a ## Deleting Objects -There are a few ways to delete a `PFObject`. For basic asynchronous deletion of a single object call the objects `deleteInBackground` function. If you prefer to recieve a callback you can use the `deleteInBackgroundWithBlock:` or `deleteInBackgroundWithTarget:selector:` methods. If you want to block the calling thread, you can use the `delete` method. Lastly, `deleteEventually` network conscious solution that deletes when possible but does not guarantee a timeframe for the tasks completion. +There are a few ways to delete a `PFObject`. For basic asynchronous deletion of a single object call the objects `deleteInBackground` function. If you prefer to recieve a callback you can use the `deleteInBackgroundWithBlock:` or `deleteInBackgroundWithTarget:selector:` methods. If you want to block the calling thread, you can use the `delete` method. Lastly, `deleteEventually` is a network conscious option that deletes when possible but does not guarantee a timeframe for the tasks completion. For deleting multiple objects use the `PFObject` static function `deleteAllInBackground` to delete an array of objects asynchronously. The same can be done while blocking the calling thread using `deleteAll`. Lastly, to recieve a callback after deleting objects asyncronously use `deleteAllInBackground:block:` as demonstrated below. From 6ec087c1bf27a5e82507fb30e16722d6ea3c826d Mon Sep 17 00:00:00 2001 From: Nathan Kellert Date: Tue, 30 Jul 2019 17:20:53 -0500 Subject: [PATCH 18/18] Update _includes/ios/objects.md Co-Authored-By: Tom Fox --- _includes/ios/objects.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_includes/ios/objects.md b/_includes/ios/objects.md index a21af2cce..41055d5cc 100644 --- a/_includes/ios/objects.md +++ b/_includes/ios/objects.md @@ -118,7 +118,7 @@ let acl = gameScore.acl
If you need to refresh an object you already have with the latest data that -is in the database, you can use the `fetchInBackgroundWithBlock:` or `fetchInBackgroundWithTarget:selector:` methods to provide additional logic which will run after fetching the object. +is in the database, you can use the `fetchInBackgroundWithBlock:` or `fetchInBackgroundWithTarget:selector:` methods.