I have a customized UIView. I've added a tapGestureRecognizer into this UIView. Not through UIViewController, but within the UIView+Category class. I'm trying to use presentViewController() when this UIView is tapped. This is a UIView class, it doesn't allow presentViewController(). I'm aware that only UIViewController allows this function to be called. So have I mistakenly architectured my project? Is it better if I just add tapGestureRecognizer to this UIView not using category but just straight off from UIViewController? This UIView is going to be used elsewhere as well so it would save me a lot of code if I can make this happen. Thanks in advance.
There is two straight ways to do that 1) Notification(provided example is written in ObjC) 2) Delegation(provided example is written in Swift)
1) Use NSNotificationCenter to inform the UIViewController that the view belongs to
In your UIView+Category where the gesture recognized handler is defined there, post notification and in your UIViewController add an Observer
In UIViewController
// Define it at the top of your view controller
#define kViewDidClick @"ViewDidClick"
- (void)viewDidLoad {
...
[[NSNotificationCenter defaultCenter]
addObserver: self
selector: @selector(presentVC:)
name: kViewDidClick
object: nil];
}
- (void)presentVC: (NSNotification *)notification {
[self.presentViewController: vc animated: false completion: nil];
}
In your UIView+Category where you handle the gesture(for now I assume it's called handleGesture)
-(void) handleGesture: (UIGestureRecognizer *)gestureRecognizer {
[[NSNotificationCenter defaultCenter] postNotificationName: kViewDidClick object: nil];
}
2) you need to define a class that handle gesture and a protocol. This way you can handle all your gesture easily no need to define some methods in your UIView or UIViewController to handle gestures every time you want to handle gestures
GestureHandlerHelper.swift
import UIKit
/**
Handle gesture recognized by a UIView instance
*/
class GestureHandlerHelper {
var delegate: SelectionDelegate?
// MARK: Initializer
init(delegate: SelectionDelegate) {
self.delegate = delegate
}
// MARK: Gesture Handler
/**
Handle gesture recognized by a UIView instance
*/
@objc func handleGesture(gestureRecongnizer: UIGestureRecognizer) {
println(self)
println(__FUNCTION__)
println(gestureRecongnizer)
if .Ended == gestureRecongnizer.state {
if nil != delegate? {
delegate?.didClick(gestureRecongnizer)
}
}
}
}
SelectionDelegate.swift
/**
Define a general rule for classes that handle gesture on views
*/
protocol SelectionDelegate {
func didClick(gestureRecognizer: UIGestureRecognizer)
}
In your UIViewController
class ViewController : UIViewController {
...
override func loadView() {
self.view = View(frame: UIScreen.mainScreen().bounds,
gestureHandlerHelper: GestureHandlerHelper(delegate: self))
}
...
}
extension ViewController : SelectionDelegate {
func didClick(gestureRecognizer: UIGestureRecognizer) {
self.presentViewController(SomeViewController(), animated: false, completion: nil)
}
}
In your UIView
init(frame: CGRect, gestureHandlerHelper: GestureHandlerHelper) {
...
var tapGestureRecognizer = UITapGestureRecognizer(target: gestureHandlerHelper, action: "handleGesture:")
...
}