如何增加 NSTimer 标签中的时间?

发布于 2024-10-18 01:20:45 字数 1294 浏览 1 评论 0原文

我是一名初出茅庐的 iPhone 开发者,所以请对我宽容一些。

我正在尝试开发一个简单应用程序,它将显示时间,然后每秒勾选一次。我觉得我在内存管理方面错过了一些东西,但我的技能太新了,无法真正知道我错过了什么。

我正在创建一个直接到主窗口的标签(非常简单的应用程序),并尝试通过 NSTimer 更新标签。这是我的代码,它仍然有点混乱。

@synthesize label, theDate;
@synthesize window;

- (void)tick 
{
    theDate = [[NSDateFormatter alloc] init];
    [theDate setDateFormat:@"hh:mm:ss"];
    NSString* currentTime = [theDate stringFromDate:[NSDate date]];
    label.text = [[NSString alloc] initWithFormat:@"%d",currentTime];
    [currentTime release];
}

- (BOOL)application:(UIApplication *)application 
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions     
{
    CGRect rect = CGRectMake(10, 200, 300, 20);
    label = [[UILabel alloc] initWithFrame:rect];
    label.textAlignment = UITextAlignmentCenter;
    [self.window addSubview:label];
    [NSTimer scheduledTimerWithTimeInterval:1.0f 
                                     target:self 
                                   selector:@selector(tick) 
                                   userInfo:nil 
                                    repeats:YES];
    [self.window makeKeyAndVisible];

    return YES;
}

@synthesize 的 ivars 是 .h 文件中的 @property,并且 ivars 在 dealloc 中释放。
谢谢!

I'm a fledgling iPhone developer, so be easy on me.

I'm trying to develop a simple app that will show the time and then tick every second. I feel like I'm missing something here with memory management, but my skills are too fresh to really know what I'm missing.

I'm creating a label straight to the main window (really simple app) and trying to update the label through and NSTimer. Here is my bit of code, it's still a little messy.

@synthesize label, theDate;
@synthesize window;

- (void)tick 
{
    theDate = [[NSDateFormatter alloc] init];
    [theDate setDateFormat:@"hh:mm:ss"];
    NSString* currentTime = [theDate stringFromDate:[NSDate date]];
    label.text = [[NSString alloc] initWithFormat:@"%d",currentTime];
    [currentTime release];
}

- (BOOL)application:(UIApplication *)application 
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions     
{
    CGRect rect = CGRectMake(10, 200, 300, 20);
    label = [[UILabel alloc] initWithFrame:rect];
    label.textAlignment = UITextAlignmentCenter;
    [self.window addSubview:label];
    [NSTimer scheduledTimerWithTimeInterval:1.0f 
                                     target:self 
                                   selector:@selector(tick) 
                                   userInfo:nil 
                                    repeats:YES];
    [self.window makeKeyAndVisible];

    return YES;
}

The @synthesize'd ivars are @propertys in the .h file and the ivars get released in dealloc.
Thanks!

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

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

发布评论

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

评论(3

ヤ经典坏疍 2024-10-25 01:20:45

这里存在许多内存问题:

  • 您分配了 theDate 但没有释放它,因此它正在泄漏。
  • 尽管没有所属引用,您仍要释放 currentTime,因此您可能会在自动释放池中看到崩溃。
  • 您正在分配分配给 label.text 的值,但没有释放它; label.text 是保留属性,在这种情况下,您会通过双重保留来泄漏该字符串,或者 label.text 不是保留属性,在这种情况下,您不会通过释放它来泄漏该字符串(最后一个除外) ,在 dealloc 中)

我强烈建议您阅读 Apple 的内存管理指南

此外,与内存问题无关,您正在使用 %d 尝试显示字符串而不是 %@,因此您将获得指针地址的数值而不是字符串的内容。

You have a number of memory problems here:

  • You are alloc'ing theDate but not releasing it, so it's leaking.
  • You are releasing currentTime despite not having an owning reference, so you'll likely see crashes in the autorelease pool.
  • You are alloc'ing the value assigned to label.text but not releasing it; either label.text is a retaining property, in which case you are leaking that string by double-retaining it, or label.text is not retaining, in which case you are leaking the string by never releasing it (except for the very last one, in dealloc)

I'd strongly suggest you read Apple's memory management guide.

Also, unrelated to the memory issues, you are using %d to try to show a string instead of %@, so you'll get the numeric value of the pointer address rather than the contents of the string.

向地狱狂奔 2024-10-25 01:20:45

您不应该释放 currentTime。您没有通过名称中带有“new”、“alloc”、“retain”或“create”的东西获得它,因此您不拥有它。您正在做的是分配一个不相关的字符串并将其提供给 label.text,然后无法释放它。建议您将这三行替换为:

NSString* currentTime = [theDate stringFromDate:[NSDate date]];
label.text = currentTime;

如果 UILabel 想要保留该字符串,则由 UILabel 来保留该字符串(我希望它会,但这是一个实现细节,无论如何都与我们无关),并且您不拥有因此可以让它在自动释放池中过期。

在相同的方法中,您还创建了一个名为“theDate”的 NSFormatter 并且无法释放它。实际上,您似乎对 getter 和 setter 有点困惑,这并不奇怪,因为这里有一些 Objective-C 的传统。如果您执行以下操作:

theData = ...whatever...;

那么您将按照正常的 C '=' 运算符,直接将指定的值复制到变量中。那里没有 Objective-C 的魔力。您是否以及如何申报您的财产(很大程度上,请参阅脚注)无关紧要。

如果您类似:

self.theData = ...whatever...;

那么编译器的行为将与您编写的完全一样:

[self setTheData:...whatever...];

因此您将获得一个方法调用,并且将使用您的实际设置器。 setter 将执行您通过 @property/@synthesize 告诉它的任何操作(即保留、复制或分配)。因此,在 dealloc 中,您往往会看到:

- (void)dealloc
{
    [property1 release];
    [property2 release];
    [super dealloc];
}

或:

- (void)dealloc
{
    self.property1 = nil;
    self.property2 = nil;
    [super dealloc];
}

与“retain”属性具有相同的整体效果(尽管后者实际上释放了原始属性,然后保留“nil”,任何发送给“nil”的消息都没有效果)。

同样的混乱可能会影响您对标签的使用,但您目前所做的事情在技术上是正确的。如果您使用“self.label =”而不是直接赋值,那么您需要传递一个自动释放的对象或您知道如何稍后释放的对象。

另外:非常值得查看 NSZombies 和 Instruments 中的 Leaks 工具;前者将帮助您了解何时以及如何访问已释放的对象,后者将帮助您发现何时泄漏内存。 Guard Malloc 对于前者也很有用,但运行时开销要大得多,我不确定它目前在 iOS 上的工作情况如何。

(脚注:在现代 64 位和 ARM 运行时中,实例变量是动态的,其实际效果是您可以纯粹通过 @property 和 @synthesize 声明它们,而无需以其他方式将它们放入 @interface 声明中;如果您这样做,那么显然@property的存在与否会影响直接访问是否有效)

You shouldn't release currentTime. You didn't get hold of it through something with 'new', 'alloc', 'retain' or 'create' in the name, so you don't own it. What you are doing is allocating an unrelated string and giving it to label.text, then failing to release that. Suggest you replace those three lines with just:

NSString* currentTime = [theDate stringFromDate:[NSDate date]];
label.text = currentTime;

It's up to the UILabel to retain the string if it wants to keep it (I expect it will, but it's an implementation detail and none of our business either way), and you don't own it so can just leave it to expire on the autorelease pool.

In the same method you also create an NSFormatter called 'theDate' and fail to release it. Actually, you seem to be a bit confused about getters and setters, which isn't surprising since there's a bit of Objective-C heritage at play here. If you do something like:

theData = ...whatever...;

Then you'll directly copy the value specified into the variable, as per the normal C '=' operator. There's no Objective-C magic there. Whether and how you've declared your property is (largely, see foot note) irrelevant.

If you something like:

self.theData = ...whatever...;

Then the compiler will act exactly as if you'd written:

[self setTheData:...whatever...];

So you get a method call and your actual setter will be used. The setter will do whatever you told it to via the @property/@synthesize (ie, retain, copy or assign). Hence, at dealloc you tend to see either:

- (void)dealloc
{
    [property1 release];
    [property2 release];
    [super dealloc];
}

Or:

- (void)dealloc
{
    self.property1 = nil;
    self.property2 = nil;
    [super dealloc];
}

Which have the same overall effect with 'retain' properties (though the latter actually releases the original then retains 'nil', any message to 'nil' having no effect).

The same confusion possibly affects your use of label, but what you're doing at the minute is technically correct. If you'd used 'self.label =' instead of the direct assignment then you'd want to pass an autoreleased object or one that you know how to release later on.

Addition: it's well worth checking out NSZombies and the Leaks tool in Instruments; the former will help you find out when and how you're accessing deallocated objects, the latter will help you spot when you're leaking memory. Guard Malloc is also useful for the former but carries a much larger runtime overhead and I'm not sure how well it works with iOS at present.

(foot note: in the modern 64 bit and ARM runtimes, instance variables are dynamic with the practical effect that you can declare them purely via @property and @synthesize without otherwise putting them in the @interface declaration; if you're doing that then obviously the presence or absence of the @property will affect whether direct access works)

哭泣的笑容 2024-10-25 01:20:45
  1. 将这个(theDate = [[NSDateFormatter alloc] init];)行放在applicationDidFinishLoading中。这样 theDate 将被分配一次。
  2. 用这个替换你的tick函数:-

    • (空)勾选
      {
      theDate = [[NSDateFormatter alloc] init];
      [theDate setDateFormat:@"hh:mm:ss"];
      NSString* currentTime = [theDate stringFromDate:[NSDate 日期]];
      标签.text = 当前时间;
      }
  1. Put this(theDate = [[NSDateFormatter alloc] init];) line in the applicationDidFinishLoading. So that theDate will be allocated once.
  2. Replace your tick function with this one:-

    • (void)tick
      {
      theDate = [[NSDateFormatter alloc] init];
      [theDate setDateFormat:@"hh:mm:ss"];
      NSString* currentTime = [theDate stringFromDate:[NSDate date]];
      label.text = currentTime;
      }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文