1

我正在尝试学习如何使用NSTimers,我想到了以下几点: 创建一个开关。让计时器在应用程序开始时开始,并且在每一秒之后,都会调用一个更改开关状态的函数。

这是我到目前为止所做的:

我在头文件 ViewControl.h 中声明了定时器和开关:

//Timer 
{NSTimer *timer;}
@property (weak, nonatomic) IBOutlet UISwitch *zeSwitch;

然后,在 ViewControl.m 文件中,我定义了以下内容:

- (IBAction)zeSwitch:(id)sender {
    UISwitch *zeSwitchSatus = (UISwitch *) sender;
    BOOL yn = zeSwitchSatus.isOn;
    [zeSwitch setOn:yn animated:YES];

}    

- (void)viewDidLoad
{

    timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self 
    selector:@selector(zeSwitch) userInfo:nil repeats:YES];


    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}

所以我希望当我运行代码时,我会看到一个打开或关闭的开关。然后我会看到它随着时间的推移自动改变其状态,而无需我干预。

图片!

但这没有用!我首先得到上面的图像。没有什么变化。然后当我按下开关时它崩溃了。(但我的想法是根本不碰它。)

有任何想法吗?

4

2 回答 2

4

你很接近。这里有一些问题。首先,您提供给计时器的方法被命名zeSwitch:——冒号很重要。所以你需要像这样创建计时器:

timer = [NSTimer scheduledTimerWithTimeInterval:1 
                                         target:self 
                                       selector:@selector(zeSwitch:) 
                                       userInfo:nil             //^ Note colon!
                                        repeats:YES];

不带冒号命名的方法zeSwitch实际上是开关的访问器方法,因为您已经命名了您的 property zeSwitch。你真的应该重命名计时器的操作方法来澄清这一点。现在,计时器每秒都在调用 switch 的访问器方法,这实际上并没有做任何事情。

接下来,计时器将自己传递给它调用的方法。中的sender参数zeSwitch:将是计时器,而不是开关。如果这个方法实际上是通过定时器调用的,你会遇到崩溃,因为你会发送isOn到定时器,而它不会响应。

你有一个开关的插座,所以你可以通过那个插座来引用它:

- (void)flipSwitch: (NSTimer *)tim
{
    BOOL switchIsOn = [[self zeSwitch] isOn];

请注意,我已经更正了此方法中的名称和类型——您还需要更改计时器的创建以反映这一点:@selector(flipSwitch:).

第三,您想要翻转开关,因此您应该将其设置为与其当前状态相反的状态。下一行需要是:

    [[self zeSwitch] setOn:!switchIsOn animated:YES];

!操作员否定BOOL它所附加的,变成YES反之亦然NO

于 2012-05-28T00:39:02.683 回答
3

1) 当你指定一个接受一个参数的选择器时,你需要在名字后面加一个冒号,所以@selector(zeSwitch:).

2)由定时器触发的选择器获取定时器作为参数,而不是开关,所以- (IBAction)zeSwitch:(NSTimer *)timer.

于 2012-05-28T00:37:13.553 回答