Turning Swift compile-time safety into safety for your users

Sometimes good coding practices lead to good UX

Oleg Dreyman
Jan 16, 2018 · 4 min read

What happened?

final class Images {

private var images: [UIImage]

func image(at index: Int) -> UIImage {
return images[index]
}

func add(_ image: UIImage) {
images.append(image)
}

func delete(imageAt index: Int) {
images.remove(at: index)
}

}
@objc func didPressDeleteButton(sender: UIButton) {
images.delete(imageAt: currentImageIndex)
}

What’s the conventional solution for this?

So what’s the “right” solution?

struct UserConfirmationRequired {

private let performDestructiveAction: () -> ()

init(destructiveAction: @escaping () -> ()) {
self.performDestructiveAction = destructiveAction
}

func performWithUserConfirmation(alertTitle: String, alertMessage: String, alertDestructiveActionTitle: String, completion: @escaping (Bool) -> ()) {

// retrieving view controller to show alert from
guard let window = UIApplication.shared.delegate?.window else {
print("No window")
completion(false)
return
}
guard let viewController = window?.rootViewController else {
print("No view controller")
completion(false)
return
}

// creating and showing an alert
let alert = UIAlertController(title: alertTitle, message: alertMessage, preferredStyle: .actionSheet)

let cancel = UIAlertAction(title: "Cancel", style: .cancel, handler: { _ in completion(false) })

let destructive = UIAlertAction(title: alertDestructiveActionTitle, style: .destructive, handler: { _ in
self.performDestructiveAction()
completion(true)
})

alert.addAction(cancel)
alert.addAction(destructive)
viewController.present(alert, animated: true)
}

}
func deleteAction(ofImageAt index: Int) -> UserConfirmationRequired {
return UserConfirmationRequired(destructiveAction: {
self.images.remove(at: index)
})
}
@objc func didPressDeleteButton(sender: UIButton) {
let title = "Delete an image"
let message = "This action can't be undone. Are you sure?"
let delete = "Delete"
images.deleteAction(ofImageAt: currentImageIndex).performWithUserConfirmation(alertTitle: title, alertMessage: message, alertDestructiveActionTitle: delete) { (deleted) in
print("Deleted:", deleted)
}
}

AnySuggestion

Swift & iOS blog by Oleg Dreyman