如何连接带有单例的按钮数组?

发布于 2025-01-02 03:44:13 字数 3493 浏览 3 评论 0原文

我的 appDelegate,在 didFinishLaunchingWithOptions 方法中加载我的视图控制器,然后创建一个单例:

UIViewController *MainWinVC = [[p3VC alloc] init];
[[self window] setRootViewController:MainWinVC];
ansButSingleton *ansButs = [[ansButSingleton alloc] init]; 

ansButSingleton.h 如下所示:

#import <Foundation/Foundation.h>

@interface ansButSingleton : NSObject {

    // View objects:

    UIButton *Ans1;
    UIButton *Ans2;
    UIButton *Ans3;
    UIButton *Ans4;
    UIButton *Ans5;
    UIButton *Ans6;
    UIButton *Ans7;
    UIButton *Ans8;

    // Other objects:

    NSArray *ansButs;

}

@property (strong) UIButton *Ans1, *Ans2, *Ans3, *Ans4, *Ans5, *Ans6, *Ans7, *Ans8;
@property (strong) NSArray *ansButs;

+ (ansButSingleton *) ansButsName;  // Declare class method
@end

和 ansButSingleton.m 如下所示:

#import "ansButSingleton.h"

@implementation ansButSingleton

static ansButSingleton *ansButsName;

@synthesize Ans1, Ans2, Ans3, Ans4, Ans5, Ans6, Ans7, Ans8;
@synthesize ansButs;

//////////////////// instantiate ////////////////////

+ (ansButSingleton *) ansButsName { // class method

    @synchronized(self)
    {
        if (!ansButsName)
            ansButsName = [[ansButSingleton alloc] init];        
        return ansButsName;
    }
}

//////////////////// initialize ////////////////////

- (id)init { // class instance method

    NSLog(@"Initializing answer buttons");

    if (ansButsName) {
        return ansButsName;
    }

    self = [super init];

    if(self) {

        // First initialze the individual buttons

        self.Ans1 = [[UIButton alloc] init];
        [Ans1 setTitle:@"" forState:UIControlStateNormal];
        self.Ans2 = [[UIButton alloc] init];
        [Ans2 setTitle:@"" forState:UIControlStateNormal];
        self.Ans3 = [[UIButton alloc] init];
        [Ans3 setTitle:@"" forState:UIControlStateNormal];
        self.Ans4 = [[UIButton alloc] init];
        [Ans4 setTitle:@"" forState:UIControlStateNormal];
        self.Ans5 = [[UIButton alloc] init];
        [Ans5 setTitle:@"" forState:UIControlStateNormal];
        self.Ans6 = [[UIButton alloc] init];
        [Ans6 setTitle:@"" forState:UIControlStateNormal];
        self.Ans7 = [[UIButton alloc] init];
        [Ans7 setTitle:@"" forState:UIControlStateNormal];
        self.Ans8 = [[UIButton alloc] init];
        [Ans8 setTitle:@"" forState:UIControlStateNormal];

        // Make an array containing the objects: this is the objective-C way!

        self.ansButs = [[NSArray alloc] initWithObjects: Ans1, Ans2, Ans3, Ans4, Ans5, Ans6, Ans7, Ans8, nil];
    }

    NSLog(@"Done initializing answer buttons");

    return self;
}
@end

这构建并运行良好(它还没有做太多事情)。由于笔尖加载成功,按钮可见。然而,它们并不活跃,因为我没有将它们连接到代码(没有 IBActions)。

问题:如何将以此方式创建的按钮连接到笔尖中的按钮?如果这些是简单的按钮(不是按钮数组),我将创建一个方法并使用 IBAction 作为该方法声明的一部分。但这个案例似乎有点不同。或者也许不是。如果这些是标签(我稍后也需要这样做),我的阅读使我相信 IBOutletCollection 可能有效,但我看不到 IBActionCollection。需要专家指导!谢谢。

编辑...与罗布合作来实现他的想法。我的 viewLoad 方法是从你的方法复制并粘贴的,但也许其中有一些我需要更改的内容?

#pragma mark - View lifecycle

 - (void)loadView {
 NSDictionary *externals = [NSDictionary dictionaryWithObject:[AnswerButtons answerButtons]
 forKey:@"answerButtons"];
 NSDictionary *nibOptions = [NSDictionary dictionaryWithObject:externals
 forKey:UINibExternalObjects];
 [self.nibBundle loadNibNamed:self.nibName owner:self options:nibOptions];
 [[AnswerButtons answerButtons] buttonsDidLoad];
 }

My appDelegate, in the method didFinishLaunchingWithOptions I load my view controller then create a singleton:

