I would like to detect the user interactions on a UIViewController like
Its indented to show a notification like "You may lose data you have entered" when user goes out of page. Can be back button.
Have seen many answers but i need the best and proper way of doing this functionality.
The view's window property is non-nil if a view is currently visible, so check the main view in the view controller: Invoking the view method causes the view to load (if it is not loaded) which is unnecessary and may be undesirable. It would be better to check first to see if it is already loaded.
Create a new IBOutlet called shakeButton for your storyboard button in your ViewController. swift file. Select the shake button in Interface Builder. Then hold down the control button ( ⌃ ) and click-drag from the storyboard button into your ViewController.
To create a new view controller, select File->New->File and select a Cocoa Touch Class. Choose whether to create it with Swift or Objective-C and inherit from UIViewController . Don't create it with a xib (a separate Interface Builder file), as you will most likely add it to an existing storyboard.
my two cents.
what are you asking is to implement a NON-iOS behaviour, see for example iOS prefs: is very rare to ask user to be careful or his data will be lost.
the iOS logic is usually:
a) automatically save every data (to help user..) and save it
b) collect data as user moves, and eventually at the end save or throw it away
c) iOS user has in his "DNA" this kind of behaviour, so is weird to ask to save... it seems windows-style use of UI.
d) as a programmer what You want to implement is a bit lengthy, as You are not follow Apple HIG, so there is no specific call to get it. What other guys are saying is generally correct, you have to map multiple callbacks/delegates.
That main problem is - user could make changes but become same object. Means change 10500 times filed and select same that was on start. Is Recent Updated ? I guess no !.
How to get diff ? - Compare a hash ! How to do that ? - use "==". That all.
A bit of abstract code.
Override back button. (Yeah, its bad practice but there is not documented way to own back button process)
Make a diff
Show alert
struct CustomModel : Hashable, Equatable {
var name : String
//your custom model
public var hashValue: Int {
return name.hashValue
}
static func ==(lhs: CustomModel, rhs: CustomModel) -> Bool {
return lhs.hashValue == rhs.hashValue
}
}
class VoteViewController : UIViewController {
private var originalModel : CustomModel!
private var mutableCopy : CustomModel!
override func viewDidLoad() {
super.viewDidLoad()
mutableCopy = originalModel
navigationItem.hidesBackButton = true
let newBackButton = UIBarButtonItem(title: "Back", style: UIBarButtonItemStyle.plain, target: self, action: #selector(VoteViewController.back(sender:)))
navigationItem.leftBarButtonItem = newBackButton
}
func back(sender: UIBarButtonItem) {
// ChechDataModification
guard mutableCopy == originalModel else {
presentAlertPop()
return
}
_ = navigationController?.popViewController(animated: true)
}
func presentAlertPop(){
//You may lose data you have entered !
}
}
The best way to use in Swift is to take the advantage of swift property observer. Let's assume you have user profile view with:
Your model will look this:
struct ProfileModel {
var isUpdated: Bool = false
var firstName: String {
willSet {
if newValue != firstName {
isRecentUpdated = true
}
}
}
var middleName: String {
willSet {
if newValue != middleName {
isRecentUpdated = true
}
}
}
var lastName: String {
willSet {
if newValue != lastName {
isRecentUpdated = true
}
}
}
var profilePhoto: URL {
willSet {
if newValue != profilePhoto {
isRecentUpdated = true
}
}
}
var dob: Date {
willSet {
if newValue != dob {
isRecentUpdated = true
}
}
}
}
Here, model has state variable isUpdated which track model state change whenever any of property modified to new value - have kept check if indeed user action has changed existing value in model.
Whenever, you launch profile screen you can set isUpdated to false so that you can track updated profile data on each launch of profile view.
OR
If you are populating this model from server then after every fetch you can reset the model state (isUpdated flag) which then can track any further change.
Hope it helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With