文件上传进度的通知观察者模式仅在文件很大时才有效 - swift?

Posted

技术标签:

【中文标题】文件上传进度的通知观察者模式仅在文件很大时才有效 - swift?【英文标题】:Notification-Observer pattern for file upload progress works only when the file is large - swift? 【发布时间】:2018-12-05 20:46:07 【问题描述】:

我有一个将图像上传到远程服务器的单视图应用程序。当用户提交上传时,我使用第二个视图控制器显示为自定义弹出窗口并显示文件上传进度。上传完成后,自定义弹出窗口展开到第一个 viewController。我正在使用通知观察者模式在两个视图控制器之间进行通信。

我的问题是:上传大文件时,可以看到上传进度条,上传完成后自定义弹窗会展开。当我上传一个小文件时,上传时间非常快,即使文件上传成功,也没有观察到上传进度并且自定义弹出窗口没有展开(见下面的代码)。

我不确定我是否正确设置了通知观察者模式?

第一视图控制器:

Alamofire.upload(
        multipartFormData:  multipartFormData in
            for(key, value) in sendParamters
                multipartFormData.append((value.data(using: .utf8)!), withName: key)
            

            for fileURL in arrayURLToUpload
                print("fileURL: \(fileURL)")
                multipartFormData.append(fileURL, withName: "file[]")
            
        ,
            to: UPLOAD_URL,
            encodingCompletion:  encodingResult in
                switch encodingResult 
                case .success(let upload, _, _):

                    /**TRACK PROGRESS OF UPLOAD**/
                    upload.uploadProgress  progress in
                        print("ECNTERFILENAME: \(progress.fractionCompleted)")

                        let progress = progress.fractionCompleted

                        // NOTIFICATION - UPLOAD PROGRESS
                        NotificationCenter.default.post(name: notifcationName, object: nil, userInfo: ["progress": progress])
                    
                    /***/


                    // 'responseJSON' FIRES WHEN UPLOAD IS COMPLETE
                    // IT ALSO TO FIRES WHEN THE IS INTERNET CONNECTIVITY ISSUES
                    upload.responseJSON  response in


                        // NOTIFICATION UPLOAD COMPLETE
                        NotificationCenter.default.post(name: uploadFinishName, object: nil, userInfo: ["response": response])
                    


                case .failure(let encodingError):
                    print("UPLOAD ERROR")
                    print(encodingError)
                
        
    )

第二个视图控制器:

override func viewDidLoad() 
    super.viewDidLoad()

    self.createUploadObserver()
    self.createUploadFinishObserver()

    if txtLabelOutlet == nil // WHEN IMAGE('tickok') HAS REPLACED 'txtLabelOutlet'
        reformTxtLabel()
    


    self.infoLabelOutlet.textColor = UIColor.black // CAN BE RED WHEN NETWORK CONNECTION IS LOST
    self.progressOutlet.progress = 0   




func createUploadObserver()
    print("createUploadObserver ..")
    NotificationCenter.default.addObserver(forName: notifcationName, object: nil, queue: OperationQueue.main)  (notification) in

        guard
            var arrayN = notification.userInfo as? [String:Double],
            let num = arrayN["progress"] else
                print("no valid data")
                return
        
        // UPDATE PROGRESS BAR
        let progress = Float.init(num)
        self.progressOutlet.progress = progress

        // UPDATE LABEL
        let percent = Int(progress*100)
        print("percent: \(percent)")


        if let progressOut = self.txtLabelOutlet
            print("OUTLET EXISTS!")
            progressOut.text = "\(percent)%"
        else
            print("OUTLET DOES NOT EXIST")
        
    





func createUploadFinishObserver()
    print("createUploadFinishObserver ..")

    NotificationCenter.default.addObserver(forName: uploadFinishName, object: nil, queue: OperationQueue.main)  (notification) in

        print("notification.userInfo: \(notification.userInfo)")

        guard let response = notification.userInfo as? [String: DataResponse<Any>] else
            print("Error completion response")
            return
        

        guard
            let respObj = response["response"] as? DataResponse<Any>,
            let result = respObj.result as? Result<Any> elsereturn


        if let value  = result.value
            print("value: \(value)")
        

        if result.description == "SUCCESS"
            // UPLOAD COMPLETE
            // SHOW VIDEO CAPTURE
            print("upload success")


            if let progressOut = self.txtLabelOutlet
                print("OUTLET EXISTS - REMOVE FROM SUPERVIEW")
                progressOut.removeFromSuperview()
            else
                print("OUTLET DOES NOT EXIST to remove from superview")
            

            // ADD GREEN TICK IMAGE TO SHOW UPLOAD SUCCESS PROGRAMTICALLY
            let image = UIImage.init(named: "tickok")
            self.showCompleteTickImage(image: image!, completion: 

                // DELAY EXECUTION OF DIMISS POPUP BY 2 SECONDS
                DispatchQueue.main.asyncAfter(deadline: .now() + 1) 
                    print("DISMISS PROGRESS POPUP")
                    // DISMISS POUP AND SHOW IMAGE CAPTURE AGAIN
                    self.performSegue(withIdentifier: "inwindme2", sender: self)

                
            )


        else
            // HANDLE UPLOAD FAIL
            print("upload fail")
            self.infoLabelOutlet.text = "Network Connection Lost"
            self.infoLabelOutlet.textColor = UIColor.red
        
    

【问题讨论】:

【参考方案1】:

可能是交换

self.createUploadFinishObserver()
self.createUploadObserver()

由于上传小文件时的popupVC好像还没有注册,所以finish post出现在observe之前,你也可以在那个popup完成的时候开始上传,

self.present(popup,animated:true) 
  // start upload

如果继续

self.performSegue(///// 
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) 
  // start upload 

NotificationCenter 工作,你的应用逻辑必须100% 确定post 发生在observe 之后

【讨论】:

参考你的回答,我可以问一个与观察进度有关的问题吗?其实我正在为此努力奋斗。

以上是关于文件上传进度的通知观察者模式仅在文件很大时才有效 - swift?的主要内容,如果未能解决你的问题,请参考以下文章

单击通知行为仅在应用程序在后台运行时才有效?

iOS:推送通知仅在应用程序在前台运行时才有效

Cordova,onResume() 仅在我包含 alert() 时才有效

异步/等待仅在读取文件时才是有效的异步函数[重复]

为啥 rewrite_rule 仅在文件夹存在时才有效?

为啥我的 C# Xml 代码仅在我枚举变量 enumerable 时才有效