tableview cell 上播放倒計(jì)時(shí)
項(xiàng)目中有用到cell上播放倒計(jì)時(shí),遇到很多的坑,在這里總結(jié)一些以免下次再遇到
- 1 第一條跟NStimer無(wú)關(guān) 只是平時(shí)項(xiàng)目中的細(xì)節(jié)問(wèn)題,一定要注意block中的循環(huán)引用問(wèn)題,這里有兩種方法
// 第一種創(chuàng)建一個(gè)self弱引用
#define WS(weakSelf) __weak __typeof(&*self)weakSelf = self;
//第二種就是如果項(xiàng)目中用到了reactivecocoa這個(gè)第三方的話 使用 @weakify(self)
@Strongify(self)
這兩個(gè)是成對(duì)出現(xiàn)的block外用@weakify block里面用@strongify(今天發(fā)現(xiàn)好多控制器請(qǐng)求數(shù)據(jù)的時(shí)候沒(méi)有嚴(yán)格使用,導(dǎo)致很多控制器沒(méi)有釋放)
-
2 這里只說(shuō)我自己遇到的問(wèn)題及解決辦法,基本的介紹就不再說(shuō)了
(1)定時(shí)器如果要循環(huán)的話需要加入到runloop中
[[NSrunLoop currenRunLoop] addTimer:_timerforMode:NSRunLoopCommonModes]
(2)定時(shí)器創(chuàng)建的線程和釋放的線程應(yīng)該在同一個(gè)線程,否則的話無(wú)法釋放有興趣的同學(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 = @"??距離開(kāi)放認(rèn)投剩余0天00時(shí)00分00秒";
}else
{
weakSelf.countDownLabel.text = [NSString stringWithFormat:@"??距離開(kāi)放認(rèn)投剩余%zd天%02zd時(shí)%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停止了");
});
注 這里我使用的是一個(gè)NStimer的分類原文有詳細(xì)介紹就是創(chuàng)建一個(gè)對(duì)self弱引用的Nstimer原文
- 3 由于cell的重用問(wèn)題 每次控制pop或者dismiss的時(shí)候,都不能夠釋放所以尤其是在和定時(shí)器一起用的時(shí)候要特別的注意循環(huán)引用的問(wèn)題 ,我就是 遇到了這樣的問(wèn)題感覺(jué)很坑的 ,我們要想釋放cell就需要知道 控制器的UIviewcontroller的dealoc方法 那么我們?cè)趺床拍茉赾ell中得到cell所在的控制器呢 為了降低耦合度 有網(wǎng)友想到了給view添加一個(gè)擴(kuò)展的方法原文在這原文有循序漸進(jìn)的講解為什么但是最終沒(méi)有完全解決我遇到的問(wèn)題,很不錯(cuò)了
核心代碼 :
- (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; }
其實(shí)是使用響應(yīng)者鏈得到對(duì)應(yīng)的Controller 這樣的話cell就可以得到對(duì)應(yīng)的Controller 然后使用RAC得到控制器銷毀的消息發(fā)送時(shí)刻釋放定時(shí)器。
核心代碼如下 :
- (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;
}];
}
}
這里釋放的時(shí)機(jī)很重要使用上面的擴(kuò)展需要Cell被添加到視圖樹(shù)之后才能獲取到需要的UIViewController,不然得到會(huì)是一個(gè)空。那么怎么保證Cell一定被添加到視圖樹(shù)呢。UIView有個(gè)方法叫didMoveToSuperview,它會(huì)在該視圖的父視圖改變的時(shí)候被調(diào)用
-
4最后的時(shí)候發(fā)現(xiàn)雖然好了很多打印的時(shí)候仍然有一個(gè)定時(shí)器不能釋放 ,試了很多的辦法都不行 所以 就在cell 的dealoc方法中又釋放了一次就好了具體是什么原因暫時(shí)還沒(méi)發(fā)現(xiàn),希望有知道的大神能夠說(shuō)一下啊,畢竟自己還是一個(gè)菜鳥(niǎo)。
最后又發(fā)現(xiàn)了一個(gè)好的例文還沒(méi)仔細(xì)看【iOS】TableViewCell上展示倒計(jì)時(shí);
好了先寫(xiě)這么多,有想起來(lái)的再補(bǔ)充吧。