简体   繁体   English

如何添加UIViewController作为在以编程方式创建的UIView中创建的UIButton操作的目标?

[英]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的子类,那么您可以通过以下两种方式之一执行此操作:

  1. 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的方法

  2. 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.

相关问题 如何以编程方式将约束添加到以编程方式创建的UIView? - How to add constraints programmatically to a programmatically created UIView? 在理解以编程方式创建的UIView和UIViewController时需要帮助 - Need help in understanding programmatically created UIView and UIViewController 以编程方式创建时 UIViewController 不明确位置的 UIView - UIView of a UIViewController ambiguous position when created programmatically 将动画添加到以编程方式创建的UIview - add animation to UIview created programmatically 将按钮添加到以编程方式创建的UIView - Add Button to UIView Created Programmatically 如何在某些情况下更改以编程方式创建的UIButton的标题和操作 - How to change the title and action of a programmatically created UIButton on some condition UIButton目标是UIViewController而不是自定义UIView - UIButton target to be UIViewController not custom UIView 我如何向放置在UIStackView中的以编程方式创建的UIButton添加约束 - How do I add constraints to a programmatically created UIButton placed in a UIStackView 如何在UIViewController中访问由UIView的子类创建的对象 - How to access an object created by a subclass of UIView in a UIViewController 添加“完成”按钮以关闭以编程方式创建的UIViewController - Add a “Done” button to dismiss a programmatically created UIViewController
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM