我正在尝试学习如何使用NSTimer
,我想到了以下内容:创建一个开关。让应用程序开始时计时器开始,每秒后,调用一个改变开关状态的函数。
这是我到目前为止所做的:
我在头文件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.
}
所以我希望当我运行代码时,我会看到一个打开或关闭的开关。然后我会看到它随着时间的推移自动改变它的状态,而不会干扰我。
但那没用!我先得到上面的图片。没有什么变化。然后当我按下开关时它会崩溃。 (但我的想法是根本不接触它。)
有什么想法吗?
答案 0 :(得分:4)
你非常接近。这里有一些问题。首先,您给定时器的方法命名为zeSwitch:
- 冒号很重要。所以你需要像这样创建计时器:
timer = [NSTimer scheduledTimerWithTimeInterval:1
target:self
selector:@selector(zeSwitch:)
userInfo:nil //^ Note colon!
repeats:YES];
没有冒号的名为zeSwitch
的方法实际上是交换机的访问方法,因为您已将属性命名为zeSwitch
。您应该重命名计时器的操作方法以澄清这一点。现在,计时器每秒都会调用交换机的访问器方法,这实际上并没有做任何事情。
接下来,计时器将本身传递给它调用的方法。 sender
中的zeSwitch:
参数将是计时器,而不是开关。如果这个方法实际上是通过计时器调用的,那么你会发生崩溃,因为你要向计时器发送isOn
,而且它没有响应。
你有一个开关的插座,所以你可以通过那个插座参考它:
- (void)flipSwitch: (NSTimer *)tim
{
BOOL switchIsOn = [[self zeSwitch] isOn];
请注意,我已更正此方法中的名称和类型 - 您还需要更改计时器创建以反映这一点:@selector(flipSwitch:)
。
第三,您想要翻转开关,因此您应该将其设置为当前状态的相反。下一行需要是:
[[self zeSwitch] setOn:!switchIsOn animated:YES];
!
运算符否定了BOOL
附加的YES
,将NO
转换为{{1}},反之亦然。
答案 1 :(得分:3)
1)当您指定一个带有一个参数的选择器时,您需要在名称后面加冒号,因此@selector(zeSwitch:)
。
2)由计时器触发的选择器将计时器作为参数而不是开关,因此- (IBAction)zeSwitch:(NSTimer *)timer
。