UIViewController *MainWinVC = [[p3VC alloc] init];
[[self window] setRootViewController:MainWinVC];
ansButSingleton *ansButs = [[ansButSingleton alloc] init]; 

ansButSingleton.h looks like this:

#import <Foundation/Foundation.h>

@interface ansButSingleton : NSObject {

    // View objects:

    UIButton *Ans1;
    UIButton *Ans2;
    UIButton *Ans3;
    UIButton *Ans4;
    UIButton *Ans5;
    UIButton *Ans6;
    UIButton *Ans7;
    UIButton *Ans8;

    // Other objects:

    NSArray *ansButs;

}

@property (strong) UIButton *Ans1, *Ans2, *Ans3, *Ans4, *Ans5, *Ans6, *Ans7, *Ans8;
@property (strong) NSArray *ansButs;

+ (ansButSingleton *) ansButsName;  // Declare class method
@end

and ansButSingleton.m like this:

#import "ansButSingleton.h"

@implementation ansButSingleton

static ansButSingleton *ansButsName;

@synthesize Ans1, Ans2, Ans3, Ans4, Ans5, Ans6, Ans7, Ans8;
@synthesize ansButs;

//////////////////// instantiate ////////////////////

+ (ansButSingleton *) ansButsName { // class method

    @synchronized(self)
    {
        if (!ansButsName)
            ansButsName = [[ansButSingleton alloc] init];        
        return ansButsName;
    }
}

//////////////////// initialize ////////////////////

- (id)init { // class instance method

    NSLog(@"Initializing answer buttons");

    if (ansButsName) {
        return ansButsName;
    }

    self = [super init];

    if(self) {

        // First initialze the individual buttons

        self.Ans1 = [[UIButton alloc] init];
        [Ans1 setTitle:@"" forState:UIControlStateNormal];
        self.Ans2 = [[UIButton alloc] init];
        [Ans2 setTitle:@"" forState:UIControlStateNormal];
        self.Ans3 = [[UIButton alloc] init];
        [Ans3 setTitle:@"" forState:UIControlStateNormal];
        self.Ans4 = [[UIButton alloc] init];
        [Ans4 setTitle:@"" forState:UIControlStateNormal];
        self.Ans5 = [[UIButton alloc] init];
        [Ans5 setTitle:@"" forState:UIControlStateNormal];
        self.Ans6 = [[UIButton alloc] init];
        [Ans6 setTitle:@"" forState:UIControlStateNormal];
        self.Ans7 = [[UIButton alloc] init];
        [Ans7 setTitle:@"" forState:UIControlStateNormal];
        self.Ans8 = [[UIButton alloc] init];
        [Ans8 setTitle:@"" forState:UIControlStateNormal];

        // Make an array containing the objects: this is the objective-C way!

        self.ansButs = [[NSArray alloc] initWithObjects: Ans1, Ans2, Ans3, Ans4, Ans5, Ans6, Ans7, Ans8, nil];
    }

    NSLog(@"Done initializing answer buttons");

    return self;
}
@end

