J'ai une application dans laquelle un utilisateur télécharge un fichier en arrière-plan, ce qui prend généralement quelques secondes. Le téléchargement est lancé lorsqu'ils appuient sur un bouton "Terminé" et cela supprime également le contrôleur de vue. Ce que je voudrais, c'est qu'une alerte apparaisse lorsque le téléchargement est terminé. Je pensais que j'ajouterais simplement le code ci-dessous à la fonction de téléchargement mais cela ne fonctionne pas. Comment puis-je faire apparaître une boîte d'alerte pour confirmer que le téléchargement a réussi?
@IBAction func tapDone(_ sender: Any) { self.dismiss(animated: true, completion: nil) if let image = newImage { submit2Parse(image: image) } } func submit2Parse (image: UIImage) { if let pfImage = image2PFFile(image: image) { // Insert PFFile into parse server let submittedImage = PFObject(className: "Images") submittedImage["imageFile"] = pfImage submittedImage["type"] = "submittedFromUserHome" submittedImage["bride"] = brideSwitch.isOn submittedImage["groom"] = groomSwitch.isOn submittedImage["user"] = userSwitch.isOn submittedImage["picturePeriod"] = pickerSelected submittedImage["uploadedByUserId"] = PFUser.current()?.objectId ?? "" submittedImage["uploadedByUserName"] = PFUser.current()?.username ?? "" if !txtIsPlaceHolder { submittedImage["description"] = imageDescription.text } submittedImage.saveInBackground { (success, error) in if success { let message = "Save in bg worked" print(message) let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertController.Style.alert) alert.addAction(UIAlertAction(title: "Ok", style: UIAlertAction.Style.default, handler: { (action) in self.dismiss(animated: true, completion: nil) })) self.present(alert,animated: true, completion: nil) } else { print(error?.localizedDescription ?? "") } } } }
Le code me donne cette erreur de construction:
Utilisation implicite de «soi» en clôture; utiliser «soi». pour rendre la sémantique de capture explicite
3 Réponses :
Dans votre méthode tapDone
, vous devez utiliser le completion
du licenciement de votre contrôleur, comme ceci:
self.dismiss(animated: true) { if let image = newImage { self.submit2Parse(image: image) } }
Ceci signifie seulement que le self.submit2Parse (image: image)
sera UNIQUEMENT exécuté après avoir fermé le contrôleur. De plus, l'erreur
Utilisation implicite de «soi» en clôture; utiliser «soi». faire la capture sémantique explicite
signifie seulement que vous devez utiliser self.
pour appeler explicitement une variable ou une méthode lorsque vous êtes dans une fermeture. Donc, votre submit2Parse ...
serait maintenant comme ceci:
self.submit2Parse (image: image)
.
Si j'ai bien compris votre question, vous souhaitez ignorer votre SecondViewController
lorsque l'utilisateur appuie sur le bouton tapDone
. Et après cela, une fois le téléchargement de votre image terminé, vous souhaitez présenter une alerte de réussite.
Mais si vous ignorez
le bouton une fois appuyé, vous ne recevrez aucune alerte car votre SecondViewController code> n'est plus dans la
hiérarchie des fenêtres
et si vous essayez de présenter l'alerte, vous obtiendrez une erreur dans la console comme:
Tentative de présentation sur dont la vue n'est pas dans le hiérarchie des fenêtres!
Pour résoudre ce problème, vous devez présenter une alerte de votre premier contrôleur de vue qui apparaîtra après avoir fermé votre deuxième contrôleur de vue et vous pouvez y parvenir avec délégué
. p >
Prenons l'exemple ci-dessous:
Commencez par déclarer un protocole
en dehors de votre FirstViewController
:
self.delegate?.uploadSuccess(message: "your message")
Que faire si je ne sais pas quel serait le contrôleur de vue actuel? Je rejette un certain contrôleur de vue, mais l'utilisateur aurait facilement pu passer à un autre pendant le téléchargement. Je sais que j'ai vu des applications alerter l'utilisateur après un téléchargement, comme lorsque Netflix vous informe que vos téléchargements sont terminés. N'existe-t-il pas un moyen de changer mon code pour que l'alter soit appelé quelle que soit la file d'attente actuellement active?
Si tel est le cas, vous pouvez présenter une alerte depuis AppDelegate. Vérifiez ceci: stackoverflow.com/questions/36155769 /…
Lorsque vous déposez la fonction ci-dessous dans le viewController qui lance le téléchargement des données en arrière-plan, puis que vous appelez cette fonction dans la fermeture qui se déclenche lorsque la soumission se termine, il est capable de créer avec succès une alerte même si le contrôleur de vue initial était ignoré (ou longtemps ignoré s'il s'agissait d'un long téléchargement).
// This is the function that performs my background upload func submit2Parse (image: UIImage) { if let pfImage = image2PFFile(image: image) { // Insert PFFile into parse server let submittedImage = PFObject(className: "Images") submittedImage["imageFile"] = pfImage submittedImage["imageCreateDt"] = newImageCreateDate submittedImage["type"] = "submittedFromUserHome" submittedImage["bride"] = brideSwitch.isOn submittedImage["groom"] = groomSwitch.isOn submittedImage["user"] = userSwitch.isOn submittedImage["picturePeriod"] = pickerSelected submittedImage["uploadedByUserId"] = PFUser.current()?.objectId ?? "" submittedImage["uploadedByUserName"] = PFUser.current()?.username ?? "" if !txtIsPlaceHolder { submittedImage["description"] = imageDescription.text } // Get the image timestamp, every photo has one // How do you get the thumbnail image too? submittedImage.saveInBackground { (success, error) in if success { let message = "Save in bg worked" print(message) self.showAlertFromAppDelegates() } else { print(error?.localizedDescription ?? "") } } } } // This is the function that creates the alert func showAlertFromAppDelegates(){ var topWindow: UIWindow? = UIWindow(frame: UIScreen.main.bounds) topWindow?.rootViewController = UIViewController() topWindow?.windowLevel = UIWindow.Level.alert + 1 let alert: UIAlertController = UIAlertController(title: "Upload Complete", message: "Your image was successfully submitted!", preferredStyle: .alert) alert.addAction(UIAlertAction.init(title: "OK", style: .default, handler: { (alertAction) in topWindow?.isHidden = true topWindow = nil })) topWindow?.makeKeyAndVisible() topWindow?.rootViewController?.present(alert, animated: true, completion:nil) }