ios - 显示启用/禁用时间单位的倒计时
<p><p>这个问题基本上是关于自定义日期格式的。我设法开发了一个倒计时应用程序,该应用程序设法创建一个事件,以后可以由客户查看、自定义或跟踪。重要的部分是倒计时计时器,它从 db 中获取秒数并根据日期格式化程序显示剩余时间。到目前为止,我在应用程序中使用默认设置,计数器格式为 dd:hh:mm,显然我的客户希望允许应用程序用户自定义时间的显示方式。所以现在用户可以选择四个选项,例如 yy:weeks:hh:mm 或months:weeks:days:hours。我认为最好的方法是将表四个索引作为字符串保存到 db 中。我的问题出现在日历上。 </p>
<pre><code>conversionInfo = ;
one = , ,,, untilOrSince]; self.eventTimer.text = one;
conversionInfo = ;
one = , untilOrSince];
</code></pre>
<p>此外,如果我确实使用所有单位构建日历但仅显示秒,那么倒计时将仅显示 59 秒而不是 343746545 秒,直到
<img src="/image/V0bjn.jpg" alt="The counter"/> </p>
<p>例如,这些日历单位不能放置在数组中,那么如果用户选择 2、4、5、6(即月:日:小时:分钟),我将如何选择日历格式?我不能说 <code>components = , ,nil];</code></p>
<p> <img src="/image/DAIQS.jpg" alt="User options"/> </p>
<p>有什么想法吗?</p></p>
<br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
<p><p>好吧,这比我最初想象的要难</p>
<hr/>
<p>在整个系统中,单位标志用于将日期定义为组件等。这个单元缺陷可以组合成一个值,一个位掩码。我将它用于我的代码。</p>
<p>年份单位可能是<code>0....000010</code>
月份单位可能是 <code>0....000100</code></p>
<p>两者的位掩码都是</p>
<pre><code>0....000010 NSCalendarUnitYear
0....000100 NSCalendarUnitMonth
------------
& 0....000110
</code></pre>
<p>所以要保存要使用一个单元的信息意味着我们只需将适当的位设置为 <code>1</code></p>
<pre><code>- (void)viewDidLoad
{
;
self.selectedUnitsBitmask= 0;
self.unitNames = @[ @"Year", @"Month", @"Week", @"Day", @"Hour", @"Minute", @"Second"];
self.units = @[@(NSCalendarUnitYear), @(NSCalendarUnitMonth), @(NSCalendarUnitWeekOfMonth), @(NSCalendarUnitDay), @(NSCalendarUnitHour), @(NSCalendarUnitMinute), @(NSCalendarUnitSecond)];
NSDateComponents *c = [ init];
c.year = 2014;
c.month = 12;
c.day = 25;
self.futureDate = [ dateFromComponents:c];
}
</code></pre>
<p><code>self.unitNames</code> 的值用于填充表格 View 。<br/>
<code>self.units</code> 存储每个可用单元的单元标志。</p>
<pre><code>-(UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier =@"Cell";
UITableViewCell *cell = ;
cell.textLabel.text = _unitNames;
NSUInteger s;
NSUInteger row = indexPath.row;
s = NSIntegerMax & integerValue];
cell.accessoryType = (self.selectedUnitsBitmask & s) ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
return cell;
}
</code></pre>
<p>如果选择了一个单元格,<code>s = NSIntegerMax & integerValue];</code> 将检查位掩码,如果要使用这个单元。</p>
<p>如果选择了一个单元格,我们想要切换它所代表的单元的位</p>
<pre><code>-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSUInteger s;
NSUInteger row = indexPath.row;
s = NSIntegerMax & integerValue];
self.selectedUnitsBitmask ^= s ;
NSLog(@"%lu, %lu", (unsigned long)s, (unsigned long)self.selectedUnitsBitmask);
UITableViewCell *cell = ;
cell.accessoryType =(self.selectedUnitsBitmask & s) ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
;
}
</code></pre>
<p>这里</p>
<pre><code>NSUInteger s;
NSUInteger row = indexPath.row;
s = NSIntegerMax & integerValue];
</code></pre>
<p><code>s</code>代表被选中的位,</p>
<pre><code>self.selectedUnitsBitmask ^= s ;
</code></pre>
<p>将在位掩码中切换它。 <code>bitmask ^= s</code> 是 <code>bitmask = bitmask ^ s</code> 的简写形式,其中 <code>^</code> 是异或:位掩码的第 n 位有与s的第n位相反</p>
<pre><code>0011 bitmask
^ 0101 s
----
= 1100
</code></pre>
<p>现在我们可以根据位掩码中的单位标志更新将打印时差的字符串:</p>
<pre><code>- (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 = [ components:self.selectedUnitsBitmask fromDate: toDate:self.futureDate options:0];
NSMutableString *outputString = [@"" mutableCopy];
if (includeYear && diffDateComponents.year)
;
if (includeMonth && diffDateComponents.month)
;
if (diffDateComponents.weekOfMonth < NSIntegerMax && diffDateComponents.weekOfMonth)
;
if (includeDay && diffDateComponents.day)
;
if (includeHour && diffDateComponents.hour)
;
if (includeMinute && diffDateComponents.minute)
;
if (includeSecond && diffDateComponents.second)
;
self.countDownLabel.text = ];
}
</code></pre>
<p>要确定是否设置了标志,我们使用 <code>&</code> AND 运算符</p>
<pre><code>BOOL includeYear= self.selectedUnitsBitmask & NSCalendarUnitYear;
</code></pre>
<p>如果年份标志是 <code>0....000010</code></p>
<p>位掩码包含<code>0....010110</code></p>
<p><code>&</code> 操作会返回</p>
<pre><code>0....000010 NSCalendarUnitYear
& 0....010110 bitmask
-------------
= 0....000010 -> NSCalendarUnitYear
</code></pre>
<p>我们为所有单位执行此操作一周。我不知道为什么,但是 & 操作总是为它返回 0。这里我们使用 hack:</p>
<pre><code>if (diffDateComponents.weekOfYear < NSIntegerMax)
;
</code></pre>
<p>对于新的 NSDateComponents <code>week</code> 用整数表示的最大数 NSIntegerMax 进行实例化。如果它的值小于 NSIntegerMax 我们假设它被设置并且我们将它附加到字符串中。</p>
<hr/>
<p>结果:</p>
<p> <img src="/image/fbGuI.png" alt="enter image description here"/> </p>
<hr/>
<p>将整个代码合二为一:</p>
<hr/>
<pre><code>#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
{
;
self.selectedUnitsBitmask= 0;
self.unitNames = @[ @"Year", @"Month", @"Week", @"Day", @"Hour", @"Minute", @"Second"];
self.units = @[@(NSCalendarUnitYear), @(NSCalendarUnitMonth), @(NSCalendarUnitWeekOfMonth), @(NSCalendarUnitDay), @(NSCalendarUnitHour), @(NSCalendarUnitMinute), @(NSCalendarUnitSecond)];
NSDateComponents *c = [ init];
c.year = 2014;
c.month = 12;
c.day = 25;
self.futureDate = [ dateFromComponents:c];
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return ;
}
-(UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier =@"Cell";
UITableViewCell *cell = ;
cell.textLabel.text = _unitNames;
NSUInteger s;
NSUInteger row = indexPath.row;
s = NSIntegerMax & 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 & integerValue];
self.selectedUnitsBitmask ^= s ;
NSLog(@"%lu, %lu", (unsigned long)s, (unsigned long)self.selectedUnitsBitmask);
UITableViewCell *cell = ;
cell.accessoryType =(self.selectedUnitsBitmask & s) ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
;
}
- (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 = [ components:self.selectedUnitsBitmask fromDate: toDate:self.futureDate options:0];
NSMutableString *outputString = [@"" mutableCopy];
if (includeYear && diffDateComponents.year)
;
if (includeMonth && diffDateComponents.month)
;
if (diffDateComponents.weekOfMonth < NSIntegerMax && diffDateComponents.weekOfMonth)
;
if (includeDay && diffDateComponents.day)
;
if (includeHour && diffDateComponents.hour)
;
if (includeMinute && diffDateComponents.minute)
;
if (includeSecond && diffDateComponents.second)
;
self.countDownLabel.text = ];
}
</code></pre></p>
<p style="font-size: 20px;">关于ios - 显示启用/禁用时间单位的倒计时,我们在Stack Overflow上找到一个类似的问题:
<a href="https://stackoverflow.com/questions/21289670/" rel="noreferrer noopener nofollow" style="color: red;">
https://stackoverflow.com/questions/21289670/
</a>
</p>
页:
[1]