swiftchatxmppframeworkimage-upload

Keep view controller code running after view controller get popped


I am implementing chat functionality with the help of XMPP and chat is working fine. Now i am working on image uploading and for that i upload image to s3 bucket and after uploading image to s3 i send s3 image url as message to other user using xmpp method. This is also working fine but problem is it is only working if i stay on same screen i.e chat screen when image is uploading. So if my image is still uploading and i pop from view controller it gets deallocated and my completion handler not get called after uploading image to s3 and because of that my sendMessage method is also not get called. So how can i achieve this. how can i send my messages and get completion handler called even if i am on different screen while image is uploading.

This is my code for picking image and upload image

@IBAction func didPressMedia(_ sender: Any) {
        ImagePickerManager().pickImage(self) { \[weak self\] pickedImage in
        guard let self = self else { return }

        let compressedImage = pickedImage.resizedImage(newSize: CGSize(width: 120, height: 120))
        
        let messageId = XMPPHelper.shared.xmppStream.generateUUID

        let chat = ChatListModel()
        chat.roomId = ""
        chat.message = ""
        chat.messageId = messageId
        chat.time = String(Date().currentTimeMillis())
        chat.to = self.viewModel.otherUser
        chat.from = self.viewModel.myJid ?? ""
        chat.type = "chat/image"
        chat.imageLocalPath = messageId
        chat.msgDeliveryStatus = MsgDeliveryStatus.sending.rawValue
        chat.isSeenSync = true
        chat.isUploading = "pending"
        
        self.viewModel.setChatDataInRealm(item: chat, isAfterPickingImage: true)

        //This is completion handler which get called after image upload to s3.
        self.viewModel.didImageUploaded = { [weak self] isImgUploaded , imgUrl, imgMessageId in
            guard let self = self else { return }
            if isImgUploaded {
                print("success uploading image")
                self.viewModel.sendMessage(message: imgUrl, isImage: true, messageId: imgMessageId). // send image url as message to other user

            }else{
                print("error uploading image")
                self.viewModel.updateRealmAfterImageUpload(uploadStatus: "failed", uploadedUrl: "", messsageId: imgMessageId)
            }
        }

        self.viewModel.uploadImage(localPath: "\(Helper.shared.getDocumentDirectoryPath(filename: messageId)).png" ,image: compressedImage, messageId: messageId)
    }
}

Solution

  • Try this code

    class ChatManager {
        
        static let shared = ChatManager()
        private init() {}
        
        
        func uploadImage(localPath: String, image: UIImage, messageId: String, didImageUploaded: @escaping (Bool, String?, String?) -> Void) {
            
            // Code to upload image to server...
            //Once image is uploaded you can continue the logic here. and after that call the closure `didImageUploaded`
            if isImgUploaded {
                print("success uploading image")
                self.sendMessage(message: imgUrl, isImage: true, messageId: imgMessageId) // send image url as message to other user
                
            }else{
                print("error uploading image")
                self.updateRealmAfterImageUpload(uploadStatus: "failed", uploadedUrl: "", messsageId: imgMessageId)
            }
            
            // Call didImageUploaded closure after image upload if needed.
            didImageUploaded(true, "imageUrl", "messageId")
            
        }
        
        func sendMessage(message: String, isImage: Bool, messageId: String) {
            // Code to send message to other user
        }
        
        func updateRealmAfterImageUpload(uploadStatus: String, uploadedUrl: String, messageId: String) {
            // Code to update Realm database after image upload
        }
    }
    

    How to call

    ChatManager.shared.uploadImage(localPath: "\(Helper.shared.getDocumentDirectoryPath(filename: messageId)).png", image: compressedImage, messageId: messageId) { [weak self] isImgUploaded, imgUrl, imgMessageId in
        //Refresh views if needed.
     }