如何检测整个viewcontroller上的用户交互

时间:2017-09-26 14:59:02

标签: ios swift swift3

我想检测UIViewController上的用户交互,如

  1. 编辑文本字段
  2. 从图库中选择图片
  3. 选择器视图选择
  4. 当用户离开页面时,它会缩进显示“您可能会丢失已输入的数据”的通知。可以回按钮。

    已经看到很多答案,但我需要最好和最恰当的方式来实现这个功能。

8 个答案:

答案 0 :(得分:7)

我的两分钱。

  • 你在问什么是实现非iOS行为,例如参见iOS prefs:很少要求用户小心或者他的数据会丢失。

  • iOS逻辑通常是:

    a)自动保存每个数据(以帮助用户..)并保存它

    b)在用户移动时收集数据,最后在保存或丢弃时收集数据

    c)iOS用户在他的“DNA”中有这种行为,所以要求保存是奇怪的......似乎是windows风格的UI使用。

    d)作为程序员,你想要实现的东西有点冗长,因为你没有关注Apple HIG,所以没有特定的调用来实现它。 其他人说的一般是正确的,你必须映射多个回调/代表。

答案 1 :(得分:2)

在Swift中使用的最佳方法是利用快速属性观察器。 我们假设您拥有用户个人资料视图:

  • 首先输入姓氏和中间名字段
  • 用于选择和显示用户图片的图片视图
  • 从选择器视图中选择日期的出生日期字段

您的模型会看起来:

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
            }
        }
    }
}

此处,模型具有状态变量 isUpdated ,只要任何属性修改为新值,就会跟踪模型状态更改 - 检查用户操作是否确实改变了模型中的现有值。

每当您启动个人资料屏幕时,您都可以将 isUpdated 设置为 false ,以便您可以在每次启动个人资料视图时跟踪更新的个人资料数据。

如果从服务器填充此模型,则在每次获取后,您可以重置模型状态(isUpdated标志),然后可以跟踪任何进一步的更改。

希望它有所帮助。

答案 2 :(得分:2)

主要问题是 - 用户可以进行更改但成为同一个对象。意味着改变10500次提交并选择开始时的相同。最近更新了吗?我猜不是!

如何获得差异? - 比较哈希!怎么做 ? - 使用" =="。那一切。

一些抽象代码。

  1. 覆盖后退按钮。 (是的,它的不良做法,但没有记录的方式来拥有后退按钮过程)

  2. 制作差异

  3. 显示提醒

  4. 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 ! } }

答案 3 :(得分:1)

用它来做。这是针对特定VC中的整个屏幕。如果要检测用户与特定UI元素的交互,则每个元素都有不同的方法。例如,文本视图具有它自己的委托方法,以检测某些内容何时修改或更改或触摸它。

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

对于滚动,您可以使用此方法

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    <#code#>
}

func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
    <#code#>
}

答案 4 :(得分:1)

您可以在显示视图控制器时保存viewcontroller上的数据,按下后退按钮可以检查输入字段中的当前数据是否与您保存的数据不同。您可以显示未保存的弹出窗口data.I认为它应该有所帮助。

答案 5 :(得分:1)

通过将滚动视图的userInteractionEnabled设置为NO,视图控制器将开始接收触摸事件,因为UIViewController是UIResponder的子类。您可以在视图控制器中覆盖这些方法中的一个或多个以响应这些触摸:

touchesBegan:withEvent:

touchesMoved:withEvent:

touchesEnded:withEvent:

touchesCancelled: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's 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's 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!")
            }
        }
    }

}

如果没有,请告诉我

答案 6 :(得分:0)

  1. 创建一个布尔标志以显示当前屏幕状态
  2. 使用委托方法更新屏幕状态
  3. 检查用户离开屏幕前的状态

答案 7 :(得分:0)

也许尝试在主视图中添加命中测试创建一个自定义容器来保存视图。这种方法非常简单易用,应该能够捕获任何触摸(按钮,文本字段,滚动等)

 override func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool {

     // Do whatever you need to in here

}

OR 使用生命值获取某种UIView触摸

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

}