Ios 如何将UIViewController添加为以编程方式创建的UIView中创建的UIButton操作的目标?
我以编程方式创建了一个Ios 如何将UIViewController添加为以编程方式创建的UIView中创建的UIButton操作的目标?,ios,iphone,objective-c,uiview,uibutton,Ios,Iphone,Objective C,Uiview,Uibutton,我以编程方式创建了一个ui视图,并添加了一个ui按钮,作为它的子视图。 我希望UIViewController成为该按钮操作的目标。 我该怎么做? 如果它是由Interface Builder创建的,那么使用iAction就很容易了。您可以将目标和操作添加到按钮 [button addTarget:controller/self action:@selector(onTapButton) forControlEvents:UIControlEventTouchUpInside]; 目标是控制器
ui视图
,并添加了一个ui按钮
,作为它的子视图。我希望
UIViewController
成为该按钮操作的目标。我该怎么做?
如果它是由Interface Builder创建的,那么使用
iAction
就很容易了。您可以将目标和操作添加到按钮
[button addTarget:controller/self action:@selector(onTapButton) forControlEvents:UIControlEventTouchUpInside];
目标是控制器,所以若您想在当前控制器中处理触摸事件,请使用self。另一方面,您应该有一个指向控制器obj的指针/引用,并使用该引用而不是self。
onTapButton
是选择器,当用户点击按钮时将调用该选择器onTapButton
不接受任何参数,如果要与参数一起使用,请使用onTapButton:
- (IBAction/void)onTapButton{
}
-(IBAction/void)onTapButton:(id)sender{
}
注:
更好的方法是处理这个问题,就是使用委托模式,在self中有一个target,即什么样的类,然后调用delegate,控制器应该实现这个委托。保持对控制器的直接引用不是好的做法。如果要以编程方式将按钮添加到UIView的子类中,则可以通过以下两种方式之一执行此操作:
[viewSubclass.buttonName addTarget:self action:@selector(buttonTapped:) forControlEvents:UIControlEventTouchUpInside];
这将把按钮的目标设置为一种buttonTapped方法:在viewController.m中@protocol ButtonProtocolName
- (void)buttonWasPressed;
@end
@interface someViewController : UIViewController <SomeButtonProtocolName>
为委托创建属性:
@property (nonatomic, assign) id <ButtonProtocolName> delegate;
SomeView *view = ... // Init your view
// Set the delegate
view.delegate = self;
在buttonTapped:方法中,调用委托方法:
- (void)buttonTapped:(id)sender {
[self.delegate buttonWasPressed];
}
在viewController.h中,您需要确保它符合协议:
@protocol ButtonProtocolName
- (void)buttonWasPressed;
@end
@interface someViewController : UIViewController <SomeButtonProtocolName>
最后,将委托方法按钮添加到viewController.m:
- (void)buttonWasPressed {
// Put code here for button's intended action.
}
更新以提供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.
}
}
此外,下面是一个使用闭包而不是委托的快速示例。(这种方法也可以使用块在ObjC中实现。)
现在,如果您使用的是UINavigationController,则按钮按下功能将
- (void)buttonPressed:(id)sender
{
NewViewController *newVC = [NewViewController new];
[self.navigationController pushViewController:newVC animated:YES];
}
如果未使用导航控制器,则
- (void)buttonPressed:(id)sender
{
NewViewController *newVC = [NewViewController new];
[self presentViewController:newVC animated:YES completion:nil];
}
我们也可以在没有代表的情况下实现这一目标 在
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;
}
说明:-在initWithFrame方法中,我正在加载当前nib。加载nib意味着初始化它包含的所有子视图。获取同一类的完全初始化视图并分配给self。返回包含完全初始化的uiview的self
在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];
斯威夫特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()
}
在视图控制器中
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
}
}
希望这有帮助。快乐编码:代码,显示一些代码。使stackoverflowers更容易帮助您这行不通。OP正在视图的子类中添加按钮,因此self将是视图,而不是视图控制器。在这种情况下,他应该引用控制器并用视图控制器替换self。C_X:我知道您做出此响应已经几个月了,但我想指出,您的第二条评论实际上违反了MVC。视图本身不应代表viewController,因此在视图子类中使用对viewController的引用是个坏主意。最佳实践是实现委托,以便viewController在调用某个方法时可以为视图执行操作。(接受的答案中有一个例子。)感谢您的回答,我还应该如何将UITextField委派设置为UIViewController?如果视图中有UITextField,则可以使用与上面所示相同的方法进行设置。但是,如果使用选项2,则必须将视图子类设置为textfield委托,然后使用视图的委托将更改传达给viewController。在文本字段的情况下,使用选项1会更容易。这比需要的复杂得多。我在这里回答了一个类似的问题:@leftspin,依我看,你的链接应该被认为是一种不好的做法,因为它没有明确说明预期的行为应该是什么。当然,它减少了一些锅炉板代码,但模糊了实现。@Aroncittendon我的答案是简单地使用责任链模式(),它“促进松散耦合的思想,这被认为是编程的最佳实践”,并且是响应者链背后的核心思想。它不比使用NSNotifications、委托,甚至(在某种意义上)方法重载更模糊实现;所有这些都是间接的技术,以促进松散耦合。有关良好的讨论,请参阅
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
}
}