iOS Create Post UI with Progress Updates
Fullstack Social iOS NodeJS REST
Having tested out the upload feature from our iOS application, its time to create a better looking UI to complete the entire process. Let's go ahead and create a brand new controller that allows us to enter some post body text in a UITextView component. Finally I'll include some code that monitors the upload progress while we send this post object to our server.

Comments (6)
Dustin Doosun Yang
4 years ago
in CreatePostController, self.homeController?.fetchPosts() is never get triggered. After dismiss got executed, it skips fetchPosts() part. self.dismiss(animated: true) { self.homeController?.fetchPosts() } Not sure what I did wrong. Any advise?
Dustin Doosun Yang
4 years ago
As a workaround, I am doing override func viewWillAppear(_ animated: Bool) { fetchPosts() } . in HomeController to fetch the data automatically as screen appears
Brian Voong
4 years ago
Dustin Doosun Yang
4 years ago
Thanks so much. That works.. I was missing createPostController.homeController = self
Mohammed Salem
4 years ago
I'm having this error whenever i post or fetch on my iOS app. Any reason why? Sending 500 ("Server Error") response: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client at ServerResponse.setHeader (_http_outgoing.js:470:11)
gerkov77
3 years ago
Same here.
bmilts
3 years ago
In createPostController, the postBodyTextView behaviour seems to have changed. let postBodyTextView = UITextView(text: nil, font: .systemFont(ofSize: 14)) Seems to bring up this error: "Incorrect argument labels in call (have 'text:font:', expected 'frame:textContainer:')" The fix xcode offers is: let postBodyTextView = UITextView(frame: nil, textContainer: .systemFont(ofSize: 14)) Doesn't seem to work though. Any ideas?
bmilts
3 years ago
Pretty stuck on this bit. Same issue occurs in xcode when downloading the project code. I will continue on with the vue.js parts but please let me know when you have any ideas. Appreciate your time! Thanks :)
Malikov_Vladimir
3 years ago
Hi there. You can change this line. Something like this one: let postBodyTextView: UITextView = { let tf = UITextView() tf.font = .systemFont(ofSize: 14) return tf }() It works.
joeypozzyclinch
3 years ago
Thank you Malikov!! That helped
omari
3 years ago
Hi Brian, if a user selects an image he can't change it. This is not very user friendly. Can you please show us how to add this feature.
AlfieLBTA
3 years ago
I would add a replace button that invokes the imagepicker method in this new controller and the picker did finish method would replace the selectedImage.image with the new one.
BButter18
3 years ago
Hello Brian, I know you are busy during these times. Thanks for the great content. I noticed with the new Alamofire 5.1.0 that a lot of the upload API code has changed a lot. I was wondering if you would post updated syntax or should we just run the 4.8.1 version that you are using in the videos in our Podfile? Obviously the latter would be easier...Thanks in advance.
BButter18
3 years ago
*4.8.2
Christopher J. Roura
2 years ago
I apologize in advance for the very long post but I have both a question and potential solution. As many people have pointed out Alamofire has released 5.1.0. The syntax has changed and while I am not 100 % sure I followed it correctly I would like to share what I have. What I would like to know is, is there any better way of doing this and is there any way to incorporate .uploadProgress portion in the success case so the upload percentage can update as the percent climbs. It just shows that it is done and doesn't actually display a progress at the moment. Thank you for your time Brian and below is the code: @objc fileprivate func handlePost() { let url = "http://localhost:1337/post" let headers: HTTPHeaders = ["Content-type": "multipart/form-data", "Accept": "application/json"] let hud = JGProgressHUD(style: .dark) hud.indicatorView = JGProgressHUDRingIndicatorView() hud.textLabel.text = "Uploading" hud.show(in: view) guard let text = postBodyTextView.text else { return } AF.upload(multipartFormData: { (formData) in // Post Text formData.append(Data(text.utf8), withName: "postBody") // Post Image guard let imageData = self.selectedImage.jpegData(compressionQuality: 0.5) else { return } formData.append(imageData, withName: "imagefile", fileName: "Doesn'tMatterSoMuch", mimeType: "image/jpg") }, to: url, method: .post, headers: headers) .uploadProgress(queue: .main, closure: { progress in print("Upload Progress: \(progress.fractionCompleted)") DispatchQueue.main.async { hud.progress = Float(progress.fractionCompleted) hud.textLabel.text = "Uploading\n\(Int(progress.fractionCompleted * 100))% Complete" } }).responseJSON(completionHandler: { data in }).response { (dataResp) in switch dataResp.result { case .success(let result): hud.dismiss() if let err = dataResp.error { print("Failed to hit server:", err) return } if let code = dataResp.response?.statusCode, code >= 300 { print("Failed to upload with status: ", code) return } print("Successfully created post, here is the response:") self.dismiss(animated: true) { self.homeController?.fetchPosts() } case .failure(let err): print("upload err: \(err)") } } }
HELP & SUPPORT