Сбой при загрузке или удалении изображений с помощью AWSS3Manager в Swift 6 - возможная проблема блока завершения?IOS

Программируем под IOS
Ответить
Anonymous
 Сбой при загрузке или удалении изображений с помощью AWSS3Manager в Swift 6 - возможная проблема блока завершения?

Сообщение Anonymous »

Я работаю с AWS S3 в приложении iOS, используя Swift 6. У меня есть односложный класс AWSS3Manager , который обрабатывает загрузку и удаление изображений, видео и других файлов. Однако после перехода на Swift 6 я испытываю частые сбои при загрузке или удалении нескольких изображений или отдельного изображения. Проблема, по-видимому, связана с тем, что блоки завершения называются ненадлежащим образом или несколько раз, особенно во время загрузки изображения или при перегрузке через uploadimages .

Код: Выделить всё

@MainActor
class AWSS3Manager{

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

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

AWSServiceManager.default().defaultServiceConfiguration = configuration
}

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

if images.count == 0 || InternetConnectionManager.isConnectedToNetwork() == false {
completion(nil, nil)
}
if AWSServiceManager.default().defaultServiceConfiguration == nil {
initializeS3()
let error = NSError(domain: "AWS", code: 1001, userInfo: [NSLocalizedDescriptionKey: "AWS is not initialized."])
completion(nil, error)
return
}
var counter: Int = 0
images.enumerated().forEach { i,image in
let imageName: String = String(paths[i].split(separator: "/").last ?? "\(UUID().uuidString).jpeg")
if let imageData = image.jpegData(compressionQuality: 0.3),
let localUrl = try? saveDataToTempFolder(data: imageData, fileName: imageName){
self.uploadfile(fileUrl: localUrl, fileName: paths[i], contenType: "image", progress: nil) { response, error in
counter += 1
if counter == paths.count {
completion(nil, error)
}
}
}else{
counter += 1
if counter == paths.count {
completion(nil, nil)
}
}
}
}

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

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

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

s3.listObjects(listObjectsRequest!).continueWith { (task) -> AnyObject? in
if let error = task.error {
debugPrint("Error occurred while listing objects: \(error)")
return nil
}

if let listObjectsOutput = task.result, 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 while deleting object \(object.key ?? ""): \(error)")
} else {
debugPrint("Deleted \(object.key ?? "") successfully.")
}
return nil
}
}
} else {
debugPrint("No objects found in folder \(folderPath)")
}
return nil
}
}

// Upload video from local 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)
}

// Upload auido from local 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)
}

// Upload files like Text, Zip, etc from local 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 unique file name
func getUniqueFileName(fileUrl: URL) -> String {
let strExt: String = "." + (URL(fileURLWithPath: fileUrl.absoluteString).pathExtension)
return (ProcessInfo.processInfo.globallyUniqueString + (strExt))
}

//MARK:- AWS file upload
// fileUrl :  file local path url
// fileName : name of file, like "myimage.jpeg" "video.mov"
// contenType: file MIME type
// progress: file upload progress, value from 0 to 1, 1 for 100% complete
// completion: completion block when uplaoding is finish, you will get S3 url of upload file here
private 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("Something went wrong!")
}
let error = NSError(domain: "AWS", code: 1001, userInfo: [NSLocalizedDescriptionKey: "AWS is not initialized."])
completion?(nil, error)
return
}
// Upload progress block
let expression = AWSS3TransferUtilityUploadExpression()
expression.progressBlock = {(task, awsProgress) in
guard let uploadProgress = progress else { return }
DispatchQueue.main.async {
uploadProgress(awsProgress.fractionCompleted)
}
}
// Completion block
var completionHandler: AWSS3TransferUtilityUploadCompletionHandlerBlock?
completionHandler = { (task, error) -> Void in
DispatchQueue.main.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)
}
}
})
}
// Start uploading using AWSS3TransferUtility
let awsTransferUtility = AWSS3TransferUtility.default()
awsTransferUtility.uploadFile(fileUrl, bucket: bucketName, key: fileName, contentType: contenType, expression: expression, completionHandler: completionHandler).continueWith { (task) ->  Any? in
if let error = task.error {
debugPrint("error is: \(error.localizedDescription)")
}
if let _ = task.result {
// your uploadTask
}
return nil
}
}
}
reference
https://releases.amplify.aws/aws-sdk-ios/ (spm)
2.40.1
образно (серийный) src="https://i.sstatic.net/yr9NeAb0.png" />
Изображение


боковая панель


Добавление nonIsolated в uploadImage & uploadfile и сделав их асинхрономатическим/ожиданием и удалением @mainactor решило проблему. Так что теперь нет сбоя, но я не могу сказать, что это лучшее решение или нет?

Подробнее здесь: https://stackoverflow.com/questions/795 ... 6-possible
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «IOS»