[英]How to add UIViewController as target of UIButton action created in programmatically created UIView?
I created a UIView
programmatically and added a UIButton
as it's subview. 我以编程方式创建了一个
UIView
并添加了一个UIButton
作为它的子视图。
I want a UIViewController
to be the target of that button action. 我希望
UIViewController
成为该按钮操作的目标。
How would I do that? 我该怎么办?
If it was created by Interface Builder then it was easy by using IBAction
. 如果它是由Interface Builder创建的,那么使用
IBAction
很容易 。
If you are adding the button programmatically to a subclass of UIView, then you can do it one of two ways: 如果您以编程方式将按钮添加到UIView的子类,那么您可以通过以下两种方式之一执行此操作:
You can make the button a property of the view, and then in the viewController that instantiates the view you can set the target of the button as follows: 您可以使按钮成为视图的属性,然后在实例化视图的viewController中,您可以设置按钮的目标,如下所示:
[viewSubclass.buttonName addTarget:self action:@selector(buttonTapped:) forControlEvents:UIControlEventTouchUpInside];
This will set the button's target to a method of buttonTapped: in the viewController.m 这会将按钮的目标设置为viewController.m中buttonTapped的方法
You can create a protocol in your subview, which the parent viewController will conform to. 您可以在子视图中创建协议,父视图控件将遵循该协议。 In your view, when you add your button set it to call a method in your view.
在您的视图中,当您添加按钮时,将其设置为在视图中调用方法。 Then call the delegate method from that view so that your viewController can respond to it:
然后从该视图中调用delegate方法,以便viewController可以响应它:
In the top your view subclass .h create the protocol: 在顶部您的视图子类.h创建协议:
@protocol ButtonProtocolName
- (void)buttonWasPressed;
@end
Create a property for the delegate: 为委托创建属性:
@property (nonatomic, assign) id <ButtonProtocolName> delegate;
In the subclass .m set your button selector: 在子类.m中设置按钮选择器:
[button addTarget:self action:@selector(buttonTapped:) forControlEvents:UIControlEventTouchUpInside];
In the buttonTapped: method call the delegate method: 在buttonTapped:方法中调用委托方法:
- (void)buttonTapped:(id)sender {
[self.delegate buttonWasPressed];
}
In your viewController.h you'll need to make sure it conforms to the protocol: 在viewController.h中,您需要确保它符合协议:
@interface someViewController : UIViewController <SomeButtonProtocolName>
In your viewController.m when you init your subview, you'll have to set the delegate: 在初始化子视图时,在viewController.m中,您必须设置委托:
SomeView *view = ... // Init your view
// Set the delegate
view.delegate = self;
Finally, add the delegate method buttonWasPressed to the viewController.m: 最后,将delegate方法buttonWasPressed添加到viewController.m:
- (void)buttonWasPressed {
// Put code here for button's intended action.
}
Updated to provide Swift example 更新以提供Swift示例
// Simple delegate protocol.
protocol SomeViewDelegate: class {
// Method used to tell the delegate that the button was pressed in the subview.
// You can add parameters here as you like.
func buttonWasPressed()
}
class SomeView: UIView {
// Define the view's delegate.
weak var delegate: SomeViewDelegate?
// Assuming you already have a button.
var button: UIButton!
// Once your view & button has been initialized, configure the button's target.
func configureButton() {
// Set your target
self.button.addTarget(self, action: #selector(someButtonPressed(_:)), for: .touchUpInside)
}
@objc func someButtonPressed(_ sender: UIButton) {
delegate?.buttonWasPressed()
}
}
// Conform to the delegate protocol
class SomeViewController: UIViewController, SomeViewDelegate {
var someView: SomeView!
func buttonWasPressed() {
// UIViewController can handle SomeView's button press.
}
}
Additionally, here is a quick example using a closure instead of a delegate. 另外,这是一个使用闭包而不是委托的快速示例。 (This can approach also be implemented in ObjC using blocks.)
(这也可以使用块在ObjC中实现。)
// Use typeAlias to define closure
typealias ButtonPressedHandler = () -> Void
class SomeView: UIView {
// Define the view's delegate.
var pressedHandler: ButtonPressedHandler?
// Assuming you already have a button.
var button: UIButton!
// Once your view & button has been initialized, configure the button's target.
func configureButton() {
// Set your target
self.button.addTarget(self, action: #selector(someButtonPressed(_:)), for: .touchUpInside)
}
@objc func someButtonPressed(_ sender: UIButton) {
pressedHandler?()
}
}
class SomeViewController: UIViewController {
var someView: SomeView!
// Set the closure in the ViewController
func configureButtonHandling() {
someView.pressedHandler = {
// UIViewController can handle SomeView's button press.
}
}
}
You can add target and action to button. 您可以向按钮添加目标和操作。
[button addTarget:controller/self action:@selector(onTapButton) forControlEvents:UIControlEventTouchUpInside];
Target is controller so If you want to handle touch event in current controller use self. 目标是控制器所以如果你想在当前控制器中处理触摸事件使用自己。 Other wise you should have a pointer/reference to the controller obj, and use that reference instead of the self.
另外,你应该有一个指向控制器obj的指针/引用,并使用该引用而不是self。
onTapButton
is selector which will be called when user tap on the button. onTapButton
是选择器,当用户点击按钮时将调用该选择器。 onTapButton
do not taking any parameter, If you want to use with parameter use onTapButton:
onTapButton
不带任何参数,如果要与参数一起使用onTapButton:
- (IBAction/void)onTapButton{
}
-(IBAction/void)onTapButton:(id)sender{
}
NOTE: Better way is to handle this is to use delegation pattern, have target in self what ever class that is, and After that call delegate, and controller should implement that delegate. 注意:更好的方法是处理这是使用委托模式,在自己的类中有目标,然后调用委托,并且控制器应该实现该委托。 Keeping direct reference to the controller is not good practice.
直接参考控制器并不是一种好的做法。
[buttonName addTarget:self action:@selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
Now, if you are using UINavigationController your buttonPressed function will be 现在,如果你正在使用UINavigationController,你的buttonPressed函数将是
- (void)buttonPressed:(id)sender
{
NewViewController *newVC = [NewViewController new];
[self.navigationController pushViewController:newVC animated:YES];
}
If you are not using navigation Controller than 如果你没有使用导航控制器
- (void)buttonPressed:(id)sender
{
NewViewController *newVC = [NewViewController new];
[self presentViewController:newVC animated:YES completion:nil];
}
We can achieve this without delegates as well. 我们也可以在没有代表的情况下实现这一点。
In your CustomUIView.m
class, implement the following method:- 在
CustomUIView.m
类中,实现以下方法: -
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
NSArray *viewsInNib = [[NSBundle mainBundle]loadNibNamed:@"AddressAlertView" owner:self options:nil];
for (id view in viewsInNib) {
if ([view isKindOfClass:[self class]]) {
self = view;
break;
}
}
return self;
}
Explanation:- In initWithFrame method, I am loading the current nib.
说明: - 在initWithFrame方法中,我正在加载当前的nib。 Loading the nib means initialising all the sub view which it contains.
加载nib意味着初始化它包含的所有子视图。 Get the fully initilised view of same class and assigned to self.
获取同一类的完全初始化视图并分配给self。 Return self which contains fully initilised uiview.
返回包含完全初始化uiview的self。
In your viewcontroller.m
file, write the below code to add custom uiview and set target of button:- 在你的
viewcontroller.m
文件中,编写下面的代码来添加自定义uiview并设置按钮的目标: -
UIWindow *mainWindow = [[[UIApplication sharedApplication]delegate]window];
AddressAlertView *objAddressAlertView = [[AddressAlertView alloc] initWithFrame:mainWindow.bounds];
[objAddressAlertView.btnCross addTarget:self
action:@selector(dummy)
forControlEvents:UIControlEventTouchUpInside];
if (objAddressAlertView)
[mainWindow addSubview:objAddressAlertView];
For Swift 4 对于Swift 4
class MyView: UIView {
weak var delegate: MyBtnDelegate?
var myBtn: UIButton = {
let myCustomButton = UIButton()
// Button UI code goes here
myCustomButton.addTarget(self, action: #selector(saveData), for: .touchUpInside)
return myCustomButton
}()
@objc func saveData() {
delegate?.doSomething()
}
In ViewController 在ViewController中
protocol MyBtnDelegate: class {
func doSomething()
}
class ViewController: UIViewController, MyBtnDelegate {
var customView = MyView()
override func viewDidLoad() {
super.viewDidLoad()
customView.delegate = self // Unless you add this line code won't be working
}
func doSomething() {
//Do whatever you want
}
}
Hope this helps. 希望这可以帮助。 Happy coding :]
快乐编码:]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.