{"action":"created","comment":{"url":"https://api.github.com/repos/aws-amplify/docs/pulls/comments/230545027","pull_request_review_id":171316430,"id":230545027,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIzMDU0NTAyNw==","diff_hunk":"@@ -161,317 +161,620 @@ func downloadData() {\n \n }\n ```\n+## Using TransferUtility \n \n+This section explains how to implement upload and download functionality and a number of additional storage use cases.\n \n-## Usage with GraphQL APIs (Complex Objects)\n+Note: If you use the transfer utility multipart upload feature, take advantage of automatic cleanup features by setting up the [AbortIncompleteMultipartUpload] https://docs.aws.amazon.com/AmazonS3/latest/dev/intro-lifecycle-rules.html) action in your Amazon S3 bucket life cycle configuration.\n+{: .callout .callout--info}\n \n-Many times you might want to create logical objects that have more complex data, such as images or videos, as part of their structure. For example, you might create a Person type with a profile picture or a Post type that has an associated image. You can use AWS AppSync to model these as GraphQL types. If any of your mutations have a variable with bucket, key, region, mimeType, and localUri fields, the SDK uploads the file to Amazon S3 for you.\n+### Transfer Utility Options\n \n-Update your schema as follows to add the S3Object and S3ObjectInput types for the file, and a new mutation named CreatePostWithFileInputMutation:\n+You can use the `AWSS3TransferUtilityConfiguration` object to configure the operations of the `TransferUtility`.\n \n-```graphql\n-input CreatePostInput {\n-    author: String!\n-    title: String\n-    content: String\n-    url: String\n-    ups: Int\n-    downs: Int\n-    version: Int!\n-}\n+**isAccelerateModeEnabled**\n+The isAccelerateModeEnabled option lets you to upload and download content from a bucket that has Transfer Acceleration enabled on it. See [Transfer Acceleration](https://docs.aws.amazon.com/AmazonS3/latest/dev/transfer-acceleration.html) for information on how to enable transfer acceleration for your bucket.\n \n-input CreatePostWithFileInput {\n-    author: String!\n-    title: String\n-    content: String\n-    url: String\n-    ups: Int\n-    downs: Int\n-    file: S3ObjectInput!\n-    version: Int!\n-}\n+This option is set to false by default.\n \n-input DeletePostInput {\n-    id: ID!\n-}\n+```swift\n+//Setup credentials\n+let credentialProvider = AWSCognitoCredentialsProvider(regionType: YOUR-IDENTITY-POOL-REGION, identityPoolId: \"YOUR-IDENTITY-POOL-ID\")\n \n-type Mutation {\n-    createPost(input: CreatePostInput!): Post\n-    createPostWithFile(input: CreatePostWithFileInput!): Post\n-    updatePost(input: UpdatePostInput!): Post\n-    deletePost(input: DeletePostInput!): Post\n-}\n+//Setup the service configuration\n+let configuration = AWSServiceConfiguration(region: .USEast1, credentialsProvider: credentialProvider)\n \n-type Post {\n-    id: ID!\n-    author: String!\n-    title: String\n-    content: String\n-    url: String\n-    ups: Int\n-    downs: Int\n-    file: S3Object\n-    version: Int!\n-}\n+//Setup the transfer utility configuration\n+let tuConf = AWSS3TransferUtilityConfiguration()\n+tuConf.isAccelerateModeEnabled = true\n \n-type PostConnection {\n-    items: [Post]\n-    nextToken: String\n-}\n \n-type Query {\n-    singlePost(id: ID!): Post\n-    getPost(id: ID!): Post\n-    listPosts(filter: TablePostFilterInput, limit: Int, nextToken: String): PostConnection\n-}\n+//Register a transfer utility object\n+AWSS3TransferUtility.register(\n+    with: configuration!,\n+    transferUtilityConfiguration: tuConf,\n+    forKey: \"transfer-utility-with-advanced-options\"\n+)\n \n-type S3Object {\n-    bucket: String!\n-    key: String!\n-    region: String!\n-}\n+//Look up the transfer utility object from the registry to use for your transfers.\n+let transferUtility = AWSS3TransferUtility.s3TransferUtility(forKey: \"transfer-utility-with-advanced-options\")\n+```\n \n-input S3ObjectInput {\n-    bucket: String!\n-    key: String!\n-    region: String!\n-    localUri: String!\n-    mimeType: String!\n-}\n+**retryLimit**\n+The retryLimit option allows you to specify the number of times the TransferUtility will retry a transfer when it encounters an error during the transfer. By default, it is set to 0, which means that there will be no retries.\n \n-type Subscription {\n-    onCreatePost(\n-        id: ID,\n-        author: String,\n-        title: String,\n-        content: String,\n-        url: String\n-    ): Post\n-    @aws_subscribe(mutations: [\"createPost\"])\n-\n-    onUpdatePost(\n-        id: ID,\n-        author: String,\n-        title: String,\n-        content: String,\n-        url: String\n-    ): Post\n-    @aws_subscribe(mutations: [\"updatePost\"])\n-\n-    onDeletePost(\n-            id: ID,\n-            author: String,\n-            title: String,\n-            content: String,\n-            url: String\n-    ): Post\n-    @aws_subscribe(mutations: [\"deletePost\"])\n-}\n+```swift\n+tuConf.retryLimit = 5\n+```\n \n-input TableBooleanFilterInput {\n-    ne: Boolean\n-    eq: Boolean\n-}\n+**multiPartConcurrencyLimit**\n+The multiPartConcurrencyLimit option allows you to specify the number of parts that will be uploaded in parallel for a MultiPart upload request. By default, this is set to 5.\n \n-input TableFloatFilterInput {\n-    ne: Float\n-    eq: Float\n-    le: Float\n-    lt: Float\n-    ge: Float\n-    gt: Float\n-    contains: Float\n-    notContains: Float\n-    between: [Float]\n-}\n+```swift\n+tuConf.multiPartConcurrencyLimit = 3\n+```\n \n-input TableIDFilterInput {\n-    ne: ID\n-    eq: ID\n-    le: ID\n-    lt: ID\n-    ge: ID\n-    gt: ID\n-    contains: ID\n-    notContains: ID\n-    between: [ID]\n-    beginsWith: ID\n-}\n+**timeoutIntervalForResource** The timeoutIntervalForResource parameter allows you to specify the maximum duration the transfer can run. The default value for this parameter is 50 minutes. This value is important if you use Amazon Cognito temporary credential because it aligns with the maximum span of time that those credentials are valid.\n+\n+```swift\n+tuConf.timeoutIntervalForResource = 15*60 //15 minutes\n+```\n+\n+### Upload a File \n+\n+ The transfer utility provides methods for both single-part and multipart uploads. When a transfer uses multipart upload, the data is chunked into a number of 5 MB parts which are transferred in parallel for increased speed.\n \n-input TableIntFilterInput {\n-    ne: Int\n-    eq: Int\n-    le: Int\n-    lt: Int\n-    ge: Int\n-    gt: Int\n-    contains: Int\n-    notContains: Int\n-    between: [Int]\n+ The following example shows how to upload a file to an Amazon S3 bucket.\n+\n+```swift\n+func uploadData() {\n+\n+  let data: Data = Data() // Data to be uploaded\n+\n+  let expression = AWSS3TransferUtilityUploadExpression()\n+     expression.progressBlock = {(task, progress) in\n+        DispatchQueue.main.async(execute: {\n+          // Do something e.g. Update a progress bar.\n+       })\n+  }\n+\n+  var completionHandler: AWSS3TransferUtilityUploadCompletionHandlerBlock?\n+  completionHandler = { (task, error) -> Void in\n+     DispatchQueue.main.async(execute: {\n+        // Do something e.g. Alert a user for transfer completion.\n+        // On failed uploads, `error` contains the error object.\n+     })\n+  }\n+\n+  let transferUtility = AWSS3TransferUtility.default()\n+\n+  transferUtility.uploadData(data,\n+       bucket: \"YourBucket\",\n+       key: \"YourFileName\",\n+       contentType: \"text/plain\",\n+       expression: expression,\n+       completionHandler: completionHandler).continueWith {\n+          (task) -> AnyObject! in\n+              if let error = task.error {\n+                 print(\"Error: \\(error.localizedDescription)\")\n+              }\n+\n+              if let _ = task.result {\n+                 // Do something with uploadTask.\n+              }\n+              return nil;\n+      }\n }\n+```\n+\n+The following example shows how to upload a file to an Amazon S3 bucket using multipart uploads.\n+\n+```swift\n+func uploadData() {\n \n-input TablePostFilterInput {\n-    id: TableIDFilterInput\n-    author: TableStringFilterInput\n-    title: TableStringFilterInput\n-    content: TableStringFilterInput\n-    url: TableStringFilterInput\n-    ups: TableIntFilterInput\n-    downs: TableIntFilterInput\n-    version: TableIntFilterInput\n+   let data: Data = Data() // Data to be uploaded\n+\n+   let expression = AWSS3TransferUtilityMultiPartUploadExpression()\n+      expression.progressBlock = {(task, progress) in\n+         DispatchQueue.main.async(execute: {\n+           // Do something e.g. Update a progress bar.\n+        })\n+   }\n+\n+   var completionHandler: AWSS3TransferUtilityMultiPartUploadCompletionHandlerBlock\n+   completionHandler = { (task, error) -> Void in\n+      DispatchQueue.main.async(execute: {\n+         // Do something e.g. Alert a user for transfer completion.\n+         // On failed uploads, `error` contains the error object.\n+      })\n+   }\n+\n+   let transferUtility = AWSS3TransferUtility.default()\n+\n+   transferUtility.uploadUsingMultiPart(data:data,\n+        bucket: \"YourBucket\",\n+        key: \"YourFileName\",\n+        contentType: \"text/plain\",\n+        expression: expression,\n+        completionHandler: completionHandler).continueWith {\n+           (task) -> AnyObject! in\n+               if let error = task.error {\n+                  print(\"Error: \\(error.localizedDescription)\")\n+               }\n+\n+               if let _ = task.result {\n+                  // Do something with uploadTask.\n+               }\n+               return nil;\n+       }\n }\n+```\n+\n+### Download a File \n \n-input TableStringFilterInput {\n-    ne: String\n-    eq: String\n-    le: String\n-    lt: String\n-    ge: String\n-    gt: String\n-    contains: String\n-    notContains: String\n-    between: [String]\n-    beginsWith: String\n+The following example shows how to download a file from an Amazon S3 bucket.\n+\n+```swift\n+func downloadData() {\n+   let expression = AWSS3TransferUtilityDownloadExpression()\n+   expression.progressBlock = {(task, progress) in DispatchQueue.main.async(execute: {\n+      // Do something e.g. Update a progress bar.\n+      })\n+   }\n+\n+   var completionHandler: AWSS3TransferUtilityDownloadCompletionHandlerBlock?\n+   completionHandler = { (task, URL, data, error) -> Void in\n+      DispatchQueue.main.async(execute: {\n+      // Do something e.g. Alert a user for transfer completion.\n+      // On failed downloads, `error` contains the error object.\n+      })\n+   }\n+\n+   let transferUtility = AWSS3TransferUtility.default()\n+   transferUtility.downloadData(\n+         fromBucket: \"YourBucket\",\n+         key: \"YourFileName\",\n+         expression: expression,\n+         completionHandler: completionHandler\n+         ).continueWith {\n+            (task) -> AnyObject! in if let error = task.error {\n+               print(\"Error: \\(error.localizedDescription)\")\n+            }\n+\n+            if let _ = task.result {\n+              // Do something with downloadTask.\n+\n+            }\n+            return nil;\n+        }\n }\n+```\n+\n+### Track Transfer Progress\n+\n+Implement progress and completion actions for transfers by passing a `progressBlock` and `completionHandler` blocks to the call to `AWSS3TransferUtility` that initiates the transfer.\n+\n+The following example of initiating a data upload, shows how progress and completion handling is typically done for all transfers. The `AWSS3TransferUtilityUploadExpression`, `AWSS3TransferUtilityMultiPartUploadExpression` and `AWSS3TransferUtilityDownloadExpression` contains the `progressBlock` that gives you the progress of the transfer which you can use to update the progress bar.\n+\n+```swift\n+// For example, create a progress bar\n+let progressView: UIProgressView! = UIProgressView()\n+progressView.progress = 0.0;\n+\n+let data = Data() // The data to upload\n \n-input UpdatePostInput {\n-    id: ID!\n-    author: String\n-    title: String\n-    content: String\n-    url: String\n-    ups: Int\n-    downs: Int\n-    version: Int\n+let expression = AWSS3TransferUtilityUploadExpression()\n+expression.progressBlock = {(task, progress) in DispatchQueue.main.async(execute: {\n+        // Update a progress bar.\n+        progressView.progress = Float(progress.fractionCompleted)\n+    })\n }\n \n-schema {\n-    query: Query\n-    mutation: Mutation\n-    subscription: Subscription\n+let completionHandler: AWSS3TransferUtilityUploadCompletionHandlerBlock = { (task, error) -> Void in DispatchQueue.main.async(execute: {\n+        if let error = error {\n+            NSLog(\"Failed with error: \\(error)\")\n+        }\n+        else if(self.progressView.progress != 1.0) {\n+            NSLog(\"Error: Failed.\")\n+        } else {\n+            NSLog(\"Success.\")\n+        }\n+    })\n }\n+\n+var refUploadTask: AWSS3TransferUtilityTask?\n+let transferUtility = AWSS3TransferUtility.default()\n+transferUtility.uploadData(data,\n+           bucket: \"S3BucketName\",\n+           key: \"S3UploadKeyName\",\n+           contentType: \"text/plain\",\n+           expression: expression,\n+           completionHandler: completionHandler).continueWith { (task) -> AnyObject! in\n+                if let error = task.error {\n+                    print(\"Error: \\(error.localizedDescription)\")\n+                }\n+\n+                if let uploadTask = task.result {\n+                    // Do something with uploadTask.\n+                    // The uploadTask can be used to pause/resume/cancel the operation, retrieve task specific information\n+                    refUploadTask = uploadTask\n+                }\n+\n+                return nil;\n+            }\n ```\n \n-**Note:** If you're using the sample schema specified at the start of this documentation, you can replace your schema with the previous schema.\n+### Pause a Transfer\n \n-Next, you need to add a resolver for createPostWithFile mutation. You can do that from the AWS AppSync console by selecting PostsTable as the data source and the following mapping templates.\n+To pause a transfer, retain references to `AWSS3TransferUtilityUploadTask`, `AWSS3TransferUtilityMultiPartUploadTask` or `AWSS3TransferUtilityDownloadTask` .\n \n-**Request Mapping Template**\n+As described in the previous section :ref:`native-track-progress-and-completion-of-a-transfer`, the variable `refUploadTask` is a reference to the `UploadTask` object that is retrieved from the `continueWith` block of an upload operation that is invoked through `transferUtility.uploadData`.\n \n+To pause a transfer, use the `suspend` method:\n+\n+```swift\n+refUploadTask.suspend()\n ```\n-{\n-    \"version\": \"2017-02-28\",\n-    \"operation\": \"PutItem\",\n-    \"key\": {\n-        \"id\": $util.dynamodb.toDynamoDBJson($util.autoId()),\n-    },\n-    #set( $attribs = $util.dynamodb.toMapValues($ctx.args.input) )\n-    #if($util.isNull($ctx.args.input.file.version))\n-        #set( $attribs.file = $util.dynamodb.toS3Object($ctx.args.input.file.key, $ctx.args.input.file.bucket, $ctx.args.input.file.region))\n-    #else\n-        #set( $attribs.file = $util.dynamodb.toS3Object($ctx.args.input.file.key, $ctx.args.input.file.bucket, $ctx.args.input.file.region, $ctx.args.input.file.version))\n-    #end\n-    \"attributeValues\": $util.toJson($attribs),\n-    \"condition\": {\n-        \"expression\": \"attribute_not_exists(#id)\",\n-        \"expressionNames\": {\n-            \"#id\": \"id\",\n-        },\n-    },\n-}\n-```\n-**Response Mapping Template**\n \n+### Resume a Transfer\n+\n+To resume a transfer, use the `resume` method:\n+\n+```swift\n+refUploadTask.resume()\n ```\n-$util.toJson($context.result)\n+\n+### Cancel a Transfer\n+\n+To cancel a transfer, use the `cancel` method:\n+\n+```swift\n+refUploadTask.cancel()\n ```\n \n-After you have a resolver for the mutation, to ensure that our S3 Complex Object details are fetched correctly during any query operation, add a resolver for the file field of Post. You can do that from the AWS AppSync console by using the following mapping templates.\n+### Background Transfers\n+\n+All transfers performed by TransferUtility for iOS happen in the background using NSURLSession background sessions. Once a transfer is initiated, it will continue regardless of whether the initiating app moves to the foreground, moves to the background, is suspended, or is terminated by the system. Note that this doesn't apply when the app is force-closed. Transfers initiated by apps that are force-closed are terminated by the operating system at the NSURLSession level. For regular uploads and downloads, you will have to re-initiate the transfer. For multi-part uploads, the TransferUtility will resume automatically and will continue the transfer.  \n \n-**Request Mapping Template**\n+To wake an app that is suspended or in the background when a transfer it has initiated is completed, implement the handleEventsForBackgroundURLSession method in the AppDelegate and have it call the interceptApplication method of AWSS3TransferUtility as follows. \n \n+```swift\n+func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void) {\n+    // Store the completion handler.\n+    AWSS3TransferUtility.interceptApplication(application, handleEventsForBackgroundURLSession: identifier, completionHandler: completionHandler)\n+}\n ```\n-{\n-    \"version\" : \"2017-02-28\",\n-    \"operation\" : \"Query\",\n-    \"query\" : {\n-        ## Provide a query expression. **\n-        \"expression\": \"id = :id\",\n-        \"expressionValues\" : {\n-            \":id\" : {\n-                \"S\" : \"${ctx.args.id}\"\n-            }\n-        }\n+\n+### Managing Transfers When an App Restarts\n+\n+When an app that has initiated a transfer restarts (if it has been terminated by the system and not force-closed), the transfer may still be in progress or have completed. To make the restarting app aware of the status of transfers, instantiate the transfer utility using the ``AWSS3TransferUtility.s3TransferUtility(forKey: \"YOUR_KEY\")`` method. AWSS3TransferUtility uses the key to uniquely identify the NSURLSession of the transfers initiated by the app, so it is important to always use the same identifier. AWSS3TransferUtility will automatically reconnect to the transfers that were in progress the last time the app was running.\n+\n+Though it can be called anywhere in the app, we recommend that you instantiate the AWSS3TransferUtility in the ``appDidFinishLaunching`` lifecycle method. \n+\n+### Manage a Transfer when a Suspended App Returns to the Foreground**\n+\n+When an app that has initiated a transfer becomes suspended and then returns to the foreground, the transfer may still be in progress or may have completed. In both cases, use the following code to re-establish the progress and completion handler blocks of the app.\n+\n+```swift\n+let uploadTasks = transferUtility.getUploadTasks().result\n+  for task in uploadTasks! {\n+       task.setCompletionHandler(completionHandler!)\n+       task.setProgressBlock(progressBlock!)\n+}\n+\n+\n+let downloadTasks = transferUtility.getDownloadTasks().result\n+   for task in downloadTasks! {\n+       task.setCompletionHandler(completionHandler!)\n+       task.setProgressBlock(progressBlock!)\n     }\n }\n+\n+\n+let multiPartUploadTasks = transferUtility.getMultiPartUploadTasks().result\n+    for task in multiPartUploadTasks! {\n+        task.setCompletionHandler(completionHandler!)\n+        task.setProgressBlock(progressBlock!)\n+\n+ }\n+```\n+\n+### Transfer with Object Metadata\n+\n+The `AWSS3TransferUtilityUploadExpression` and `AWSS3TransferUtilityMultiPartUploadExpression` classes contain the method `setValue:forRequestHeader` where you can pass in metadata to Amazon S3. This example demonstrates passing in the Server-side Encryption Algorithm as a request header in uploading data to S3 using MultiPart.\n+\n+```swift\n+\n+let data: Data = Data() // The data to upload\n+\n+let uploadExpression = AWSS3TransferUtilityMultiPartUploadExpression()\n+uploadExpression.setValue(\"AES256\", forRequestHeader: \"x-amz-server-side-encryption-customer-algorithm\")\n+uploadExpression.progressBlock = {(task, progress) in DispatchQueue.main.async(execute: {\n+        // Do something e.g. Update a progress bar.\n+    })\n+}\n+\n+let transferUtility = AWSS3TransferUtility.default()\n+\n+transferUtility.uploadUsingMultiPart(data:data,\n+            bucket: \"S3BucketName\",\n+            key: \"S3UploadKeyName\",\n+            contentType: \"text/plain\",\n+            expression: uploadExpression,\n+            completionHandler: nil).continueWith { (task) -> AnyObject! in\n+                if let error = task.error {\n+                    print(\"Error: \\(error.localizedDescription)\")\n+                }\n+\n+                return nil;\n+            }\n ```\n \n-**Response Mapping Template**\n+### Transfer with Access Control List\n+\n+To upload a file and specify permissions for it, you can use predefined grants, also known as canned ACLs. The following code shows you how to setup a file with publicRead access using the AWSS3 client.\n \n+\n+```swift\n+//Create a AWSS3PutObjectRequest object and setup the content, bucketname, key on it.\n+//use the .acl method to specify the ACL for the file\n+let s3: AWSS3 = AWSS3.default()\n+\n+let putObjectRequest: AWSS3PutObjectRequest! = AWSS3PutObjectRequest()\n+let content = \"testObjectData\"\n+putObjectRequest.acl = AWSS3ObjectCannedACL.publicRead\n+putObjectRequest.bucket = \"bucket name\"\n+putObjectRequest.key = \"file name\"\n+putObjectRequest.body = content\n+putObjectRequest.contentLength = content.count as NSNumber\n+putObjectRequest.contentType = \"text/plain\";\n+\n+s3.putObject(putObjectRequest, completionHandler: { (putObjectOutput:AWSS3PutObjectOutput? , error: Error? ) in\n+    if let output = putObjectOutput {\n+        print (output)\n+    }\n+\n+    if let error = error {\n+        print (error)\n+    }\n+})\n ```\n-$util.toJson($util.dynamodb.fromS3ObjectJson($context.source.file))\n+\n+### Downloading to a File\n+\n+```swift\n+let fileURL = // The file URL of the download destination.\n+\n+let transferUtility = AWSS3TransferUtility.default()","path":"ios/storage.md","position":633,"original_position":633,"commit_id":"bb2dda95ba305dedb922eea10a1ab518cd988733","original_commit_id":"bb2dda95ba305dedb922eea10a1ab518cd988733","user":{"login":"undefobj","id":4294295,"node_id":"MDQ6VXNlcjQyOTQyOTU=","avatar_url":"https://avatars0.githubusercontent.com/u/4294295?v=4","gravatar_id":"","url":"https://api.github.com/users/undefobj","html_url":"https://github.com/undefobj","followers_url":"https://api.github.com/users/undefobj/followers","following_url":"https://api.github.com/users/undefobj/following{/other_user}","gists_url":"https://api.github.com/users/undefobj/gists{/gist_id}","starred_url":"https://api.github.com/users/undefobj/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/undefobj/subscriptions","organizations_url":"https://api.github.com/users/undefobj/orgs","repos_url":"https://api.github.com/users/undefobj/repos","events_url":"https://api.github.com/users/undefobj/events{/privacy}","received_events_url":"https://api.github.com/users/undefobj/received_events","type":"User","site_admin":false},"body":"Isn't this redundant with the other Download examples above?","created_at":"2018-11-03T04:42:55Z","updated_at":"2018-11-03T04:42:55Z","html_url":"https://github.com/aws-amplify/docs/pull/89#discussion_r230545027","pull_request_url":"https://api.github.com/repos/aws-amplify/docs/pulls/89","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/aws-amplify/docs/pulls/comments/230545027"},"html":{"href":"https://github.com/aws-amplify/docs/pull/89#discussion_r230545027"},"pull_request":{"href":"https://api.github.com/repos/aws-amplify/docs/pulls/89"}}},"pull_request":{"url":"https://api.github.com/repos/aws-amplify/docs/pulls/89","id":228083447,"node_id":"MDExOlB1bGxSZXF1ZXN0MjI4MDgzNDQ3","html_url":"https://github.com/aws-amplify/docs/pull/89","diff_url":"https://github.com/aws-amplify/docs/pull/89.diff","patch_url":"https://github.com/aws-amplify/docs/pull/89.patch","issue_url":"https://api.github.com/repos/aws-amplify/docs/issues/89","number":89,"state":"open","locked":false,"title":"Updates to ios Storage section","user":{"login":"cbommas","id":5359504,"node_id":"MDQ6VXNlcjUzNTk1MDQ=","avatar_url":"https://avatars1.githubusercontent.com/u/5359504?v=4","gravatar_id":"","url":"https://api.github.com/users/cbommas","html_url":"https://github.com/cbommas","followers_url":"https://api.github.com/users/cbommas/followers","following_url":"https://api.github.com/users/cbommas/following{/other_user}","gists_url":"https://api.github.com/users/cbommas/gists{/gist_id}","starred_url":"https://api.github.com/users/cbommas/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cbommas/subscriptions","organizations_url":"https://api.github.com/users/cbommas/orgs","repos_url":"https://api.github.com/users/cbommas/repos","events_url":"https://api.github.com/users/cbommas/events{/privacy}","received_events_url":"https://api.github.com/users/cbommas/received_events","type":"User","site_admin":false},"body":"","created_at":"2018-11-02T23:41:24Z","updated_at":"2018-11-03T04:42:55Z","closed_at":null,"merged_at":null,"merge_commit_sha":"4711c0de3ef623f9218e50d2d75d1eade9f0749b","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/aws-amplify/docs/pulls/89/commits","review_comments_url":"https://api.github.com/repos/aws-amplify/docs/pulls/89/comments","review_comment_url":"https://api.github.com/repos/aws-amplify/docs/pulls/comments{/number}","comments_url":"https://api.github.com/repos/aws-amplify/docs/issues/89/comments","statuses_url":"https://api.github.com/repos/aws-amplify/docs/statuses/bb2dda95ba305dedb922eea10a1ab518cd988733","head":{"label":"cbommas:storage-ios-updates","ref":"storage-ios-updates","sha":"bb2dda95ba305dedb922eea10a1ab518cd988733","user":{"login":"cbommas","id":5359504,"node_id":"MDQ6VXNlcjUzNTk1MDQ=","avatar_url":"https://avatars1.githubusercontent.com/u/5359504?v=4","gravatar_id":"","url":"https://api.github.com/users/cbommas","html_url":"https://github.com/cbommas","followers_url":"https://api.github.com/users/cbommas/followers","following_url":"https://api.github.com/users/cbommas/following{/other_user}","gists_url":"https://api.github.com/users/cbommas/gists{/gist_id}","starred_url":"https://api.github.com/users/cbommas/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cbommas/subscriptions","organizations_url":"https://api.github.com/users/cbommas/orgs","repos_url":"https://api.github.com/users/cbommas/repos","events_url":"https://api.github.com/users/cbommas/events{/privacy}","received_events_url":"https://api.github.com/users/cbommas/received_events","type":"User","site_admin":false},"repo":{"id":155931988,"node_id":"MDEwOlJlcG9zaXRvcnkxNTU5MzE5ODg=","name":"docs","full_name":"cbommas/docs","private":false,"owner":{"login":"cbommas","id":5359504,"node_id":"MDQ6VXNlcjUzNTk1MDQ=","avatar_url":"https://avatars1.githubusercontent.com/u/5359504?v=4","gravatar_id":"","url":"https://api.github.com/users/cbommas","html_url":"https://github.com/cbommas","followers_url":"https://api.github.com/users/cbommas/followers","following_url":"https://api.github.com/users/cbommas/following{/other_user}","gists_url":"https://api.github.com/users/cbommas/gists{/gist_id}","starred_url":"https://api.github.com/users/cbommas/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cbommas/subscriptions","organizations_url":"https://api.github.com/users/cbommas/orgs","repos_url":"https://api.github.com/users/cbommas/repos","events_url":"https://api.github.com/users/cbommas/events{/privacy}","received_events_url":"https://api.github.com/users/cbommas/received_events","type":"User","site_admin":false},"html_url":"https://github.com/cbommas/docs","description":"AWS Amplify Documentation","fork":true,"url":"https://api.github.com/repos/cbommas/docs","forks_url":"https://api.github.com/repos/cbommas/docs/forks","keys_url":"https://api.github.com/repos/cbommas/docs/keys{/key_id}","collaborators_url":"https://api.github.com/repos/cbommas/docs/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/cbommas/docs/teams","hooks_url":"https://api.github.com/repos/cbommas/docs/hooks","issue_events_url":"https://api.github.com/repos/cbommas/docs/issues/events{/number}","events_url":"https://api.github.com/repos/cbommas/docs/events","assignees_url":"https://api.github.com/repos/cbommas/docs/assignees{/user}","branches_url":"https://api.github.com/repos/cbommas/docs/branches{/branch}","tags_url":"https://api.github.com/repos/cbommas/docs/tags","blobs_url":"https://api.github.com/repos/cbommas/docs/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/cbommas/docs/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/cbommas/docs/git/refs{/sha}","trees_url":"https://api.github.com/repos/cbommas/docs/git/trees{/sha}","statuses_url":"https://api.github.com/repos/cbommas/docs/statuses/{sha}","languages_url":"https://api.github.com/repos/cbommas/docs/languages","stargazers_url":"https://api.github.com/repos/cbommas/docs/stargazers","contributors_url":"https://api.github.com/repos/cbommas/docs/contributors","subscribers_url":"https://api.github.com/repos/cbommas/docs/subscribers","subscription_url":"https://api.github.com/repos/cbommas/docs/subscription","commits_url":"https://api.github.com/repos/cbommas/docs/commits{/sha}","git_commits_url":"https://api.github.com/repos/cbommas/docs/git/commits{/sha}","comments_url":"https://api.github.com/repos/cbommas/docs/comments{/number}","issue_comment_url":"https://api.github.com/repos/cbommas/docs/issues/comments{/number}","contents_url":"https://api.github.com/repos/cbommas/docs/contents/{+path}","compare_url":"https://api.github.com/repos/cbommas/docs/compare/{base}...{head}","merges_url":"https://api.github.com/repos/cbommas/docs/merges","archive_url":"https://api.github.com/repos/cbommas/docs/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/cbommas/docs/downloads","issues_url":"https://api.github.com/repos/cbommas/docs/issues{/number}","pulls_url":"https://api.github.com/repos/cbommas/docs/pulls{/number}","milestones_url":"https://api.github.com/repos/cbommas/docs/milestones{/number}","notifications_url":"https://api.github.com/repos/cbommas/docs/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/cbommas/docs/labels{/name}","releases_url":"https://api.github.com/repos/cbommas/docs/releases{/id}","deployments_url":"https://api.github.com/repos/cbommas/docs/deployments","created_at":"2018-11-02T23:32:52Z","updated_at":"2018-11-02T23:32:55Z","pushed_at":"2018-11-03T00:00:56Z","git_url":"git://github.com/cbommas/docs.git","ssh_url":"git@github.com:cbommas/docs.git","clone_url":"https://github.com/cbommas/docs.git","svn_url":"https://github.com/cbommas/docs","homepage":"https://aws-amplify.github.io/docs","size":32071,"stargazers_count":0,"watchers_count":0,"language":"HTML","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":null,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"aws-amplify:master","ref":"master","sha":"03ded8d2d69d2de0786f722c6e54b33377c5307a","user":{"login":"aws-amplify","id":41077760,"node_id":"MDEyOk9yZ2FuaXphdGlvbjQxMDc3NzYw","avatar_url":"https://avatars0.githubusercontent.com/u/41077760?v=4","gravatar_id":"","url":"https://api.github.com/users/aws-amplify","html_url":"https://github.com/aws-amplify","followers_url":"https://api.github.com/users/aws-amplify/followers","following_url":"https://api.github.com/users/aws-amplify/following{/other_user}","gists_url":"https://api.github.com/users/aws-amplify/gists{/gist_id}","starred_url":"https://api.github.com/users/aws-amplify/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aws-amplify/subscriptions","organizations_url":"https://api.github.com/users/aws-amplify/orgs","repos_url":"https://api.github.com/users/aws-amplify/repos","events_url":"https://api.github.com/users/aws-amplify/events{/privacy}","received_events_url":"https://api.github.com/users/aws-amplify/received_events","type":"Organization","site_admin":false},"repo":{"id":149512426,"node_id":"MDEwOlJlcG9zaXRvcnkxNDk1MTI0MjY=","name":"docs","full_name":"aws-amplify/docs","private":false,"owner":{"login":"aws-amplify","id":41077760,"node_id":"MDEyOk9yZ2FuaXphdGlvbjQxMDc3NzYw","avatar_url":"https://avatars0.githubusercontent.com/u/41077760?v=4","gravatar_id":"","url":"https://api.github.com/users/aws-amplify","html_url":"https://github.com/aws-amplify","followers_url":"https://api.github.com/users/aws-amplify/followers","following_url":"https://api.github.com/users/aws-amplify/following{/other_user}","gists_url":"https://api.github.com/users/aws-amplify/gists{/gist_id}","starred_url":"https://api.github.com/users/aws-amplify/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aws-amplify/subscriptions","organizations_url":"https://api.github.com/users/aws-amplify/orgs","repos_url":"https://api.github.com/users/aws-amplify/repos","events_url":"https://api.github.com/users/aws-amplify/events{/privacy}","received_events_url":"https://api.github.com/users/aws-amplify/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/aws-amplify/docs","description":"AWS Amplify Documentation","fork":false,"url":"https://api.github.com/repos/aws-amplify/docs","forks_url":"https://api.github.com/repos/aws-amplify/docs/forks","keys_url":"https://api.github.com/repos/aws-amplify/docs/keys{/key_id}","collaborators_url":"https://api.github.com/repos/aws-amplify/docs/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/aws-amplify/docs/teams","hooks_url":"https://api.github.com/repos/aws-amplify/docs/hooks","issue_events_url":"https://api.github.com/repos/aws-amplify/docs/issues/events{/number}","events_url":"https://api.github.com/repos/aws-amplify/docs/events","assignees_url":"https://api.github.com/repos/aws-amplify/docs/assignees{/user}","branches_url":"https://api.github.com/repos/aws-amplify/docs/branches{/branch}","tags_url":"https://api.github.com/repos/aws-amplify/docs/tags","blobs_url":"https://api.github.com/repos/aws-amplify/docs/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/aws-amplify/docs/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/aws-amplify/docs/git/refs{/sha}","trees_url":"https://api.github.com/repos/aws-amplify/docs/git/trees{/sha}","statuses_url":"https://api.github.com/repos/aws-amplify/docs/statuses/{sha}","languages_url":"https://api.github.com/repos/aws-amplify/docs/languages","stargazers_url":"https://api.github.com/repos/aws-amplify/docs/stargazers","contributors_url":"https://api.github.com/repos/aws-amplify/docs/contributors","subscribers_url":"https://api.github.com/repos/aws-amplify/docs/subscribers","subscription_url":"https://api.github.com/repos/aws-amplify/docs/subscription","commits_url":"https://api.github.com/repos/aws-amplify/docs/commits{/sha}","git_commits_url":"https://api.github.com/repos/aws-amplify/docs/git/commits{/sha}","comments_url":"https://api.github.com/repos/aws-amplify/docs/comments{/number}","issue_comment_url":"https://api.github.com/repos/aws-amplify/docs/issues/comments{/number}","contents_url":"https://api.github.com/repos/aws-amplify/docs/contents/{+path}","compare_url":"https://api.github.com/repos/aws-amplify/docs/compare/{base}...{head}","merges_url":"https://api.github.com/repos/aws-amplify/docs/merges","archive_url":"https://api.github.com/repos/aws-amplify/docs/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/aws-amplify/docs/downloads","issues_url":"https://api.github.com/repos/aws-amplify/docs/issues{/number}","pulls_url":"https://api.github.com/repos/aws-amplify/docs/pulls{/number}","milestones_url":"https://api.github.com/repos/aws-amplify/docs/milestones{/number}","notifications_url":"https://api.github.com/repos/aws-amplify/docs/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/aws-amplify/docs/labels{/name}","releases_url":"https://api.github.com/repos/aws-amplify/docs/releases{/id}","deployments_url":"https://api.github.com/repos/aws-amplify/docs/deployments","created_at":"2018-09-19T21:08:59Z","updated_at":"2018-11-02T21:22:37Z","pushed_at":"2018-11-03T00:00:58Z","git_url":"git://github.com/aws-amplify/docs.git","ssh_url":"git@github.com:aws-amplify/docs.git","clone_url":"https://github.com/aws-amplify/docs.git","svn_url":"https://github.com/aws-amplify/docs","homepage":"https://aws-amplify.github.io/docs","size":32060,"stargazers_count":6,"watchers_count":6,"language":"HTML","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":46,"mirror_url":null,"archived":false,"open_issues_count":16,"license":null,"forks":46,"open_issues":16,"watchers":6,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/aws-amplify/docs/pulls/89"},"html":{"href":"https://github.com/aws-amplify/docs/pull/89"},"issue":{"href":"https://api.github.com/repos/aws-amplify/docs/issues/89"},"comments":{"href":"https://api.github.com/repos/aws-amplify/docs/issues/89/comments"},"review_comments":{"href":"https://api.github.com/repos/aws-amplify/docs/pulls/89/comments"},"review_comment":{"href":"https://api.github.com/repos/aws-amplify/docs/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/aws-amplify/docs/pulls/89/commits"},"statuses":{"href":"https://api.github.com/repos/aws-amplify/docs/statuses/bb2dda95ba305dedb922eea10a1ab518cd988733"}},"author_association":"NONE"}}
{"actor":{"display_login":"undefobj"}}