Skip to content

Commit 9ab5271

Browse files
authoredSep 13, 2022
feat: add ParseFileTransferable protocol for direct file uploads (#410)
* feat: add ParseFileTransferable protocol for direct uploads to file storage * nit
1 parent 378b81a commit 9ab5271

13 files changed

+154
-26
lines changed
 

‎CHANGELOG.md

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
# Parse-Swift Changelog
22

33
### main
4-
[Full Changelog](https://github.com/parse-community/Parse-Swift/compare/4.10.0...main)
4+
[Full Changelog](https://github.com/parse-community/Parse-Swift/compare/4.12.0...main)
55
* _Contributing to this repo? Add info about your change here to be included in the next release_
66

7+
### 4.12.0
8+
[Full Changelog](https://github.com/parse-community/Parse-Swift/compare/4.11.0...4.12.0)
9+
710
__New features__
11+
- Add the ParseFileTransferable protocol for overriding the default transfer behavior for ParseFile's. Allows for direct uploads to other file storage
12+
providers ([#408](https://github.com/parse-community/Parse-Swift/pull/408)), thanks to [Corey Baker](https://github.com/cbaker6).
813
- Add the become method to ParseInstallation which allows any ParseInstallation to be copied to the current installation. This method can be used to migrate any ParseInstallation to the current installation in the Swift SDK ([#407](https://github.com/parse-community/Parse-Swift/pull/407)), thanks to [Corey Baker](https://github.com/cbaker6).
914

1015
__Fixes__

‎ParseSwift.xcodeproj/project.pbxproj

+20
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,14 @@
319319
704C886D28BE69A8008E6B01 /* ParseConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 704C886B28BE69A8008E6B01 /* ParseConfiguration.swift */; };
320320
704C886E28BE69A8008E6B01 /* ParseConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 704C886B28BE69A8008E6B01 /* ParseConfiguration.swift */; };
321321
704C886F28BE69A8008E6B01 /* ParseConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 704C886B28BE69A8008E6B01 /* ParseConfiguration.swift */; };
322+
704E781728CFD8A00075F952 /* ParseFileTransferable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 704E781628CFD8A00075F952 /* ParseFileTransferable.swift */; };
323+
704E781828CFD8A00075F952 /* ParseFileTransferable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 704E781628CFD8A00075F952 /* ParseFileTransferable.swift */; };
324+
704E781928CFD8A00075F952 /* ParseFileTransferable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 704E781628CFD8A00075F952 /* ParseFileTransferable.swift */; };
325+
704E781A28CFD8A00075F952 /* ParseFileTransferable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 704E781628CFD8A00075F952 /* ParseFileTransferable.swift */; };
326+
704E781C28CFFAF80075F952 /* ParseFileDefaultTransfer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 704E781B28CFFAF80075F952 /* ParseFileDefaultTransfer.swift */; };
327+
704E781D28CFFAF80075F952 /* ParseFileDefaultTransfer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 704E781B28CFFAF80075F952 /* ParseFileDefaultTransfer.swift */; };
328+
704E781E28CFFAF80075F952 /* ParseFileDefaultTransfer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 704E781B28CFFAF80075F952 /* ParseFileDefaultTransfer.swift */; };
329+
704E781F28CFFAF80075F952 /* ParseFileDefaultTransfer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 704E781B28CFFAF80075F952 /* ParseFileDefaultTransfer.swift */; };
322330
705025992842FD3B008D6624 /* ParseCLPTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 705025982842FD3B008D6624 /* ParseCLPTests.swift */; };
323331
7050259A2842FD3B008D6624 /* ParseCLPTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 705025982842FD3B008D6624 /* ParseCLPTests.swift */; };
324332
7050259B2842FD3B008D6624 /* ParseCLPTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 705025982842FD3B008D6624 /* ParseCLPTests.swift */; };
@@ -1234,6 +1242,8 @@
12341242
7045769726BD917500F86F71 /* Query+async.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Query+async.swift"; sourceTree = "<group>"; };
12351243
7045769C26BD934000F86F71 /* ParseFile+async.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ParseFile+async.swift"; sourceTree = "<group>"; };
12361244
704C886B28BE69A8008E6B01 /* ParseConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParseConfiguration.swift; sourceTree = "<group>"; };
1245+
704E781628CFD8A00075F952 /* ParseFileTransferable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParseFileTransferable.swift; sourceTree = "<group>"; };
1246+
704E781B28CFFAF80075F952 /* ParseFileDefaultTransfer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParseFileDefaultTransfer.swift; sourceTree = "<group>"; };
12371247
705025982842FD3B008D6624 /* ParseCLPTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParseCLPTests.swift; sourceTree = "<group>"; };
12381248
7050259C2843F0CF008D6624 /* ParseSchemaAsyncTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParseSchemaAsyncTests.swift; sourceTree = "<group>"; };
12391249
705025A02843F0E7008D6624 /* ParseSchemaCombineTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParseSchemaCombineTests.swift; sourceTree = "<group>"; };
@@ -1790,6 +1800,7 @@
17901800
703B090626BD9764005A112F /* ParseCloud+async.swift */,
17911801
7044C17425C4ECFF0011F6E7 /* ParseCloud+combine.swift */,
17921802
70647E9B259E3A9A004C1004 /* ParseEncodable.swift */,
1803+
704E781628CFD8A00075F952 /* ParseFileTransferable.swift */,
17931804
70CE0AB6285A83B100DAEA86 /* ParseHookable.swift */,
17941805
70385E752858E1000084D306 /* ParseHookFunctionable.swift */,
17951806
70CE0AC0285FD59B00DAEA86 /* ParseHookFunctionable+async.swift */,
@@ -2124,6 +2135,7 @@
21242135
F97B45C124D9C6F200F4A88B /* ParseFile.swift */,
21252136
7045769C26BD934000F86F71 /* ParseFile+async.swift */,
21262137
7044C19025C4F5B60011F6E7 /* ParseFile+combine.swift */,
2138+
704E781B28CFFAF80075F952 /* ParseFileDefaultTransfer.swift */,
21272139
F97B45BC24D9C6F200F4A88B /* ParseGeoPoint.swift */,
21282140
70F79A182639CE6F00731C46 /* ParseHealth.swift */,
21292141
703B08FC26BD953B005A112F /* ParseHealth+async.swift */,
@@ -2707,6 +2719,7 @@
27072719
705025E628514F36008D6624 /* ParsePushPayloadAny.swift in Sources */,
27082720
709A148228395ED100BF85E5 /* ParseSchema+async.swift in Sources */,
27092721
705025D1284CFCDE008D6624 /* ParsePushAppleAlert.swift in Sources */,
2722+
704E781C28CFFAF80075F952 /* ParseFileDefaultTransfer.swift in Sources */,
27102723
7045769826BD917500F86F71 /* Query+async.swift in Sources */,
27112724
703B094E26BF47E3005A112F /* ParseTwitter+combine.swift in Sources */,
27122725
70386A3825D998D90048EC1B /* ParseLDAP.swift in Sources */,
@@ -2765,6 +2778,7 @@
27652778
707A3C2025B14BD0000D215C /* ParseApple.swift in Sources */,
27662779
703B095D26BF481F005A112F /* ParseFacebook+async.swift in Sources */,
27672780
709A147D283949D100BF85E5 /* ParseSchema.swift in Sources */,
2781+
704E781728CFD8A00075F952 /* ParseFileTransferable.swift in Sources */,
27682782
F97B462224D9C6F200F4A88B /* ParseKeyValueStore.swift in Sources */,
27692783
703B090226BD9652005A112F /* ParseAnalytics+async.swift in Sources */,
27702784
703B093F26BF47AC005A112F /* ParseApple+async.swift in Sources */,
@@ -3016,6 +3030,7 @@
30163030
705025E728514F36008D6624 /* ParsePushPayloadAny.swift in Sources */,
30173031
709A148328395ED100BF85E5 /* ParseSchema+async.swift in Sources */,
30183032
705025D2284CFCDE008D6624 /* ParsePushAppleAlert.swift in Sources */,
3033+
704E781D28CFFAF80075F952 /* ParseFileDefaultTransfer.swift in Sources */,
30193034
703B094F26BF47E3005A112F /* ParseTwitter+combine.swift in Sources */,
30203035
70386A3925D998D90048EC1B /* ParseLDAP.swift in Sources */,
30213036
700395F325A171320052CB31 /* LiveQueryable.swift in Sources */,
@@ -3074,6 +3089,7 @@
30743089
703B095E26BF481F005A112F /* ParseFacebook+async.swift in Sources */,
30753090
F97B462324D9C6F200F4A88B /* ParseKeyValueStore.swift in Sources */,
30763091
709A147E283949D100BF85E5 /* ParseSchema.swift in Sources */,
3092+
704E781828CFD8A00075F952 /* ParseFileTransferable.swift in Sources */,
30773093
703B090326BD9652005A112F /* ParseAnalytics+async.swift in Sources */,
30783094
703B094026BF47AC005A112F /* ParseApple+async.swift in Sources */,
30793095
F97B45E724D9C6F200F4A88B /* Query.swift in Sources */,
@@ -3457,6 +3473,7 @@
34573473
705025E928514F36008D6624 /* ParsePushPayloadAny.swift in Sources */,
34583474
709A148528395ED100BF85E5 /* ParseSchema+async.swift in Sources */,
34593475
705025D4284CFCDE008D6624 /* ParsePushAppleAlert.swift in Sources */,
3476+
704E781F28CFFAF80075F952 /* ParseFileDefaultTransfer.swift in Sources */,
34603477
7045769B26BD917500F86F71 /* Query+async.swift in Sources */,
34613478
703B095126BF47E3005A112F /* ParseTwitter+combine.swift in Sources */,
34623479
70386A3B25D998D90048EC1B /* ParseLDAP.swift in Sources */,
@@ -3515,6 +3532,7 @@
35153532
703B096026BF481F005A112F /* ParseFacebook+async.swift in Sources */,
35163533
F97B462124D9C6F200F4A88B /* ParseStorage.swift in Sources */,
35173534
709A1480283949D100BF85E5 /* ParseSchema.swift in Sources */,
3535+
704E781A28CFD8A00075F952 /* ParseFileTransferable.swift in Sources */,
35183536
703B090526BD9652005A112F /* ParseAnalytics+async.swift in Sources */,
35193537
703B094226BF47AC005A112F /* ParseApple+async.swift in Sources */,
35203538
F97B466724D9C88600F4A88B /* SecureStorage.swift in Sources */,
@@ -3643,6 +3661,7 @@
36433661
705025E828514F36008D6624 /* ParsePushPayloadAny.swift in Sources */,
36443662
709A148428395ED100BF85E5 /* ParseSchema+async.swift in Sources */,
36453663
705025D3284CFCDE008D6624 /* ParsePushAppleAlert.swift in Sources */,
3664+
704E781E28CFFAF80075F952 /* ParseFileDefaultTransfer.swift in Sources */,
36463665
7045769A26BD917500F86F71 /* Query+async.swift in Sources */,
36473666
703B095026BF47E3005A112F /* ParseTwitter+combine.swift in Sources */,
36483667
70386A3A25D998D90048EC1B /* ParseLDAP.swift in Sources */,
@@ -3701,6 +3720,7 @@
37013720
703B095F26BF481F005A112F /* ParseFacebook+async.swift in Sources */,
37023721
F97B462024D9C6F200F4A88B /* ParseStorage.swift in Sources */,
37033722
709A147F283949D100BF85E5 /* ParseSchema.swift in Sources */,
3723+
704E781928CFD8A00075F952 /* ParseFileTransferable.swift in Sources */,
37043724
703B090426BD9652005A112F /* ParseAnalytics+async.swift in Sources */,
37053725
703B094126BF47AC005A112F /* ParseApple+async.swift in Sources */,
37063726
F97B466624D9C88600F4A88B /* SecureStorage.swift in Sources */,

