我有一个计时器,可以在我今天的小部件中倒计时。我从View Controller收集日期,然后在扩展程序中启动计时器,然后从那里我以三个标签显示日期,小时,分钟和秒。在我的应用程序中...这是完美的,但在通知中心却不是这样。倒计时正确加载并且大约20秒工作。之后它会跳过一秒并冻结,然后它会在大约4秒内再次启动,然后它将重置整个小部件(一切都消失),然后大约2秒后整个小部件重置。这是记忆警告还是什么?
查看控制器: mainTextLabel.text = 436496400
NSUserDefaults *sharedDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.nicmac.nextgame"];
[sharedDefaults setObject:mainTextLabel.text forKey:@"MyNumberKey"];
[sharedDefaults synchronize];
今日视图控制器
- (id)initWithCoder:(NSCoder *)aDecoder {
if (self = [super initWithCoder:aDecoder]) {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(userDefaultsDidChange:)
name:NSUserDefaultsDidChangeNotification
object:nil];
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.preferredContentSize = CGSizeMake(320, 300);
[self performSelector:@selector(updateNumberLabelText) withObject:nil afterDelay:1.0];
}
- (void)userDefaultsDidChange:(NSNotification *)notification {
[self performSelector:@selector(updateNumberLabelText) withObject:nil afterDelay:1.0];
}
- (void)updateNumberLabelText {
NSUserDefaults *defaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.nicmac.nextgame"];
NSString *date = [defaults stringForKey:@"MyNumberKey"];
self.numberLabel.text = [NSString stringWithFormat:@"%@", date];
NSString *doubleString = self.numberLabel.text;
double value = [doubleString doubleValue];
destinationDate = [NSDate dateWithTimeIntervalSince1970:value];
timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateNumberLabelText) userInfo:nil repeats:YES];
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
int units = NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
NSDateComponents *components = [calendar components:units fromDate:[NSDate date] toDate:destinationDate options:0];
[hour setText:[NSString stringWithFormat:@"%ld", (long)[components day] * 24 + (long)[components hour]]];
[minute setText:[NSString stringWithFormat:@"%ld", (long)[components minute]]];
[second setText:[NSString stringWithFormat:@"%ld", (long)[components second]]];
}
谢谢!
答案 0 :(得分:3)
这里的问题在于- (void)updateNumberLabelText
方法。
具体来说,这里:
timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateNumberLabelText) userInfo:nil repeats:YES];
这意味着每次调用此方法时,它都会安排另一个计时器每秒调用此方法(因为repeats:YES
而每秒调用一次)。这意味着,每秒(由于计算机中的任何延迟而具有微偏移),x个预定计时器正在产生x更多数量的预定计时器,这意味着每秒钟您的计时器数量增加一倍。这称为指数增长,可以建模为2^x
。
所以要在20秒内找到计时器的数量:
2^1+2^2+2^3+2^4+2^5+2^6+2^7+2^8+2^9+2^10+2^11+2^12+2^13+2^14+2^15+2^16+2^17+2^18+2^19+2^20
我们能否更好地代表这一点 - 我们可以!我们可以像这样使用sigma表示法:
<no. of seconds> Σ 2^i i=1
但足够的数学。平均在20秒内初始化的高达 2,000,000 计时器的平均值。这是一个很多的计时器,并且小部件最终会努力去呼吸(没有更多的内存!)并且死亡/崩溃/重启自己。
以下是修复方法: 如果你真的希望这个方法循环自己,请调用
[self performSelector:@selector(updateNumberLabelText) withObject:nil afterDelay:1.0];
在方法中。
您可以按照当前的方式执行此操作并执行repeats:NO
,但我不认为计时器会在1.0秒之后自invalidate
,并创建那么多计时器不是很有效率。