This builds and runs fine (it doesn't do much yet). The buttons are visible due to the successful loading of the nib. However, they are not active since I haven't connected them to the code (no IBActions).

Question: How do I connect buttons created this way to the buttons in the nib? If these were simple buttons (not an array of buttons) I would create a method and use IBAction as part of that method declaration. But this case seems a bit different. Or maybe not. If these were labels (which I also need to do later), my reading leads me to believe IBOutletCollection might work, but there is no IBActionCollection that I can see. Expert guidance needed! Thanks.

EDIT ... working with Rob to implement his ideas. My viewLoad method was copied and pasted from yours, but maybe there was something in it I needed to change?

#pragma mark - View lifecycle

 - (void)loadView {
 NSDictionary *externals = [NSDictionary dictionaryWithObject:[AnswerButtons answerButtons]
 forKey:@"answerButtons"];
 NSDictionary *nibOptions = [NSDictionary dictionaryWithObject:externals
 forKey:UINibExternalObjects];
 [self.nibBundle loadNibNamed:self.nibName owner:self options:nibOptions];
 [[AnswerButtons answerButtons] buttonsDidLoad];
 }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

一影成城 2025-01-09 03:44:13

有多种方法可以做到这一点。我会通过在笔尖上连接单例的连接来做到这一点。方法如下。

首先,让我们修复单例类以匹配 iOS 编程约定,并提供对笔尖中按钮连接的支持:

AnswerButtons.h

#import <Foundation/Foundation.h>

@interface AnswerButtons : NSObject

@property (strong, nonatomic) IBOutlet UIButton *button1, *button2, *button3, *button4, *button5, *button6, *button7, *button8;
@property (strong, nonatomic, readonly) NSArray *buttons;

+ (AnswerButtons *)answerButtons;

- (void)buttonsDidLoad;

@end

AnswerButtons.m

#import "AnswerButtons.h"

@implementation AnswerButtons

@synthesize button1 = _button1;
@synthesize button2 = _button2;
@synthesize button3 = _button3;
@synthesize button4 = _button4;
@synthesize button5 = _button5;
@synthesize button6 = _button6;
@synthesize button7 = _button7;
@synthesize button8 = _button8;

@synthesize buttons = _buttons;

+ (AnswerButtons *)answerButtons {
    static AnswerButtons *singleton;
    static dispatch_once_t once;
    dispatch_once(&once, ^{
        singleton = [[AnswerButtons alloc] init];
    });
    return singleton;
}

- (void)buttonsDidLoad {
    _buttons = [[NSArray alloc] initWithObjects:_button1, _button2, _button3, _button4, _button5, _button6, _button7, _button8, nil];
}

@end

请注意,我们在类方法中创建单例第一次请求单例。不要在 application:didFinishLaunchingWithOptions: 中执行此操作。

接下来,让我们连接笔尖中的按钮:

  1. 打开 p3VC 类的笔尖。 (您应该考虑更改此名称以大写字母开头,并拼出 ViewController 或只是 Controller。)
  2. 将“外部对象”从对象库拖到笔尖中。
  3. 在身份检查器中,将外部对象的自定义类设置为 AnswerButtons
  4. 在属性检查器中,将其外部对象标识符设置为 answerButtons
  5. 按住 Control 键并从“应答按钮”对象拖动到八个按钮中的每一个,将按钮连接到相应的插座。

最后,当我们加载笔尖时,我们需要向笔尖加载器提供AnswerButtons单例。编辑 p3VC.m 并给它一个 loadView 方法:

p3VC.m

- (void)loadView {
    NSDictionary *externals = [NSDictionary dictionaryWithObject:[AnswerButtons answerButtons]
        forKey:@"answerButtons"];
    NSDictionary *nibOptions = [NSDictionary dictionaryWithObject:externals
        forKey:UINibExternalObjects];
    [self.nibBundle loadNibNamed:self.nibName owner:self options:nibOptions];
    [[AnswerButtons answerButtons] buttonsDidLoad];
}

通过这种方法,您还可以在 中创建 IBAction 方法AnswerButtons 类并使用笔尖将按钮连接到这些操作。

There are a number of ways you could do this. I'd do it by hooking up the singleton's connections in the nib. Here's how.

First, let's fix up the singleton class to match iOS programming conventions and provide the support for wiring up the button connections in the nib:

AnswerButtons.h

#import <Foundation/Foundation.h>

@interface AnswerButtons : NSObject

@property (strong, nonatomic) IBOutlet UIButton *button1, *button2, *button3, *button4, *button5, *button6, *button7, *button8;
@property (strong, nonatomic, readonly) NSArray *buttons;

+ (AnswerButtons *)answerButtons;

- (void)buttonsDidLoad;

@end

AnswerButtons.m

#import "AnswerButtons.h"

@implementation AnswerButtons

@synthesize button1 = _button1;
@synthesize button2 = _button2;
@synthesize button3 = _button3;
@synthesize button4 = _button4;
@synthesize button5 = _button5;
@synthesize button6 = _button6;
@synthesize button7 = _button7;
@synthesize button8 = _button8;

@synthesize buttons = _buttons;

+ (AnswerButtons *)answerButtons {
    static AnswerButtons *singleton;
    static dispatch_once_t once;
    dispatch_once(&once, ^{
        singleton = [[AnswerButtons alloc] init];
    });
    return singleton;
}

- (void)buttonsDidLoad {
    _buttons = [[NSArray alloc] initWithObjects:_button1, _button2, _button3, _button4, _button5, _button6, _button7, _button8, nil];
}

@end

Note that we create the singleton in the class method the first time the singleton is requested. Don't do it in application:didFinishLaunchingWithOptions:.

Next, let's hook up the buttons in the nib:

  1. Open the nib for the p3VC class. (You should consider changing this name to start with a capital letter and spell out ViewController or just Controller.)
  2. Drag an “External Object” from the Object Library into the nib.
  3. In the Identity Inspector, set the External Object's custom class to AnswerButtons.
  4. In the Attributes Inspector, set its External Object Identifier to answerButtons.
  5. Control-drag from the Answer Buttons object to each of the eight buttons, connecting the button to the appropriate outlet.

Finally, we need to provide the AnswerButtons singleton to the nib loader when we load the nib. Edit p3VC.m and give it a loadView method:

p3VC.m

- (void)loadView {
    NSDictionary *externals = [NSDictionary dictionaryWithObject:[AnswerButtons answerButtons]
        forKey:@"answerButtons"];
    NSDictionary *nibOptions = [NSDictionary dictionaryWithObject:externals
        forKey:UINibExternalObjects];
    [self.nibBundle loadNibNamed:self.nibName owner:self options:nibOptions];
    [[AnswerButtons answerButtons] buttonsDidLoad];
}

With this approach, you can also create IBAction methods in the AnswerButtons class and use the nib to connect the buttons to those actions.

半山落雨半山空 2025-01-09 03:44:13

由于 UIButton 继承自 UIControl,您可以使用以下方法:

[yourButton1 addTarget:yourObject action:@selector(yourMethod) forControlEvents:UIControlEventTouchUpInside];

将其挂钩到创建按钮的循环中,然后就可以开始了。如果您要从界面生成器添加按钮,那么您需要为每个按钮挂钩一个 IBOutlet。示例:在视图控制器 init 中:

 self.Ans1 = [[UIButton alloc] init];
 [Ans1 setTitle:@"" forState:UIControlStateNormal];
//set the action
    [Ans1 addTarget:self action:@selector(yourMethod) forControlEvents:UIControlEventTouchUpInside];

另一种方法是为每个按钮创建 IBAction 方法,并将该方法挂接到单例中的方法,我认为这是更清楚了。

示例:在您的视图控制器中:

-(IBAction) button1Press:(id)sender{

[yourSingleton button1Press];

}

Since UIButton inherits from UIControl you can use the method:

[yourButton1 addTarget:yourObject action:@selector(yourMethod) forControlEvents:UIControlEventTouchUpInside];

Hook that in the loop where the buttons are created and you are good to go. If you are adding the buttons from interface builder then you need to hook an IBOutlet for each. Example: In your view controller init:

 self.Ans1 = [[UIButton alloc] init];
 [Ans1 setTitle:@"" forState:UIControlStateNormal];
//set the action
    [Ans1 addTarget:self action:@selector(yourMethod) forControlEvents:UIControlEventTouchUpInside];

Another way would be to create the IBAction method for each button and hook that method to the method in the singleton, which in my opinion is much more clear.

Example: in your view controller:

-(IBAction) button1Press:(id)sender{

[yourSingleton button1Press];

}
孤蝉 2025-01-09 03:44:13

要将按钮连接到界面生成器,您必须在每个变量声明中的 UIButton 之前放置“IBOutlet”。

IBOutlet UIButton * Ans1;

然后在界面生成器中,您可以右键单击并从视图控制器拖动到按钮上,然后选择右侧按钮。然后,如果您想让每个按钮执行一个方法,您应该在 .h 文件中声明一个 IBAction 方法:

-(IBAction)doButtonStuff:(id)sender;

然后,要将该行为连接到界面构建器中的每个按钮,请转到界面构建器,右键单击并从按钮拖动到查看控制器并选择您想要将其关联的方法。通常,使用界面生成器既快速又简单,但如果您想在幕后做一些额外的事情,您可以使用whitelion发布的代码。
另外,请注意,为了在设置按钮时使用更少的代码,您可以为每个循环执行一个。

for (UIButton * button in ansButs) {
    self.button = [[UIButton alloc] init];
    [button setTitle:@"" forState:UIControlStateNormal];
}

这样代码就少了很多!!!您必须在此代码之前声明数组并在其中包含所有按钮。

To connect the buttons to interface builder, you'd have to place "IBOutlet" before the UIButton in each one of your variable declarations.

IBOutlet UIButton * Ans1;

Then in interface builder, you can right click and drag from view controller onto the button and select the right button. Then if you wanted to have each button perform a method, you should declare an IBAction method in your .h file:

-(IBAction)doButtonStuff:(id)sender;

Then to hook up the act to each button in interface builder, go to interface builder and right click and drag from the button to view controller and select what method you want to associate it with. Typically using interface builder is quick and easy but if you want to do some extra behind the scenes stuff, you can use the code whitelion posted.
Also, just a side note, to use less code when setting up your buttons, you can do a for each loop.

for (UIButton * button in ansButs) {
    self.button = [[UIButton alloc] init];
    [button setTitle:@"" forState:UIControlStateNormal];
}

This is a lot less code!!! You'd have to declare the array before this code and include all of the buttons in it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文