How to detect user interactions with an entire view manager

I would like to detect user interactions in a UIViewController, for example

  • Editing Text Fields
  • Select image from gallery
  • View Mode Selection

With its indentation, a notification like “You may lose the data that you entered” is displayed when the user leaves the page. A button can be pressed.

I saw a lot of answers, but I need a better and correct way to perform this function.

+5
source share
8 answers

my two cents.

  • what you ask is to implement the behavior of NON-iOS, see, for example, prefs iOS: it is very rare to ask the user to be careful or his data will be lost.

  • iOS logic usually:

    a) automatically save all data (to help the user ..) and save it

    b) collect data when the user moves, and finally save or discard him at the end

    c) The iOS user has this behavior in his “DNA”, so it’s strange to ask to save ... it seems like using a Windows-style user interface.

    d) as the programmer you want to implement is a little longer since you are not following the Apple HIG, so there is no specific call to receive it. What the other guys are saying is generally correct, you need to match multiple callbacks / delegates.

+7
source

The best way to use Swift is to take advantage of the fast property observer. Suppose you have a user profile profile:

  • First enter the last and middle name to enter
  • Image to select and display user image
  • Date field to select a date from the picker view

Your model will look like 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, the model has the isUpdated state variable , which monitors the change in the state of the model whenever a property is changed to a new value - we checked whether the user’s action really changed the existing value in the model.

When you launch the profile screen, you can set isUpdated to false so that you can keep track of updated profile data each time you launch the profile view.

OR

If you populate this model from the server, then after each selection, you can reset the state of the model (isUpdated flag), which then can track any further changes.

Hope this helps.

+2
source

The main problem is that the user could make changes, but became the same object. Funds change 10,500 times and choose the same as at startup. Updated? I think no!.

How to get diff? - Compare the hash! How to do it? - use "==". All this.

A bit of abstract code.

  • Cancel back button. (Yes, its a bad practice, but there is no documented way to own a back button click)

  • Make 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 ! } } 
+2
source

Use it to do it. This is for the entire screen in a specific VC. If you want to detect user interaction with a specific user interface element, there are different methods for each element. For example, a text view has its own delegate method for detecting when something has changed or changed it or touched it.

 override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { super.touchesBegan(touches, with: event) } 

You can use this method to scroll.

 func scrollViewDidScroll(_ scrollView: UIScrollView) { <#code#> } func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { <#code#> } 
+1
source

you can save the data that is in the view manager when the view manager is displayed, and after clicking the back button, you can check if the current data is flowing in the input fields than the one you saved .. you can display pop-ups of unsaved data.I think this should help.

+1
source

By setting userInteractionEnabled to NO to view scrolling, the view controller will begin to receive touch events, since the UIViewController is a subclass of UIResponder. You can override one or more of these methods in your view controller to respond to these touches:

touchhesBegan: withEvent:

touchhesMoved: withEvent:

touchesEnded: withEvent:

touchCancelled: withEvent:

 class ViewController: UIViewController { @IBOutlet weak var scrollView: UIScrollView! @IBOutlet weak var textView: UITextView! @IBOutlet weak var lableView: UILabel! @IBOutlet weak var textField: UITextField! var arrayViews = NSMutableArray() override func viewDidLoad() { super.viewDidLoad() arrayViews.add(textView) arrayViews.add(lableView) arrayViews.add(textField) } override func touchesBegan(touches: NSSet!, withEvent event: UIEvent!) { touched(touches) } override func touchesMoved(touches: NSSet!, withEvent event: UIEvent!) { touched(touches) } func touched(touches: NSSet!) { // Get the first touch and its location in this view controller view coordinate system let touch = touches.allObjects[0] as UITouch let touchLocation = touch.locationInView(self.view) for viewLocate in arrayViews { // Convert the location of the obstacle view to this view controller view coordinate system let viewLocateFrame = self.view.convertRect(viewLocate.frame, fromView: viewLocate.superview) // Check if the touch is inside the obstacle view if CGRectContainsPoint(viewLocateFrame, touchLocation) { println("Touch!") } } } } 

This should work, please let me know if it doesn’t

+1
source
  • create a boolean flag to display the current state of the screen
  • Use delegate methods to update screen state.
  • check the status before the user leaves the screen.
0
source

Perhaps try either adding tests with a kick to the main view , or by creating a custom container for storing views. This approach is quite simple and easy to use and should capture any touch (buttons, text fields, scrolls, etc.).

  override func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool { // Do whatever you need to in here } 

OR use the hit point to select some UIView affected

 override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? { let subview = super.hitTest(point, withEvent: event) return subview == self.nextPageBtn || subview == self.backPageBtn ? subview : nil } 
0
source

Source: https://habr.com/ru/post/1272138/


All Articles