99import Foundation
1010
1111/// This class allows uploading multiple `Uploadable` items to a given storage location.
12- ///
13- /// Please notice this class can not be directly instantiated. Instances of this class are
14- /// returned by the upload functions in `Client`.
15- ///
16- /// Features:
17- ///
18- /// - Ability to track upload progress (see the `progress` property)
19- /// - Ability to add `Uploadable` items at any time before the upload starts (see `add(uploadables:)`)
20- /// - Ability to cancel the upload process (see `cancel()`)
21- ///
22- @objc ( FSMultifileUpload) public class MultifileUpload : NSObject {
12+ class MultifileUpload : Uploader , DeferredAdd {
2313 // MARK: - Public Properties
2414
25- /// The overall upload progress.
26- @objc public let progress = Progress ( )
27-
28- /// Current upload status.
29- @objc public private( set) var currentStatus : UploadStatus = . notStarted
30-
3115 // MARK: - Internal Properties
3216
33- internal var uploadProgress : ( ( Progress ) -> Void ) ?
17+ internal let masterProgress = MirroredProgress ( )
18+ internal var progressHandler : ( ( Progress ) -> Void ) ?
3419 internal var completionHandler : ( ( [ NetworkJSONResponse ] ) -> Void ) ?
3520
3621 // MARK: - Private Properties
@@ -58,42 +43,29 @@ import Foundation
5843 self . apiKey = apiKey
5944 self . security = security
6045
61- super. init ( )
62-
6346 if let uploadables = uploadables {
6447 enqueueUploadables ( uploadables: uploadables)
6548 }
6649 }
6750
68- // MARK: - Public Functions
69-
70- /// Adds items to be uploaded.
71- ///
72- /// - Important: Any items added after the upload process started will be ignored.
73- ///
74- /// - Parameter uploadables: An array of `Uploadable` items to upload.
75- /// - Returns: True on success, false otherwise.
76- @discardableResult public func add( uploadables: [ Uploadable ] ) -> Bool {
77- switch currentStatus {
78- case . notStarted:
79- self . enqueueUploadables ( uploadables: uploadables)
51+ // MARK: - Uploadable Protocol Implementation
8052
81- return true
82- default :
83- return false
53+ private( set) var currentStatus : UploadStatus = . notStarted {
54+ didSet {
55+ switch currentStatus {
56+ case . cancelled:
57+ progress. cancel ( )
58+ default :
59+ break
60+ }
8461 }
8562 }
8663
87- /// Cancels upload.
88- ///
89- /// - Important: Any already uploaded files **will not** be deleted —
90- /// only the current file being uploaded (if any) and any pending files will be affected.
91- ///
92- /// On success, this will trigger `completionHandler`.
93- ///
94- /// - Returns: True on success, false otherwise.
95- @objc
96- @discardableResult public func cancel( ) -> Bool {
64+ lazy var progress = {
65+ masterProgress. mirror
66+ } ( )
67+
68+ @discardableResult func cancel( ) -> Bool {
9769 switch currentStatus {
9870 case . notStarted:
9971 fallthrough
@@ -108,11 +80,7 @@ import Foundation
10880 }
10981 }
11082
111- /// Starts upload.
112- ///
113- /// - Returns: True on success, false otherwise.
114- @objc
115- @discardableResult public func start( ) -> Bool {
83+ @discardableResult func start( ) -> Bool {
11684 switch currentStatus {
11785 case . notStarted:
11886 uploadNextFile ( )
@@ -124,11 +92,22 @@ import Foundation
12492 }
12593 }
12694
127- /// :nodoc:
128- @available ( * , deprecated, message: " Marked for removal in version 3.0. Use start() instead. " )
129- @objc public func uploadFiles( ) {
95+ func uploadFiles( ) {
13096 start ( )
13197 }
98+
99+ // MARK: - DeferredAdd Protocol Implementation
100+
101+ @discardableResult func add( uploadables: [ Uploadable ] ) -> Bool {
102+ switch currentStatus {
103+ case . notStarted:
104+ self . enqueueUploadables ( uploadables: uploadables)
105+
106+ return true
107+ default :
108+ return false
109+ }
110+ }
132111}
133112
134113private extension MultifileUpload {
@@ -144,15 +123,15 @@ private extension MultifileUpload {
144123 // Append uploads to `pendingUploads`.
145124 pendingUploads. append ( contentsOf: uploads)
146125 // Update progress total unit count so it matches the `pendingUploads` count.
147- progress . totalUnitCount = Int64 ( pendingUploads. count)
126+ masterProgress . totalUnitCount = Int64 ( pendingUploads. count)
148127
149128 // Set upload progress and completion handlers and add upload progress as a child of our main `progress` object
150129 // so we can track all uploads from our main `progress` object.
151130 for upload in uploads {
152131 upload. uploadProgress = { _ in self . updateProgress ( ) }
153132 upload. completionHandler = { self . finishedCurrentFile ( with: $0) }
154133
155- progress . addChild ( upload. progress , withPendingUnitCount: 1 )
134+ masterProgress . addChild ( upload. masterProgress , withPendingUnitCount: 1 )
156135 }
157136 }
158137
@@ -171,13 +150,13 @@ private extension MultifileUpload {
171150 func stopUpload( ) {
172151 guard currentStatus != . completed, currentStatus != . cancelled else { return }
173152
174- if progress . completedUnitCount == progress . totalUnitCount {
153+ if masterProgress . completedUnitCount == masterProgress . totalUnitCount {
175154 currentStatus = . completed
176155 } else {
177156 currentStatus = . cancelled
178157 }
179158
180- while uploadResponses. count < progress . totalUnitCount {
159+ while uploadResponses. count < masterProgress . totalUnitCount {
181160 uploadResponses. append ( NetworkJSONResponse ( with: MultipartUploadError . aborted) )
182161 }
183162
@@ -186,14 +165,14 @@ private extension MultifileUpload {
186165 // To ensure this object can be properly deallocated we must ensure that any closures are niled,
187166 // and `currentOperation` object is niled as well.
188167 self . completionHandler = nil
189- self . uploadProgress = nil
168+ self . progressHandler = nil
190169 self . currentOperation = nil
191170 }
192171 }
193172
194173 func updateProgress( ) {
195174 queue. async {
196- self . uploadProgress ? ( self . progress)
175+ self . progressHandler ? ( self . progress)
197176 }
198177 }
199178
@@ -211,7 +190,7 @@ private extension MultifileUpload {
211190
212191extension MultifileUpload {
213192 /// :nodoc:
214- public override var description : String {
193+ public var description : String {
215194 return Tools . describe ( subject: self , only: [ " currentStatus " , " progress " ] )
216195 }
217196}
0 commit comments