2017-09-26 75 views
5

我想检测用户交互上一个UIViewController像如何检测上的整体视图 - 控制用户交互

  1. 编辑文本字段
  2. 从画廊
  3. 选择图片
  4. 选择器视图选择

当用户离开页面时,它会缩进显示通知,如“您可能会丢失您输入的数据”。可以返回按钮。

已经看到很多答案,但我需要做这个功能的最佳和正确的方式。

+0

解决方案是否应该假定它知道屏幕上究竟是什么,或者您希望为包含问题中提到的控件的所有可能的VC提供通用解决方案? –

+0

它应该是可重复使用的,以便可以应用于许多视图控制器以及 – Saranjith

回答

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#> 
} 
+0

如果用户滚动视图控制器,我认为 – Saranjith

+0

我添加了一个委托方法,您可以使用它来检测用户是否也滚动。 –

1

可以保存在那里的视图 - 控制在视图 - 控制被提供的数据,并且在按压后退按钮,你可以检查当前的数据在输入字段是不同的,你保存..你可以弹出未保存的数据。我认为这应该有所帮助。

2

在Swift中使用的最好方法是利用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,使您可以跟踪每个发射纵断面图的更新配置文件数据。

OR

如果你再经过填充每次从服务器这种模式获取可以重置模型状态(isUpdated标志),然后可以跟踪任何进一步的变化。

希望它有帮助。

2

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

如何获取diff? - 比较哈希!怎么做 ? - 使用“==”。这一切。

一点抽象的代码。

  1. 覆盖后退按钮。 (是的,它是不好的做法,但也未记录的方式将自己后退按钮过程)

  2. 做一个差异

  3. 显示警报

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

我的两分钱。

  • 什么是你问的是实现一个非iOS的行为,例如参见iOS的首选项:是非常罕见的问用户要小心或他的数据将会丢失。

  • iOS的逻辑通常是:

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

    b)中收集的数据作为用户移动,并最终在结束保存或把它扔掉

    c)iOS用户在他的“DNA”中有这种行为,所以要求保存......这似乎很奇怪,它似乎是Windows的Windows风格的使用。 d)作为程序员你想要实现的东西有点冗长,因为你没有遵循Apple HIG,所以没有具体的调用来获取它。 其他人说的通常是正确的,你必须映射多个回调/代表。

0
  1. 创建一个布尔标志,显示当前的屏幕状态
  2. 使用委托方法来更新屏幕状态
  3. 检查用户之前的状态离开屏幕
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!") 
      } 
     } 
    } 

} 

这应该工作,请让我知道,如果它不

0

也许可以尝试将主要视图的命中测试添加到创建自定义容器以容纳视图。这种方法是相当简单的,易于使用,并且应该抓住任何触摸(按钮,文本框,滚动等)

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

    // Do whatever you need to in here 

} 

使用的命中点来获取某种的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 

} 
相关问题