‎Sources/ParseSwift/Documentation.docc/ParseSwift.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ To learn how to use or experiment with ParseSwift, you can run and edit the [Par
1212
### Configure SDK
1313

1414
- ``ParseSwift/initialize(configuration:)``
15-
- ``ParseSwift/initialize(applicationId:clientKey:masterKey:serverURL:liveQueryServerURL:allowingCustomObjectIds:usingTransactions:usingEqualQueryConstraint:usingPostForQuery:keyValueStore:requestCachePolicy:cacheMemoryCapacity:cacheDiskCapacity:usingDataProtectionKeychain:deletingKeychainIfNeeded:httpAdditionalHeaders:maxConnectionAttempts:authentication:)``
16-
- ``ParseSwift/initialize(applicationId:clientKey:masterKey:serverURL:liveQueryServerURL:allowingCustomObjectIds:usingTransactions:usingEqualQueryConstraint:usingPostForQuery:keyValueStore:requestCachePolicy:cacheMemoryCapacity:cacheDiskCapacity:migratingFromObjcSDK:usingDataProtectionKeychain:deletingKeychainIfNeeded:httpAdditionalHeaders:maxConnectionAttempts:authentication:)``
15+
- ``ParseSwift/initialize(applicationId:clientKey:masterKey:serverURL:liveQueryServerURL:allowingCustomObjectIds:usingTransactions:usingEqualQueryConstraint:usingPostForQuery:keyValueStore:requestCachePolicy:cacheMemoryCapacity:cacheDiskCapacity:usingDataProtectionKeychain:deletingKeychainIfNeeded:httpAdditionalHeaders:maxConnectionAttempts:parseFileTransfer:authentication:)``
16+
- ``ParseSwift/initialize(applicationId:clientKey:masterKey:serverURL:liveQueryServerURL:allowingCustomObjectIds:usingTransactions:usingEqualQueryConstraint:usingPostForQuery:keyValueStore:requestCachePolicy:cacheMemoryCapacity:cacheDiskCapacity:migratingFromObjcSDK:usingDataProtectionKeychain:deletingKeychainIfNeeded:httpAdditionalHeaders:maxConnectionAttempts:parseFileTransfer:authentication:)``
1717
- ``ParseSwift/configuration``
1818
- ``ParseSwift/setAccessGroup(_:synchronizeAcrossDevices:)``
1919
- ``ParseSwift/updateAuthentication(_:)``

‎Sources/ParseSwift/Extensions/URLSession.swift

+20-13
Original file line numberDiff line numberDiff line change
@@ -226,15 +226,21 @@ internal extension URLSession {
226226
) {
227227
var task: URLSessionTask?
228228
if let data = data {
229-
task = uploadTask(with: request, from: data) { (responseData, urlResponse, responseError) in
229+
task = ParseSwift
230+
.configuration
231+
.parseFileTransfer
232+
.upload(with: request, from: data) { (responseData, urlResponse, responseError) in
230233
completion(self.makeResult(request: request,
231234
responseData: responseData,
232235
urlResponse: urlResponse,
233236
responseError: responseError,
234237
mapper: mapper))
235238
}
236239
} else if let file = file {
237-
task = uploadTask(with: request, fromFile: file) { (responseData, urlResponse, responseError) in
240+
task = ParseSwift
241+
.configuration
242+
.parseFileTransfer
243+
.upload(with: request, fromFile: file) { (responseData, urlResponse, responseError) in
238244
completion(self.makeResult(request: request,
239245
responseData: responseData,
240246
urlResponse: urlResponse,
@@ -244,19 +250,20 @@ internal extension URLSession {
244250
} else {
245251
completion(.failure(ParseError(code: .unknownError, message: "data and file both cannot be nil")))
246252
}
247-
if let task = task {
248-
#if compiler(>=5.5.2) && canImport(_Concurrency)
249-
Task {
250-
await Parse.sessionDelegate.delegates.updateUpload(task, callback: progress)
251-
await Parse.sessionDelegate.delegates.updateTask(task, queue: notificationQueue)
252-
task.resume()
253-
}
254-
#else
255-
Parse.sessionDelegate.uploadDelegates[task] = progress
256-
Parse.sessionDelegate.taskCallbackQueues[task] = notificationQueue
253+
guard let task = task else {
254+
return
255+
}
256+
#if compiler(>=5.5.2) && canImport(_Concurrency)
257+
Task {
258+
await Parse.sessionDelegate.delegates.updateUpload(task, callback: progress)
259+
await Parse.sessionDelegate.delegates.updateTask(task, queue: notificationQueue)
257260
task.resume()
258-
#endif
259261
}
262+
#else
263+
Parse.sessionDelegate.uploadDelegates[task] = progress
264+
Parse.sessionDelegate.taskCallbackQueues[task] = notificationQueue
265+
task.resume()
266+
#endif
260267
}
261268

262269
func downloadTask<U>(

‎Sources/ParseSwift/Objects/ParseObject.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@ public extension ParseObject {
312312
/**
313313
Set the value of a specific `KeyPath` on a `ParseObject`.
314314
- parameter key: The `KeyPath` of the value to set.
315-
- parameter to: The value to set the `KeyPath` to.
315+
- parameter value: The value to set the `KeyPath` to.
316316
- returns: The updated `ParseObject`.
317317
- important: This method should be used when updating a `ParseObject` that has already been saved to
318318
a Parse Server. You can also use this method on a new `ParseObject`'s that has not been saved to a Parse Server

‎Sources/ParseSwift/Parse.swift

+12
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,10 @@ public func initialize(configuration: ParseConfiguration) {
205205
- parameter httpAdditionalHeaders: A dictionary of additional headers to send with requests. See Apple's
206206
[documentation](https://developer.apple.com/documentation/foundation/urlsessionconfiguration/1411532-httpadditionalheaders)
207207
for more info.
208+
- parameter maxConnectionAttempts: Maximum number of times to try to connect to Parse Server.
209+
Defaults to 5.
210+
- parameter parseFileTransfer: Override the default transfer behavior for `ParseFile`'s.
211+
Allows for direct uploads to other file storage providers.
208212
- parameter authentication: A callback block that will be used to receive/accept/decline network challenges.
209213
Defaults to `nil` in which the SDK will use the default OS authentication methods for challenges.
210214
It should have the following argument signature: `(challenge: URLAuthenticationChallenge,
@@ -234,6 +238,7 @@ public func initialize(
234238
deletingKeychainIfNeeded: Bool = false,
235239
httpAdditionalHeaders: [AnyHashable: Any]? = nil,
236240
maxConnectionAttempts: Int = 5,
241+
parseFileTransfer: ParseFileTransferable? = nil,
237242
authentication: ((URLAuthenticationChallenge,
238243
(URLSession.AuthChallengeDisposition,
239244
URLCredential?) -> Void) -> Void)? = nil
@@ -255,6 +260,7 @@ public func initialize(
255260
deletingKeychainIfNeeded: deletingKeychainIfNeeded,
256261
httpAdditionalHeaders: httpAdditionalHeaders,
257262
maxConnectionAttempts: maxConnectionAttempts,
263+
parseFileTransfer: parseFileTransfer,
258264
authentication: authentication)
259265
initialize(configuration: configuration)
260266
}
@@ -292,6 +298,10 @@ public func initialize(
292298
- parameter httpAdditionalHeaders: A dictionary of additional headers to send with requests. See Apple's
293299
[documentation](https://developer.apple.com/documentation/foundation/urlsessionconfiguration/1411532-httpadditionalheaders)
294300
for more info.
301+
- parameter maxConnectionAttempts: Maximum number of times to try to connect to Parse Server.
302+
Defaults to 5.
303+
- parameter parseFileTransfer: Override the default transfer behavior for `ParseFile`'s.
304+
Allows for direct uploads to other file storage providers.
295305
- parameter authentication: A callback block that will be used to receive/accept/decline network challenges.
296306
Defaults to `nil` in which the SDK will use the default OS authentication methods for challenges.
297307
It should have the following argument signature: `(challenge: URLAuthenticationChallenge,
@@ -323,6 +333,7 @@ public func initialize(
323333
deletingKeychainIfNeeded: Bool = false,
324334
httpAdditionalHeaders: [AnyHashable: Any]? = nil,
325335
maxConnectionAttempts: Int = 5,
336+
parseFileTransfer: ParseFileTransferable? = nil,
326337
authentication: ((URLAuthenticationChallenge,
327338
(URLSession.AuthChallengeDisposition,
328339
URLCredential?) -> Void) -> Void)? = nil
@@ -344,6 +355,7 @@ public func initialize(
344355
deletingKeychainIfNeeded: deletingKeychainIfNeeded,
345356
httpAdditionalHeaders: httpAdditionalHeaders,
346357
maxConnectionAttempts: maxConnectionAttempts,
358+
parseFileTransfer: parseFileTransfer,
347359
authentication: authentication)
348360
configuration.isMigratingFromObjcSDK = migratingFromObjcSDK
349361
initialize(configuration: configuration)

‎Sources/ParseSwift/ParseConstants.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import Foundation
1010

1111
enum ParseConstants {
1212
static let sdk = "swift"
13-
static let version = "4.11.0"
13+
static let version = "4.12.0"
1414
static let fileManagementDirectory = "parse/"
1515
static let fileManagementPrivateDocumentsDirectory = "Private Documents/"
1616
static let fileManagementLibraryDirectory = "Library/"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
//
2+
// ParseFileAdaptable.swift
3+
// ParseSwift
4+
//
5+
// Created by Corey Baker on 9/12/22.
6+
// Copyright © 2022 Parse Community. All rights reserved.
7+
//
8+
9+
import Foundation
10+
#if canImport(FoundationNetworking)
11+
import FoundationNetworking
12+
#endif
13+
14+
/**
15+
A protocol for overriding the default transfer behavior for `ParseFile`'s.
16+
Allows for direct uploads to other file storage providers.
17+
*/
18+
public protocol ParseFileTransferable: AnyObject {
19+
/**
20+
Creates a task that performs an HTTP request for uploading the specified file,
21+
then calls a handler upon completion.
22+
- parameter request: The Parse URL request object that provides the URL, cache policy,
23+
request type, and so on.
24+
- parameter fileURL: The URL of the file to upload.
25+
- parameter completion: The completion handler to call when the load request
26+
is complete. This handler is executed on the delegate queue.
27+
*/
28+
func upload(with request: URLRequest,
29+
fromFile fileURL: URL,
30+
completion: @escaping (Data?, URLResponse?, Error?) -> Void) -> URLSessionUploadTask
31+
32+
/**
33+
Creates a task that performs an HTTP request for the specified URL request
34+
object, uploads the provided data, and calls a handler upon completion.
35+
- parameter request: The Parse URL request object that provides the URL, cache policy,
36+
request type, and so on.
37+
- parameter bodyData: The body data for the request.
38+
- parameter completion: The completion handler to call when the load request
39+
is complete. This handler is executed on the delegate queue.
40+
*/
41+
func upload(with request: URLRequest,
42+
from bodyData: Data?,
43+
completion: @escaping (Data?, URLResponse?, Error?) -> Void) -> URLSessionUploadTask
44+
}
45+
46+
extension ParseFileTransferable {
47+
func upload(with request: URLRequest,
48+
fromFile fileURL: URL,
49+
completion: @escaping (Data?, URLResponse?, Error?) -> Void) -> URLSessionUploadTask {
50+
URLSession.parse.uploadTask(with: request, fromFile: fileURL, completionHandler: completion)
51+
}
52+
53+
func upload(with request: URLRequest,
54+
from bodyData: Data?,
55+
completion: @escaping (Data?, URLResponse?, Error?) -> Void) -> URLSessionUploadTask {
56+
URLSession.parse.uploadTask(with: request, from: bodyData, completionHandler: completion)
57+
}
58+
}

‎Sources/ParseSwift/Types/ParseCLP.swift

+4-4
Original file line numberDiff line numberDiff line change
@@ -472,8 +472,8 @@ public extension ParseCLP {
472472
/**
473473
Sets whether the given `ParseUser` objectId has access to perform
474474
create/update/delete/addField actions on a Parse class.
475+
- parameter allow: **true** if access should be allowed, **false** otherwise.
475476
- parameter objectId: The `ParseUser` objectId to provide/restrict access to.
476-
- parameter to: **true** if access should be allowed, **false** otherwise.
477477
- parameter canAddField: **true** if access should be allowed to `addField`,
478478
**false** otherwise. Defaults to **false**.
479479
- returns: A mutated instance of `ParseCLP` for easy chaining.
@@ -495,8 +495,8 @@ public extension ParseCLP {
495495

496496
/**
497497
Sets whether the given `ParseUser` has access to perform create/update/delete/addField actions on a Parse class.
498+
- parameter allow: **true** if access should be allowed, **false** otherwise.
498499
- parameter user: The `ParseUser` to provide/restrict access to.
499-
- parameter to: **true** if access should be allowed, **false** otherwise.
500500
- parameter canAddField: **true** if access should be allowed to `addField`,
501501
**false** otherwise. Defaults to **false**.
502502
- returns: A mutated instance of `ParseCLP` for easy chaining.
@@ -512,8 +512,8 @@ public extension ParseCLP {
512512
/**
513513
Sets whether the given `ParseUser`pointer has access to perform
514514
create/update/delete/addField actions on a Parse class.
515+
- parameter allow: **true** if access should be allowed, **false** otherwise.
515516
- parameter user: The `ParseUser` to provide/restrict access to.
516-
- parameter to: **true** if access should be allowed, **false** otherwise.
517517
- parameter canAddField: **true** if access should be allowed to `addField`,
518518
**false** otherwise. Defaults to **false**.
519519
- returns: A mutated instance of `ParseCLP` for easy chaining.
@@ -526,8 +526,8 @@ public extension ParseCLP {
526526

527527
/**
528528
Sets whether the given `ParseRole` has access to perform create/update/delete/addField actions on a Parse class.
529+
- parameter allow: **true** if access should be allowed, **false** otherwise.
529530
- parameter role: The `ParseRole` to provide/restrict access to.
530-
- parameter to: **true** if access should be allowed, **false** otherwise.
531531
- parameter canAddField: **true** if access should be allowed to `addField`,
532532
**false** otherwise. Defaults to **false**.
533533
- returns: A mutated instance of `ParseCLP` for easy chaining.

‎Sources/ParseSwift/Types/ParseConfiguration.swift

+14
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,12 @@ public struct ParseConfiguration {
9494
/// Defaults to 5.
9595
public internal(set) var maxConnectionAttempts: Int = 5
9696

97+
/**
98+
Override the default transfer behavior for `ParseFile`'s.
99+
Allows for direct uploads to other file storage providers.
100+
*/
101+
public internal(set) var parseFileTransfer: ParseFileTransferable
102+
97103
internal var authentication: ((URLAuthenticationChallenge,
98104
(URLSession.AuthChallengeDisposition,
99105
URLCredential?) -> Void) -> Void)?
@@ -137,6 +143,8 @@ public struct ParseConfiguration {
137143
for more info.
138144
- parameter maxConnectionAttempts: Maximum number of times to try to connect to Parse Server.
139145
Defaults to 5.
146+
- parameter parseFileTransfer: Override the default transfer behavior for `ParseFile`'s.
147+
Allows for direct uploads to other file storage providers.
140148
- parameter authentication: A callback block that will be used to receive/accept/decline network challenges.
141149
Defaults to `nil` in which the SDK will use the default OS authentication methods for challenges.
142150
It should have the following argument signature: `(challenge: URLAuthenticationChallenge,
@@ -166,6 +174,7 @@ public struct ParseConfiguration {
166174
deletingKeychainIfNeeded: Bool = false,
167175
httpAdditionalHeaders: [AnyHashable: Any]? = nil,
168176
maxConnectionAttempts: Int = 5,
177+
parseFileTransfer: ParseFileTransferable? = nil,
169178
authentication: ((URLAuthenticationChallenge,
170179
(URLSession.AuthChallengeDisposition,
171180
URLCredential?) -> Void) -> Void)? = nil) {
@@ -189,6 +198,7 @@ public struct ParseConfiguration {
189198
self.isDeletingKeychainIfNeeded = deletingKeychainIfNeeded
190199
self.httpAdditionalHeaders = httpAdditionalHeaders
191200
self.maxConnectionAttempts = maxConnectionAttempts
201+
self.parseFileTransfer = parseFileTransfer ?? ParseFileDefaultTransfer()
192202
ParseStorage.shared.use(keyValueStore ?? InMemoryKeyValueStore())
193203
}
194204

@@ -226,6 +236,8 @@ public struct ParseConfiguration {
226236
for more info.
227237
- parameter maxConnectionAttempts: Maximum number of times to try to connect to Parse Server.
228238
Defaults to 5.
239+
- parameter parseFileTransfer: Override the default transfer behavior for `ParseFile`'s.
240+
Allows for direct uploads to other file storage providers.
229241
- parameter authentication: A callback block that will be used to receive/accept/decline network challenges.
230242
Defaults to `nil` in which the SDK will use the default OS authentication methods for challenges.
231243
It should have the following argument signature: `(challenge: URLAuthenticationChallenge,
@@ -257,6 +269,7 @@ public struct ParseConfiguration {
257269
deletingKeychainIfNeeded: Bool = false,
258270
httpAdditionalHeaders: [AnyHashable: Any]? = nil,
259271
maxConnectionAttempts: Int = 5,
272+
parseFileTransfer: ParseFileTransferable? = nil,
260273
authentication: ((URLAuthenticationChallenge,
261274
(URLSession.AuthChallengeDisposition,
262275
URLCredential?) -> Void) -> Void)? = nil) {
@@ -278,6 +291,7 @@ public struct ParseConfiguration {
278291
deletingKeychainIfNeeded: deletingKeychainIfNeeded,
279292
httpAdditionalHeaders: httpAdditionalHeaders,
280293
maxConnectionAttempts: maxConnectionAttempts,
294+
parseFileTransfer: parseFileTransfer ?? ParseFileDefaultTransfer(),
281295
authentication: authentication)
282296
self.isMigratingFromObjcSDK = migratingFromObjcSDK
283297
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
//
2+
// ParseFileDefaultTransfer.swift
3+
// ParseSwift
4+
//
5+
// Created by Corey Baker on 9/12/22.
6+
// Copyright © 2022 Parse Community. All rights reserved.
7+
//
8+
9+
import Foundation
10+
11+
final class ParseFileDefaultTransfer: ParseFileTransferable {}

‎Sources/ParseSwift/Types/ParseOperation.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public struct ParseOperation<T>: Savable where T: ParseObject {
4848
An operation that sets a field's value.
4949
- Parameters:
5050
- keyPath: The respective `KeyPath` of the object.
51-
- to: The value to set the `KeyPath` to.
51+
- value: The value to set the `KeyPath` to.
5252
- returns: The updated operations.
5353
- warning: Do not combine operations using this method with other operations that
5454
do not use this method to **set** all operations. If you need to combine multiple types
@@ -91,7 +91,7 @@ public struct ParseOperation<T>: Savable where T: ParseObject {
9191
An operation that sets a field's value if it has changed from its previous value.
9292
- Parameters:
9393
- key: A tuple consisting of the key and the respective `KeyPath` of the object.
94-
- to: The value to set the `KeyPath` to.
94+
- value: The value to set the `KeyPath` to.
9595
- returns: The updated operations.
9696
- Note: Set the value to "nil" if you want it to be "null" on the Parse Server.
9797
*/
@@ -125,7 +125,7 @@ public struct ParseOperation<T>: Savable where T: ParseObject {
125125
An operation that force sets a field's value.
126126
- Parameters:
127127
- key: A tuple consisting of the key and the respective `KeyPath` of the object.
128-
- to: The value to set the `KeyPath` to.
128+
- value: The value to set the `KeyPath` to.
129129
- returns: The updated operations.
130130
- Note: Set the value to "nil" if you want it to be "null" on the Parse Server.
131131
*/

‎Tests/ParseSwiftTests/InitializeSDKTests.swift

+2-1
Original file line numberDiff line numberDiff line change
@@ -573,7 +573,8 @@ class InitializeSDKTests: XCTestCase {
573573
clientKey: "clientKey",
574574
masterKey: "masterKey",
575575
serverURL: url,
576-
migratingFromObjcSDK: true)
576+
migratingFromObjcSDK: true,
577+
parseFileTransfer: nil)
577578
guard let installation = Installation.current else {
578579
XCTFail("Should have installation")
579580
return

0 commit comments

Comments
 (0)
Please sign in to comment.