tableview cell 上播放倒計時
項目中有用到cell上播放倒計時,遇到很多的坑,在這里總結(jié)一些以免下次再遇到
- 1 第一條跟NStimer無關(guān) 只是平時項目中的細節(jié)問題,一定要注意block中的循環(huán)引用問題,這里有兩種方法
// 第一種創(chuàng)建一個self弱引用
#define WS(weakSelf) __weak __typeof(&*self)weakSelf = self;
//第二種就是如果項目中用到了reactivecocoa這個第三方的話 使用 @weakify(self)
@Strongify(self)
這兩個是成對出現(xiàn)的block外用@weakify block里面用@strongify(今天發(fā)現(xiàn)好多控制器請求數(shù)據(jù)的時候沒有嚴格使用,導(dǎo)致很多控制器沒有釋放)
-
2 這里只說我自己遇到的問題及解決辦法,基本的介紹就不再說了
(1)定時器如果要循環(huán)的話需要加入到runloop中
[[NSrunLoop currenRunLoop] addTimer:_timerforMode:NSRunLoopCommonModes]
(2)定時器創(chuàng)建的線程和釋放的線程應(yīng)該在同一個線程,否則的話無法釋放有興趣的同學(xué)可以試一下
//創(chuàng)建
dispatch_async(dispatch_get_main_queue(), ^{
if (self.time) {
[self.time invalidate];
}
self.time = [NSTimer ez_scheduledTimerWithTimeInterval:1 block:^{
NSDate *currentDate =[NSDate date];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSCalendarUnit unit = NSDayCalendarUnit | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
NSDateComponents *commponent = [calendar components:unit fromDate:currentDate toDate:[NSDate dateWithString:weakSelf.endTime ] options:NSCalendarWrapComponents];
NSDate *dt = [[NSDate dateWithString: weakSelf.endTime] earlierDate:currentDate];
NSLog(@"-------------------%@",weakSelf.endTime);
// self.getPrimeRate.enabled =YES;
if([dt isEqualToDate:[NSDate dateWithString:weakSelf.endTime ]])
{
[weakSelf.time invalidate];
weakSelf.countDownLabel.text = @"??距離開放認投剩余0天00時00分00秒";
}else
{
weakSelf.countDownLabel.text = [NSString stringWithFormat:@"??距離開放認投剩余%zd天%02zd時%02zd分%02zd秒",commponent.day,commponent.hour,commponent.minute,commponent.second];
}
} repeats:YES];
});
這里是釋放
dispatch_async(dispatch_get_main_queue(), ^{
@strongify(self)
[self.time invalidate];
self.time = nil;
NSLog(@"timer停止了");
});
注 這里我使用的是一個NStimer的分類原文有詳細介紹就是創(chuàng)建一個對self弱引用的Nstimer原文
- 3 由于cell的重用問題 每次控制pop或者dismiss的時候,都不能夠釋放所以尤其是在和定時器一起用的時候要特別的注意循環(huán)引用的問題 ,我就是 遇到了這樣的問題感覺很坑的 ,我們要想釋放cell就需要知道 控制器的UIviewcontroller的dealoc方法 那么我們怎么才能在cell中得到cell所在的控制器呢 為了降低耦合度 有網(wǎng)友想到了給view添加一個擴展的方法原文在這原文有循序漸進的講解為什么但是最終沒有完全解決我遇到的問題,很不錯了
核心代碼 :
- (UIViewController*)getViewController
{
for (UIView* next = [self superview]; next; next = next.superview)
{
UIResponder* nextResponder = [next nextResponder];
if ([nextResponder isKindOfClass:[UIViewController class]])
{
return (UIViewController*)nextResponder;
}
}
return nil; }
其實是使用響應(yīng)者鏈得到對應(yīng)的Controller 這樣的話cell就可以得到對應(yīng)的Controller 然后使用RAC得到控制器銷毀的消息發(fā)送時刻釋放定時器。
核心代碼如下 :
- (void)didMoveToSuperview
{
UIViewController *controller = [self getViewController];
//這里需要判斷相應(yīng)的controller是否存在
if (controller){
@weakify(self)
[controller.rac_willDeallocSignal
subscribeCompleted:^{
@strongify(self)
[self.countDownTimer invalidate];
self.countDownTimer = nil;
}];
}
}
這里釋放的時機很重要使用上面的擴展需要Cell被添加到視圖樹之后才能獲取到需要的UIViewController,不然得到會是一個空。那么怎么保證Cell一定被添加到視圖樹呢。UIView有個方法叫didMoveToSuperview,它會在該視圖的父視圖改變的時候被調(diào)用
-
4最后的時候發(fā)現(xiàn)雖然好了很多打印的時候仍然有一個定時器不能釋放 ,試了很多的辦法都不行 所以 就在cell 的dealoc方法中又釋放了一次就好了具體是什么原因暫時還沒發(fā)現(xiàn),希望有知道的大神能夠說一下啊,畢竟自己還是一個菜鳥。
最后又發(fā)現(xiàn)了一個好的例文還沒仔細看【iOS】TableViewCell上展示倒計時;
好了先寫這么多,有想起來的再補充吧。