这个问题基本上是关于自定义日期格式。我设法开发了一个倒计时应用程序,该应用程序设法创建一个事件,以后可以由客户查看,定制或跟踪。重要的部分是倒数计时器,它从数据库中获取秒数并根据日期格式化程序显示剩余时间。到目前为止,我在应用程序中使用默认设置,计数器格式为dd:hh:mm,显然我的客户希望允许应用程序用户自定义时间显示方式。所以现在用户可以选择四个选项,例如yy:周:hh:mm或月:周:天:小时。我认为最好的方法是将表四个索引保存为db作为字符串。我的问题出现在日历上。
conversionInfo = [sysCalendar components:NSHourCalendarUnit | NSMinuteCalendarUnit | NSDayCalendarUnit | NSSecondCalendarUnit fromDate:today toDate:future options:0];
one = [NSString stringWithFormat:@"%d Days %d Hours %d Minutes %d Seconds %@", [conversionInfo day], [conversionInfo hour],[conversionInfo minute],[conversionInfo second], untilOrSince]; self.eventTimer.text = one;
conversionInfo = [sysCalendar components: NSHourCalendarUnit | NSSecondCalendarUnit fromDate:today toDate:future options:0];
one = [NSString stringWithFormat:@"%ld Seconds %@", (long)[conversionInfo second], untilOrSince];
此外,如果我使用所有单位构建日历但仅显示秒数,那么倒计时将仅显示59秒而不是343746545秒直到
例如,这些日历单位不能放在一个数组中,那么如果用户选择2,4,5,6这将是几个月:天:小时:分钟,我将如何选择日历格式?我不能说components = [NSArray arrayWithObjects: [arrComponents objectAtIndex:2], [arrComponents objectAtIndex:2],nil];
有什么想法吗?
答案 0 :(得分:3)
好的,这比我最初的想法更难
在整个系统中,单位标志用于将日期定义为组件等。这个单元缺陷可以只用一个值,一个位掩码组合。我将它用于我的代码。
年份单位可能为0....000010
月份单位可能为0....000100
两者的位掩码都是
0....000010 NSCalendarUnitYear
0....000100 NSCalendarUnitMonth
------------
& 0....000110
因此,要保存一个单位的信息,我们只需要将相应的位设置为1
- (void)viewDidLoad
{
[super viewDidLoad];
self.selectedUnitsBitmask= 0;
self.unitNames = @[ @"Year", @"Month", @"Week", @"Day", @"Hour", @"Minute", @"Second"];
self.units = @[@(NSCalendarUnitYear), @(NSCalendarUnitMonth), @(NSCalendarUnitWeekOfMonth), @(NSCalendarUnitDay), @(NSCalendarUnitHour), @(NSCalendarUnitMinute), @(NSCalendarUnitSecond)];
NSDateComponents *c = [[NSDateComponents alloc] init];
c.year = 2014;
c.month = 12;
c.day = 25;
self.futureDate = [[NSCalendar currentCalendar] dateFromComponents:c];
}
self.unitNames
的值用于填充表格视图
self.units
存储每个可用单元的单位标志。
-(UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier =@"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
cell.textLabel.text = _unitNames[indexPath.row];
NSUInteger s;
NSUInteger row = indexPath.row;
s = NSIntegerMax & [self.units[row] integerValue];
cell.accessoryType = (self.selectedUnitsBitmask & s) ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
return cell;
}
如果选择了一个单元格,s = NSIntegerMax & [self.units[row] integerValue];
将检查位掩码,如果要使用此单位。
如果选择了一个单元格,我们想要切换它所代表的单位的位
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSUInteger s;
NSUInteger row = indexPath.row;
s = NSIntegerMax & [self.units[row] integerValue];
self.selectedUnitsBitmask ^= s ;
NSLog(@"%lu, %lu", (unsigned long)s, (unsigned long)self.selectedUnitsBitmask);
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.accessoryType =(self.selectedUnitsBitmask & s) ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
[self updateCountDownLabel:nil];
}
下面
NSUInteger s;
NSUInteger row = indexPath.row;
s = NSIntegerMax & [self.units[row] integerValue];
s
表示所选的位,
self.selectedUnitsBitmask ^= s ;
将在位掩码中切换它。 bitmask ^= s
是bitmask = bitmask ^ s
的缩写形式,其中^
是独占或:位掩码的第n位必须与s的第n位相反
0011 bitmask
^ 0101 s
----
= 1100
现在我们可以根据位掩码中的单位标志更新将打印时差的字符串:
- (IBAction)updateCountDownLabel:(id)sender {
BOOL includeYear = self.selectedUnitsBitmask & NSCalendarUnitYear;
BOOL includeMonth = self.selectedUnitsBitmask & NSCalendarUnitMonth;
BOOL includeDay = self.selectedUnitsBitmask & NSCalendarUnitDay;
BOOL includeHour = self.selectedUnitsBitmask & NSCalendarUnitHour;
BOOL includeMinute= self.selectedUnitsBitmask & NSCalendarUnitMinute;
BOOL includeSecond= self.selectedUnitsBitmask & NSCalendarUnitSecond;
NSDateComponents *diffDateComponents = [[NSCalendar currentCalendar] components:self.selectedUnitsBitmask fromDate:[NSDate date] toDate:self.futureDate options:0];
NSMutableString *outputString = [@"" mutableCopy];
if (includeYear && diffDateComponents.year)
[outputString appendFormat:@"%d Year", diffDateComponents.year];
if (includeMonth && diffDateComponents.month)
[outputString appendFormat:@" %d Month", diffDateComponents.month];
if (diffDateComponents.weekOfMonth < NSIntegerMax && diffDateComponents.weekOfMonth)
[outputString appendFormat:@" %d Week", diffDateComponents.weekOfMonth];
if (includeDay && diffDateComponents.day)
[outputString appendFormat:@" %d Day", diffDateComponents.day];
if (includeHour && diffDateComponents.hour)
[outputString appendFormat:@" %d Hour", diffDateComponents.hour];
if (includeMinute && diffDateComponents.minute)
[outputString appendFormat:@" %d Minute", diffDateComponents.minute];
if (includeSecond && diffDateComponents.second)
[outputString appendFormat:@" %d Second", diffDateComponents.second];
self.countDownLabel.text = [outputString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
}
要确定是否设置了标记,我们使用&
AND运算符
BOOL includeYear = self.selectedUnitsBitmask & NSCalendarUnitYear;
如果年份标志为0....000010
并且位掩码包含0....010110
&
操作将返回
0....000010 NSCalendarUnitYear
& 0....010110 bitmask
-------------
= 0....000010 -> NSCalendarUnitYear
我们为所有单位执行此操作。我不知道为什么,但&amp;操作总是返回0。在这里我们使用hack:
if (diffDateComponents.weekOfYear < NSIntegerMax)
[outputString appendFormat:@" %d Week", diffDateComponents.weekOfYear];
对于新的NSDateComponents week
,使用可用整数NSIntegerMax表示的最大数字进行实例化。如果它的值小于NSIntegerMax,我们假设它已设置,我们将它附加到字符串。
结果:
整个守则整体:
#import "ViewController.h"
@interface ViewController () <UITableViewDataSource, UITableViewDelegate>
@property (weak, nonatomic) IBOutlet UITableView *tableView;
@property (weak, nonatomic) IBOutlet UILabel *countDownLabel;
@property (nonatomic) NSInteger selectedUnitsBitmask;
@property (strong, nonatomic) NSArray *unitNames;
@property (strong, nonatomic) NSArray *units;
@property (strong, nonatomic) NSDate *futureDate;
- (IBAction)updateCountDownLabel:(id)sender;
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.selectedUnitsBitmask= 0;
self.unitNames = @[ @"Year", @"Month", @"Week", @"Day", @"Hour", @"Minute", @"Second"];
self.units = @[@(NSCalendarUnitYear), @(NSCalendarUnitMonth), @(NSCalendarUnitWeekOfMonth), @(NSCalendarUnitDay), @(NSCalendarUnitHour), @(NSCalendarUnitMinute), @(NSCalendarUnitSecond)];
NSDateComponents *c = [[NSDateComponents alloc] init];
c.year = 2014;
c.month = 12;
c.day = 25;
self.futureDate = [[NSCalendar currentCalendar] dateFromComponents:c];
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.units count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier =@"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
cell.textLabel.text = _unitNames[indexPath.row];
NSUInteger s;
NSUInteger row = indexPath.row;
s = NSIntegerMax & [self.units[row] integerValue];
cell.accessoryType = (self.selectedUnitsBitmask & s) ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSUInteger s;
NSUInteger row = indexPath.row;
s = NSIntegerMax & [self.units[row] integerValue];
self.selectedUnitsBitmask ^= s ;
NSLog(@"%lu, %lu", (unsigned long)s, (unsigned long)self.selectedUnitsBitmask);
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.accessoryType =(self.selectedUnitsBitmask & s) ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
[self updateCountDownLabel:nil];
}
- (IBAction)updateCountDownLabel:(id)sender {
BOOL includeYear = self.selectedUnitsBitmask & NSCalendarUnitYear;
BOOL includeMonth = self.selectedUnitsBitmask & NSCalendarUnitMonth;
BOOL includeDay = self.selectedUnitsBitmask & NSCalendarUnitDay;
BOOL includeHour = self.selectedUnitsBitmask & NSCalendarUnitHour;
BOOL includeMinute= self.selectedUnitsBitmask & NSCalendarUnitMinute;
BOOL includeSecond= self.selectedUnitsBitmask & NSCalendarUnitSecond;
NSDateComponents *diffDateComponents = [[NSCalendar currentCalendar] components:self.selectedUnitsBitmask fromDate:[NSDate date] toDate:self.futureDate options:0];
NSMutableString *outputString = [@"" mutableCopy];
if (includeYear && diffDateComponents.year)
[outputString appendFormat:@"%d Year", diffDateComponents.year];
if (includeMonth && diffDateComponents.month)
[outputString appendFormat:@" %d Month", diffDateComponents.month];
if (diffDateComponents.weekOfMonth < NSIntegerMax && diffDateComponents.weekOfMonth)
[outputString appendFormat:@" %d Week", diffDateComponents.weekOfMonth];
if (includeDay && diffDateComponents.day)
[outputString appendFormat:@" %d Day", diffDateComponents.day];
if (includeHour && diffDateComponents.hour)
[outputString appendFormat:@" %d Hour", diffDateComponents.hour];
if (includeMinute && diffDateComponents.minute)
[outputString appendFormat:@" %d Minute", diffDateComponents.minute];
if (includeSecond && diffDateComponents.second)
[outputString appendFormat:@" %d Second", diffDateComponents.second];
self.countDownLabel.text = [outputString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
}
答案 1 :(得分:-1)
您可以使用stringByAppendingString:
NSString formattedDate = @"";
formattedDate = [formattedDate stringByAppendingString:[NSString stringWithFormat:@"%d Days", [conversionInfo day]]];
formattedDate = [formattedDate stringByAppendingString:[NSString stringWithFormat:@"%d Hours", [conversionInfo hour]]];
///....
答案 2 :(得分:-1)
感谢您的所有答案,我感谢他们。
在你回复之前,我想到了我自己的解决方案,它可能不像vikingosegundo那样详细和理解,但它有效,可以扩展。
首先从检查表中将四个数字作为字符串存储到数据库中。这允许我使用“事件”存储格式信息。每次我想获得格式化我需要获取字符串并更改为数组:
int option = 0;
unsigned int unitFlags = 0;
NSString *input = self.detailItem.prefs;
NSArray *myWords = [input componentsSeparatedByString:@","];
for (int fuu = 0; fuu < myWords.count; fuu++) {
option = [[myWords objectAtIndex:fuu]intValue];
switch (option)
{
case 0:
unitFlags = unitFlags | NSYearCalendarUnit;
break;
case 1:
unitFlags = unitFlags | NSMonthCalendarUnit;
break;
case 2:
unitFlags = unitFlags | NSWeekCalendarUnit;
break;
case 3:
unitFlags = unitFlags | NSDayCalendarUnit;
break;
case 4:
unitFlags = unitFlags | NSHourCalendarUnit;
break;
case 5:
unitFlags = unitFlags | NSMinuteCalendarUnit;
break;
}
}
正如你所看到的,我正在根据数组中的whats构建我的单位标志。
现在我需要如何构建日历,但我怎么知道组件和格式是什么?
以下是答案:
NSString *prularity = @"";
if ([future compare:today] == NSOrderedAscending ) {
conversionInfo = [sysCalendar components:unitFlags fromDate:future toDate:today options:0];
untilOrSince = @"since";
} else {
conversionInfo = [sysCalendar components:unitFlags fromDate:today toDate:future options:0];
untilOrSince = @"until";
}
在这里,我使用所选单位构建我的日历,我也计算日期或日期。
最后,我只需要根据所选内容进行格式化:
for (int fuu = 0; fuu < myWords.count; fuu++) {
option = [[myWords objectAtIndex:fuu]intValue];
switch (option)
{
case 0:
if ([conversionInfo year] >= 2 || [conversionInfo year] == 0) {
prularity = @"YEARS";
} else {
prularity = @"YEAR";
}
one = [one stringByAppendingString:[NSString stringWithFormat:@"%ld %@ ", (long)[conversionInfo year], prularity]];
break;
case 1:
if ([conversionInfo month] >= 2|| [conversionInfo month] == 0) {
prularity = @"MONTHS";
} else {
prularity = @"MONTH";
}
one = [one stringByAppendingString:[NSString stringWithFormat:@"%ld %@ ", (long)[conversionInfo month], prularity]];
break;
case 2:
if ([conversionInfo week] >= 2 || [conversionInfo week] == 0) {
prularity = @"WEEKS";
} else {
prularity = @"WEEK";
}
one = [one stringByAppendingString:[NSString stringWithFormat:@"%ld %@ ", (long)[conversionInfo week], prularity]];
break;
case 3:
if ([conversionInfo day] >= 2 || [conversionInfo day] == 0) {
prularity = @"DAYS";
} else {
prularity = @"DAY";
}
one = [one stringByAppendingString:[NSString stringWithFormat:@"%ld %@ ", (long)[conversionInfo day], prularity]];
break;
case 4:
if ([conversionInfo hour] >= 2 || [conversionInfo hour] == 0) {
prularity = @"HOURS";
} else {
prularity = @"HOUR";
}
one = [one stringByAppendingString:[NSString stringWithFormat:@"%ld %@ ", (long)[conversionInfo hour], prularity]];
break;
case 5:
if ([conversionInfo minute] >= 2 || [conversionInfo minute] == 0) {
prularity = @"MINUTES";
} else {
prularity = @"MINUTE";
}
one = [one stringByAppendingString:[NSString stringWithFormat:@"%ld %@ ", (long)[conversionInfo minute], prularity]];
break;
}
}
打印我的柜台:
one = [one stringByAppendingString:[NSString stringWithFormat:@" %@",untilOrSince]];
self.eventTimer.text = one;
希望这可以帮助有类似问题的人。我知道这不是最好的解决方案,但到目前为止它还有效。