ios – Crash when importing or deleting photographs with AWSS3Manager in Swift 6 – attainable completion block problem?

0
1
ios – Crash when importing or deleting photographs with AWSS3Manager in Swift 6 – attainable completion block problem?


I am working with AWS S3 in an iOS app utilizing Swift 6. I’ve a singleton class AWSS3Manager that handles importing and deleting photographs, movies, and different recordsdata. Nonetheless, after migrating to Swift 6, I am experiencing random crashes when importing or deleting a number of photographs. The difficulty appears to be associated to completion blocks being referred to as inappropriately or a number of occasions, particularly throughout picture add or when iterating by means of uploadImages.

@MainActor
class AWSS3Manager{

    static let shared = AWSS3Manager() // 4
    non-public init () {
        initializeS3()
    }
    let bucketName = "Bucket_Name" //5

    func initializeS3() {
        if S3Key == "" || S3SecretKeyName == "" {
//            if let topVC = UIApplication.topViewController() {
//                topVC.showError("One thing went unsuitable!")
//            }
            debugPrint("AWS initialisation Error")
            return
        }
        let credentials = AWSStaticCredentialsProvider(accessKey: S3Key, secretKey: S3SecretKeyName)
        let configuration = AWSServiceConfiguration(area: AWSRegionType.USEast1, credentialsProvider: credentials)

        AWSServiceManager.default().defaultServiceConfiguration = configuration
    }

    func uploadImages(photographs: [UIImage], paths: [String], completion: @escaping(_ response: Any?, _ error: Error?) -> Void){

        if photographs.rely == 0 || InternetConnectionManager.isConnectedToNetwork() == false {
            completion(nil, nil)
        }
        if AWSServiceManager.default().defaultServiceConfiguration == nil {
            initializeS3()
            let error = NSError(area: "AWS", code: 1001, userInfo: [NSLocalizedDescriptionKey: "AWS is not initialized."])
            completion(nil, error)
            return
        }
        var counter: Int = 0
        photographs.enumerated().forEach { i,picture in
            let imageName: String = String(paths[i].cut up(separator: "/").final ?? "(UUID().uuidString).jpeg")
            if let imageData = picture.jpegData(compressionQuality: 0.3),
               let localUrl = attempt? saveDataToTempFolder(information: imageData, fileName: imageName){
                self.uploadfile(fileUrl: localUrl, fileName: paths[i], contenType: "picture", progress: nil) { response, error in
                    counter += 1
                    if counter == paths.rely {
                        completion(nil, error)
                    }
                }
            }else{
                counter += 1
                if counter == paths.rely {
                    completion(nil, nil)
                }
            }
        }
    }

    func deleteImage(path: String){
        if AWSServiceManager.default().defaultServiceConfiguration == nil {
            initializeS3()
            if let topVC = UIApplication.topViewController() {
                topVC.showError("One thing went unsuitable!")
            }
            return
        }
        let s3 = AWSS3.default()
        guard let deleteObjectRequest = AWSS3DeleteObjectRequest() else {
            return
        }
        deleteObjectRequest.bucket = S3BucketName
        deleteObjectRequest.key = path
        s3.deleteObject(deleteObjectRequest).continueWith { (process:AWSTask) -> AnyObject? in
            if let error = process.error {
                debugPrint("Error occurred: (error)")
                return nil
            }
            debugPrint("Deleted efficiently.")
            return nil
        }
    }

    func deleteAllImagesForUser(userID: String) {
        if AWSServiceManager.default().defaultServiceConfiguration == nil {
            initializeS3()
            if let topVC = UIApplication.topViewController() {
                topVC.showError("One thing went unsuitable!")
            }
            return
        }
        let s3 = AWSS3.default()
        let folderPath = "Receipts/(userID)/"

        let listObjectsRequest = AWSS3ListObjectsRequest()
        listObjectsRequest?.bucket = S3BucketName
        listObjectsRequest?.prefix = folderPath

        s3.listObjects(listObjectsRequest!).continueWith { (process) -> AnyObject? in
            if let error = process.error {
                debugPrint("Error occurred whereas itemizing objects: (error)")
                return nil
            }

            if let listObjectsOutput = process.outcome, let contents = listObjectsOutput.contents {
                for object in contents {
                    let deleteObjectRequest = AWSS3DeleteObjectRequest()
                    deleteObjectRequest?.bucket = S3BucketName
                    deleteObjectRequest?.key = object.key

                    s3.deleteObject(deleteObjectRequest!).continueWith { (deleteTask) -> AnyObject? in
                        if let error = deleteTask.error {
                            debugPrint("Error occurred whereas deleting object (object.key ?? ""): (error)")
                        } else {
                            debugPrint("Deleted (object.key ?? "") efficiently.")
                        }
                        return nil
                    }
                }
            } else {
                debugPrint("No objects present in folder (folderPath)")
            }
            return nil
        }
    }

