你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發基礎 >> 源碼分享:高仿喜馬拉雅FM

源碼分享:高仿喜馬拉雅FM

編輯:IOS開發基礎

項目地址github:https://github.com/Eastwu5788/XMLYFM 如果您覺得不錯,記得給一個star

最新用空閒時間高仿了一下喜馬拉雅FM這款APP,目前主要完成了發現欄目中的推薦頁面。

效果演示

分析

+發現tab中有五個小分類,分別對應五個頁面,所有在“發現”的控制器中使用了UIPageViewController來控制五個子控制器。
+從Charles抓出來的接口來看,“推薦”頁面一共調用了三個接口,分別請求了推薦、熱門、直播的內容,所以在這裡選擇了Reactivecocoa來實現接口的並發訪問

- (void)refreshDataSource {       

    @weakify(self);
    RACSignal *signalRecommend = [RACSignal createSignal:^RACDisposable *(id subscriber) {
        @strongify(self);
        [self requestRecommendList:^{
            [subscriber sendNext:nil];
        }];
        return nil;
    }];    

    RACSignal *signalHotAndGuess = [RACSignal createSignal:^RACDisposable *(id subscriber) {
        @strongify(self);
        [self requestHotAndGuessList:^{
            [subscriber sendNext:nil];
        }];
        return nil;
    }];

    RACSignal *signalLiving = [RACSignal createSignal:^RACDisposable *(id subscriber) {
        @strongify(self);
        [self requestLiving:^{
            [subscriber sendNext:nil];
        }];
        return nil;
    }];

    [[RACSignal combineLatest:@[signalRecommend,signalHotAndGuess,signalLiving]] subscribeNext:^(id x) {
        @strongify(self);
        [(RACSubject *)self.updateContentSignal sendNext:nil];
    }];
}



文章轉自 耐心_朱迪的簡書

+在“推薦”頁面中有幾個輪播圖,仔細觀察會發現它的輪播圖一直想左轉換,所以這裡的輪播圖片需要做一下特殊處理。以實現無限輪播的效果

- (void)setModel:(XMLYFindFocusImagesModel *)model  {      
    _model = model;    
    [self.adverScrollView removeAllSubViews];    
    self.adverScrollView.contentSize = CGSizeMake(kScreenWidth * _model.list.count, 150);     
    //1.向scrollView中增加UIImageView的時候,需要在最後一張圖片後面將第一張圖片添加上去    
    for(NSInteger index = 0; index <= _model.list.count; index++)   {      
        //2.如果是最後一張圖片,則放置第一張圖片
        XMLYFindFocusImageDetailModel \*detail = index == _model.list.count ? _model.list.firstObject : [_model.list objectAtIndex:index];
        UIImageView \*imageView = [[UIImageView alloc] init];
        imageView.frame = CGRectMake(kScreenWidth \* index, 0, kScreenWidth, 150);
        [imageView yy_setImageWithURL:[NSURL URLWithString:detail.pic] options:YYWebImageOptionSetImageWithFadeAnimation];
        [self.adverScrollView addSubview:imageView];
    }
}

在輪播圖滾動動畫結束後需要做一下判斷,如果當前滾動到了最後一張圖片,則立即將scrollView的偏移調整到初始位置,這樣一個無限輪播就完成了。

- (void)scrollViewDidScroll:(UIScrollView \*)scrollView {   
    NSInteger curPage = self.adverScrollView.contentOffset.x / kScreenWidth;    
    if(curPage == self.model.list.count) {    
        [self.adverScrollView setContentOffset:CGPointMake(0, 0) animated:NO];    
      }
}

在有輪播圖的地方肯定少不了定時器,如果將定時器直接放在cell中,就會因為cell的復用導致定時器出現問題,所有一般是將定時器放在控制器中。但是這樣的話也帶來一個問題,就是由於定時器的存在,如果要求定時器的生命周期和控制器相同(也就是在控制器dealloc的時候才取消定時器).這樣的控制器是無法調用dealloc的,會造成控制器雖然已經退出但是定時器依然在正常工作。所以這裡專門為控制器設計了一個定時器的單例幫助類,這樣的話就可以在dealloc中去銷毀所有的定時器。

@interface XMLYFindRecommendHelper : NSObject    
#pragma mark - Common    
//生成幫助類單例
+ (instancetype)helper;    

//銷毀所有的定時器    
- (void)destoryAllTimer;

#pragma mark - Live    

//  開啟為直播設置的定時器      
- (void)startLiveTimer;    

//銷毀直播的定時器    
- (void)destoryLiveTimer;    

#pragma mark - Header    

//開啟頭部的定時器    
- (void)startHeadTimer;    

//銷毀頭部的定時器    
- (void)destoryHeaderTimer;    
@end

在廣播頁面中,有一個根據當前時間顯示不同的問候語的小功能。比如現在是早上6點鐘,應該顯示“早安*北京”。這裡就需要用到NSDateFormatter,但是NSDateFormatter的比較消耗性能,所以我專門寫了一個XMLYTimeHelper類來管理所有的時間轉換操作。在這個類中對NSDateFormatter做了緩存處理,並使用dispatch_semaphore_t保證了線程安全。

//根據字符串生成相應的NSDateFormatter,比如"yyyy-MM-dd HH:mm:ss"
static force_inline NSDateFormatter *XMLYDataCreateFormatter(NSString *string) {
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    formatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
    formatter.dateFormat = string;
    return formatter;
}

//用戶直接調用此方法,傳入"yyyy-MM-dd HH:mm:ss"這樣的字符串生成NSDateFormatter
static force_inline NSDateFormatter *XMLYDateFormatter(NSString *string) {
    //1.檢查輸入的合法性
    if(!string || ![string isKindOfClass:[NSString class]] || string.length == 0) return nil;
   //2.初始化單例參數
    static CFMutableDictionaryRef cache;
    static dispatch_semaphore_t lock;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        cache = CFDictionaryCreateMutable(CFAllocatorGetDefault(), 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
        lock = dispatch_semaphore_create(1);
    });

    //3.加鎖
    dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER);
    //4.查詢當前字符串是否已經存在相應的NSDateformatter
    NSDateFormatter *formatter = CFDictionaryGetValue(cache, (__bridge const void *)(string));
   //5.解鎖
    dispatch_semaphore_signal(lock);

   //6.如果緩存中沒有,則需要重新生成
    if(!formatter) {
        formatter = XMLYDataCreateFormatter(string);
        //7.重新生成成功,存入緩存
        if(formatter) {
            dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER);
            CFDictionarySetValue(cache, (__bridge const void *)(string), (__bridge const void *)(formatter));
            dispatch_semaphore_signal(lock);
        }
    }
    return formatter;
}



文章轉自 East_wu的簡書
  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved