progress
的属性,它存储了总秒数。
我已经写了一些代码,它需要这些秒并将其格式化为可读字符串。我是新手,所以请原谅我,如果这不是最好的代码。我欢迎任何建议:
// hours, minutes, and seconds are instance variables defined as integers
int totalSeconds = (int)streamer.progress;
hours = totalSeconds / (60 * 60);
if (hours > 0)
formattedTimeString = [NSString stringWithFormat:@"%d:", hours]; // WRONG
minutes = (totalSeconds / 60) % 60;
seconds = totalSeconds % 60;
[formattedTimeString stringByAppendingFormat:@"%d:%d", minutes, seconds]; // WRONG
基本上我希望它显示为“3:35”,例如显示3分35秒。我只想显示小时部分,如果它是一个小时,在这种情况下它将是“2:3:35”例如(任何人都可以推荐一种更好的格式化方法吗?)。
我遇到的问题是我实际创建/设置字符串的位置(标记为错误的行)。由于这是每秒完成的,如果我不断要求新的字符串对象,我很容易就会泄漏。我想我可以通过在方法结束时释放foramttedTimeString来解决这个问题,但这是否是正确的方法呢? NSMutableString
会以任何方式帮助吗? Cocoa还有更好的方法吗?我已经在#iphonedev
@ freenode询问,他们说我必须自己写这个方法,但我想我会再问一次。
提供上下文:这是一个互联网广播流媒体应用程序(我知道已有很多,但我只是练习)。我希望能够显示流媒体播放的时间。
对不起,如果这个问题很愚蠢,嘿,就像我说我是新手一样。
答案 0 :(得分:4)
我会这样做:
int totalSeconds = (int)streamer.progress;
hours = totalSeconds / (60 * 60);
minutes = (totalSeconds / 60) % 60;
seconds = totalSeconds % 60;
if ( hours > 0 ) {
formattedTimeString = [NSString stringWithFormat:@"%d:%02d:%02d", hours, minutes, seconds];
} else {
formattedTimeString = [NSString stringWithFormat:@"%d:%02d", minutes, seconds];
}
现在最后,formattedTimeString是所需的时间,但你不“拥有”它 - 你必须保留它,或者如果你想保留它,就把它存储在“copy”属性中。
请注意,%02d会为您提供两个数字,即零填充数字,这通常是您在部分时间内所需的数字。
要了解如何使用stringByAppendingFormat,它看起来像这样:
NSString* formattedTimeString = @"";
if ( hours > 0 ) {
formattedTimeString = [formattedTimeString stringByAppendingFormat:@"%d:", hours];
}
formattedTimeString = [formattedTimeString stringByAppendingFormat:@"%d:%02d", minutes, seconds];
然而在这种情况下,你会得到像3:4:05这样的时间,而不是更理想的3:04:05。
请注意,每次都会覆盖formattedTimeString,但这样就可以了,因为你不会随时“拥有”它,所以你不负责释放它。
最后,要使用可变字符串查看它,它可能如下所示:
NSMutableString* formattedTimeString = [NSMutableString string];
if ( hours > 0 ) {
[formattedTimeString appendFormat:@"%d:", hours];
}
[formattedTimeString appendFormat:@"%d:%02d", minutes, seconds];
同样,时间结果是不受欢迎的3:4:05,并且你最后没有自己的formattedTimeString,所以它必须保留或存储一个copy属性以保持它。
答案 1 :(得分:2)
要将增量知道为时间单位,您还可以执行以下操作:
// as part of init...
self.gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
// in the timer or wherever you are tracking time deltas...
static NSUInteger unitFlags =
NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;
NSDateComponents *components = [gregorian components:unitFlags
fromDate:myBaseTime
toDate:[NSDate date] options:0];
然后您可以使用类似[components minute]
的内容来引用这些部分。
请记住,您必须在dealloc
中发布日历。
答案 2 :(得分:1)
你的代码看起来很不错。您没有泄漏任何内存,因为您创建的字符串对象的保留计数为零,系统将清除它。但是,如果formattedTimeString不是函数中的局部变量,则需要在结尾处保留它以防止这种情况发生!为此,您需要将[formattedTimeString retain]添加到代码块的末尾,然后在替换字符串对象之前添加[formattedTimeString release]。
作为一般规则,名称包含“alloc”,“copy”,“create”和“new”的函数返回已保留的对象(意味着它们的保留计数为+1)。当你完成使用它们时,你有责任对这些对象进行释放或自动释放 - 或者它们只是开始堆积在内存中。
“stringWithFormat:”,“imageNamed:”和“arrayWithCapacity:”之类的函数都返回保留计数为零的对象 - 因此您可以安全地丢弃它们(就像您在代码示例中一样)。如果你想保留它们,你应该调用retain来确保在你使用它们时不会清理它们。
所有这一切,我认为主要的问题是你使用stringByAppendingFormat:。由于您使用的NSString不可变,因此该调用返回 new 字符串。你想说:
formattedTimeString = [formattedTimeString stringByAppendingFormat:@“%d:%d”,分钟,秒];
或者,您可以使用NSMutableString。既然这是你一遍又一遍地做的事情,我建议你这样做。从技术上讲,无论哪种方式都很好。
希望有所帮助!整个保留/释放事情可能会让人感到困惑。请记住,每个对象都有一个“retainCount”,一旦它达到零,就不知道该对象或它的数据会发生什么。
答案 3 :(得分:0)
嘿谢谢你们,我很欣赏这些回复。
我最终做到了这一点,但它确实有效,但我想知道你们是否看到它有任何问题:
int totalSeconds = (int)streamer.progress;
[formattedTimeString setString:@""];
hours = totalSeconds / (60 * 60);
if (hours > 0)
[formattedTimeString appendFormat:@"%d:", hours];
minutes = (totalSeconds / 60) % 60;
seconds = totalSeconds % 60;
[formattedTimeString appendFormat:@"%02d:%02d", minutes, seconds];
然后当然在viewDidLoad
我实例化实例变量formattedTimeString
:
formattedTimeString = [[NSMutableString alloc] initWithCapacity:8];
我没有在第一个代码片段中保留/释放,因为我认为没有必要,但我可能是错的。然而,我在dealloc方法中释放,所以我应该没事。