iOS工具類-OC篇

最近想整理下關于OC的工具類,常用到的也方便自己之后查閱,也可以給需要的朋友參考。

1、兩種倒計時

  • 第一種:GCD
__block NSInteger timeout = time;//可以假設time等于60秒
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_source_t _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    dispatch_source_set_timer(_timer,dispatch_walltime(NULL, 0),1.0*NSEC_PER_SEC, 0); //每秒執(zhí)行
    dispatch_source_set_event_handler(_timer, ^{
        if(timeout<=0){ //倒計時結束,關閉
            dispatch_source_cancel(_timer);
            dispatch_async(dispatch_get_main_queue(), ^{
                //主線程中處理UI
            });
        }else{
            dispatch_async(dispatch_get_main_queue(), ^{
                //主線程中處理UI
                presellTimeLB.text = [self dateFormatDays_Hours_MinsWith:timeout];
            });
            timeout--;
        }
    });
    dispatch_resume(_timer);

這里我假設我有一個名為presellTimeLB的Label,處理倒計時的方法dateFormatDays_Hours_MinsWith: (僅供參考)

 - (NSString *)dateFormatDays_Hours_MinsWith:(NSInteger)time
{
    NSInteger days = 0,hours = 0,minutes = 0,second = 0;
    NSInteger daySeconds = 24*60*60;
    //獲取天數(shù)
    if (time >= daySeconds) {
        days = time/daySeconds;
        time = time%daySeconds;
    }
    //獲取小時數(shù)
    if(time>=60*60){
        hours = time/3600;
        time = time%3600;
    }
    //獲取分鐘數(shù)
    if (time>=60) {
        minutes = time/60;
        time = time%60;
    }
    //獲取秒數(shù)
    second = time;
    if (days>0) {
        return [NSString stringWithFormat:@"%ld天%ld時%ld分",(long)days,(long)hours,(long)minutes];
    }else{
        return [NSString stringWithFormat:@"%ld時%ld分%ld秒",(long)hours,(long)minutes,(long)second];
    }
}
  • 第二種:NSTimer

1)聲明

[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerFireMethod:) userInfo:nil repeats:YES];

2)實現(xiàn)select方法

 - (void)timerFireMethod:(NSTimer *)theTimer
{
    timer = theTimer;
    static NSInteger hhh;
    if (timeStart) {
        hhh = [self.leftTime integerValue];
        timeStart = NO;
    }
    if (hhh <= 1) {
        preSellView.hidden = YES;
        //注①
        [timer invalidate];
    }else {   
        //注②
        [[NSRunLoop currentRunLoop] addTimer:theTimer forMode:NSRunLoopCommonModes];
        hhh--;
        dispatch_async(dispatch_get_main_queue(), ^{
            [presellTimeLB setText:[self dateFormatDays_Hours_MinsWith:hhh]];
        });
    }
}

注:
NSTimer對象用完之后必須進行invalidateNSTimer才會消失。比如說你還需要考慮到倒計時沒結束時退出當前頁面時是不是也需要把當前的NSTimer invalidate呢?
②這里為什么要用NSRunLoop寫這句代碼呢?如果沒有這句代碼,會發(fā)現(xiàn)在界面上滾動一個scrollView,那么滾動停止前,timer像是暫停了一樣,其實這是runloop的mode在作怪。
runloop可以理解為cocoa下的一種消息循環(huán)機制,用來處理各種消息事件,我們在開發(fā)的時候并不需要手動去創(chuàng)建一個runloop,因為框架為我們創(chuàng)建了一個默認的runloop,通過[NSRunloop currentRunloop]我們可以得到一個當前線程下面對應的runloop對象,不過我們需要注意的是不同的runloop之間消息的通知方式。
在開啟一個NSTimer實質(zhì)上是在當前的runloop中注冊了一個新的事件源,而當scrollView滾動的時候,當前的MainRunLoop是處于UITrackingRunLoopMode的模式下,在這個模式下,是不會處理NSDefaultRunLoopMode的消息(因為RunLoop Mode不一樣),要
要想在scrollView滾動的同時也響應其他runloop的消息,需要改變兩者之間的runloopMode.

[[NSRunLoop currentRunLoop] addTimer:theTimer forMode:NSRunLoopCommonModes];
  • NSTimer 的另一種寫法
  - (void)timerFireMethod:(NSTimer *)theTimer
{
    NSCalendar *cal = [NSCalendar currentCalendar];//定義一個NSCalendar對象
    NSDateComponents *endTime = [[NSDateComponents alloc] init];    //初始化目標時間...
    NSDate *today = [NSDate date];    //得到當前時間
    NSDate *date = [NSDate dateWithTimeInterval:80 sinceDate:today];
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
    NSString *dateString = [dateFormatter stringFromDate:date];
    static int year;
    static int month;
    static int day;
    static int hour;
    static int minute;
    static int second;
    if(timeStart) {//從NSDate中取出年月日,時分秒,但是只能取一次
        year = [[dateString substringWithRange:NSMakeRange(0, 4)] intValue];
        month = [[dateString substringWithRange:NSMakeRange(5, 2)] intValue];
        day = [[dateString substringWithRange:NSMakeRange(8, 2)] intValue];
        hour = [[dateString substringWithRange:NSMakeRange(11, 2)] intValue];
        minute = [[dateString substringWithRange:NSMakeRange(14, 2)] intValue];
        second = [[dateString substringWithRange:NSMakeRange(17, 2)] intValue];
        timeStart= NO;
    }
    [endTime setYear:year];
    [endTime setMonth:month];
    [endTime setDay:day];
    [endTime setHour:hour];
    [endTime setMinute:minute];
    [endTime setSecond:second];
    NSDate *todate = [cal dateFromComponents:endTime]; //把目標時間裝載入date
    //用來得到具體的時差,是為了統(tǒng)一成北京時間
    unsigned int unitFlags = NSYearCalendarUnit| NSMonthCalendarUnit| NSDayCalendarUnit| NSHourCalendarUnit| NSMinuteCalendarUnit| NSSecondCalendarUnit;
    NSDateComponents *d = [cal components:unitFlags fromDate:today toDate:todate options:0];
    NSString *h = [NSString stringWithFormat:@"%ld",(long)[d hour]];
    
    NSString *fen = [NSString stringWithFormat:@"%ld", (long)[d minute]];
    if([d minute] < 10) {
        fen = [NSString stringWithFormat:@"%ld",[d minute]];
    }
    NSString *miao = [NSString stringWithFormat:@"%ld", (long)[d second]];
    if([d second] < 10) {
        miao = [NSString stringWithFormat:@"0%ld",(long)[d second]];
    }
    if([d second] >= 0) {
        //計時尚未結束,do_something
        dispatch_async(dispatch_get_main_queue(), ^{
            [[NSRunLoop currentRunLoop] addTimer:theTimer forMode:NSRunLoopCommonModes];
            [presellTimeLB setText:[NSString stringWithFormat:@"%ld時%ld分%ld秒",[h integerValue],[fen integerValue], [miao integerValue]]];
        });
    } else{
        //倒計時結束,do something
        [theTimer invalidate];
    }
}

注:這里我們以80秒倒計時為例,還是假設我有一個BOOL類型的timeStart為了取一次原始時間,有名為presellTimeLB的Laber,nsrunloop改變mode的狀態(tài)照樣寫上。這里把時間處理和邏輯判斷寫在了一起。

2、字符串富文本處理之NSMutableAttributedString

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內(nèi)容