    // Add video from native path url
    func uploadVideo(videoUrl: URL, progress: progressBlock?, completion: completionBlock?) {
        let fileName = self.getUniqueFileName(fileUrl: videoUrl)
        self.uploadfile(fileUrl: videoUrl, fileName: fileName, contenType: "video", progress: progress, completion: completion)
    }

    // Add auido from native path url
    func uploadAudio(audioUrl: URL, progress: progressBlock?, completion: completionBlock?) {
        let fileName = self.getUniqueFileName(fileUrl: audioUrl)
        self.uploadfile(fileUrl: audioUrl, fileName: fileName, contenType: "audio", progress: progress, completion: completion)
    }

    // Add recordsdata like Textual content, Zip, and so on from native path url
    func uploadOtherFile(fileUrl: URL, conentType: String, progress: progressBlock?, completion: completionBlock?) {
        let fileName = self.getUniqueFileName(fileUrl: fileUrl)
        self.uploadfile(fileUrl: fileUrl, fileName: fileName, contenType: conentType, progress: progress, completion: completion)
    }

    // Get distinctive file identify
    func getUniqueFileName(fileUrl: URL) -> String {
        let strExt: String = "." + (URL(fileURLWithPath: fileUrl.absoluteString).pathExtension)
        return (ProcessInfo.processInfo.globallyUniqueString + (strExt))
    }

    //MARK:- AWS file add
    // fileUrl :  file native path url
    // fileName : identify of file, like "myimage.jpeg" "video.mov"
    // contenType: file MIME sort
    // progress: file add progress, worth from 0 to 1, 1 for 100% full
    // completion: completion block when uplaoding is end, you'll get S3 url of add file right here
    non-public func uploadfile(fileUrl: URL, fileName: String, contenType: String, progress: progressBlock?, completion: completionBlock?) {
        if AWSServiceManager.default().defaultServiceConfiguration == nil {
            initializeS3()
            if let topVC = UIApplication.topViewController() {
                topVC.showError("One thing went unsuitable!")
            }
            let error = NSError(area: "AWS", code: 1001, userInfo: [NSLocalizedDescriptionKey: "AWS is not initialized."])
            completion?(nil, error)
            return
        }
        // Add progress block
        let expression = AWSS3TransferUtilityUploadExpression()
        expression.progressBlock = {(process, awsProgress) in
            guard let uploadProgress = progress else { return }
            DispatchQueue.major.async {
                uploadProgress(awsProgress.fractionCompleted)
            }
        }
        // Completion block
        var completionHandler: AWSS3TransferUtilityUploadCompletionHandlerBlock?
        completionHandler = { (process, error) -> Void in
            DispatchQueue.major.async(execute: {
                if error == nil {
                    let url = AWSS3.default().configuration.endpoint.url
                    let publicURL = url?.appendingPathComponent(self.bucketName).appendingPathComponent(fileName)
                    let presignedURL = self.getPreSignedURL(S3DownloadKeyName: fileName)
                    if let completionBlock = completion {
                        completionBlock(fileName, nil)
                    }
                } else {
                    if let completionBlock = completion {
                        completionBlock(nil, error)
                    }
                }
            })
        }
        // Begin importing utilizing AWSS3TransferUtility
        let awsTransferUtility = AWSS3TransferUtility.default()
        awsTransferUtility.uploadFile(fileUrl, bucket: bucketName, key: fileName, contentType: contenType, expression: expression, completionHandler: completionHandler).continueWith { (process) -> Any? in
            if let error = process.error {
                debugPrint("error is: (error.localizedDescription)")
            }
            if let _ = process.outcome {
                // your uploadTask
            }
            return nil
        }
    }
}

LEAVE A REPLY

Please enter your comment!
Please enter your name here