iOS 模仿一個小項目,總結一下里邊的模塊

  ManoBoo:  參考連接:http://www.jianshu.com/p/fd4c46c31508

 這個小的項目是參考ManoBoo的簡書的,連接在上方,本身在仿作的過程當中,也離不開ManoBoo的幫助

 

一 配置項目的基本環境

    1 Pod AVFoundation框架,ReactiveCocoa框架vim

      -->從終端打開項目  cd+文件路徑  設計模式

        

      -->建立Podfile文件   vim Podfile 多線程

          

 

      -->安裝第三方框架  pod installapp

        

         

  

    2 使用pch文件框架

      -->新建pch文件異步

        

      -->將須要用到的全局的頭文件和宏添加進去async

        

    3 導入ttf字體文件並使用ide

      -->獲取字體文件ttf函數

      -->將ttf文件copy到項目中字體

      -->在Info.plist中添加項

        

      -->在Project--Build Phases--Copy Bundle Resoueces中添加資源

        

      -->使用(要使用字體的真實名稱,而不是文件名)

二 基礎頁面的搭建

    根據須要將項目分紅相應的模塊,在這裏按照頁面以及功能劃分

        

    1 開始頁面

            

    1-1 添加按鈕

- (void)setMainView
{
    _startBtn = [[UIButton alloc] initWithFrame:CGRectMake(0, 20, SCREEN_WIDTH / 2, SCREEN_HEIGHT)];
    _startBtn.backgroundColor = [UIColor blackColor];
    _startBtn.titleLabel.font = [UIFont fontWithName:@"FZMiaoWuS-GB" size:36];
    [_startBtn setTitle:@"開始遊戲 " forState:UIControlStateNormal];

    WeakSelf;
    [[_startBtn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) {
       
        [weakSelf buttonHideAnimation];
        
        [weakSelf presentViewController:[[GameSceneViewController alloc] init] animated:false completion:^{
            [SoundPlayer pauseBGMMusic];
        }];
        
    }];

    [self.view addSubview:_startBtn];

    1-2 給按鈕添加點擊事件

     [_startButton rac_signalForControlEvents:UIControlEventTouchUpInside]返回一個 RACSignal,能夠理解爲 一個信號,用於監聽事件,後面 subscribeNext:^(id x) {} 用於訂閱信號

      

    1-3 給按鈕添加動畫

# pragma mark : 按鈕消失/ 出現動畫

- (void)buttonHideAnimation
{
    [UIView animateWithDuration:0.4 animations:^{
        _startBtn.center = CGPointMake(- _startBtn.center.x, _startBtn.center.y);
        _settingBtn.center = CGPointMake(_settingBtn.center.x + SCREEN_WIDTH, _settingBtn.center.y);
    }];
}

- (void)buttonShowAnimation
{
    [UIView animateWithDuration:0.4 animations:^{
        _startBtn.center = CGPointMake(SCREEN_WIDTH / 4, _startBtn.center.y);
        _settingBtn.center = CGPointMake(SCREEN_WIDTH / 4 * 3, _settingBtn.center.y);
    }];
}

      使用的是UIView的block動畫

      

  2 倒計時動畫頁面    

- (CAAnimationGroup *)setAnimationGroup
{
    //縮放動畫
    CABasicAnimation *animation1 = [CABasicAnimation animation];
    [animation1 setKeyPath:@"transform.scale"];
    [animation1 setFromValue:@1.0];
    [animation1 setToValue:@4.0];
    [animation1 setDuration:1.0];
    //透明度改變更畫
    CABasicAnimation *animation2 = [CABasicAnimation animation];
    [animation2 setKeyPath:@"alpha"];
    [animation2 setFromValue:@1.0];
    [animation2 setToValue:@0.3];
    [animation2 setDuration:1.0];
    
    CAAnimationGroup *animationGroup = [[CAAnimationGroup alloc] init];
    animationGroup.animations = [NSArray arrayWithObjects:animation1, animation2, nil];
    [animationGroup setDuration:1.0];
    [animationGroup setDelegate:self];
    
    return animationGroup;
}

    使用的是CABasicAnimation基礎動畫

    這個ManoBoo在簡書中已經講的很詳細了,此處略去

  3 遊戲界面以及點擊按鈕以後的閃爍動畫效果

    如何搭建遊戲界面,在簡書中也有很是詳細的介紹

    4 點擊錯誤後彈出的失敗頁面

     

    4-1 此處重點在於如何在xib中使用位置的綁定

    4-2 點擊結束按鈕後會跳轉回開始頁面

      用 presentViewController 方法進入遊戲頁面,對應的,用 dismissViewControllerAnimated 方法能夠返回

      用 pushViewController 方法進入的話,則須要調用 popViewControllerAnimated 方法返回

  5 設置頁面的搭建

        

    5-1 與錯誤頁面的搭建相似,區別在於其中加入了按鈕動畫

      5-1 水波紋動畫按鈕

         將CABasicAnimation基礎動畫和CAKeyframeAnimation幀動畫結合使用  

- (void)drawRect:(CGRect)rect{
    
    NSInteger pulsingCount = 6;//波紋的環數
    double animationDuration = 5;
    
    CALayer * animationLayer = [CALayer layer];//動畫layer
    
    for (int i = 0; i < pulsingCount; i++) {
        //保證波紋是個圓形
        CALayer * pulsingLayer = [CALayer layer];
        pulsingLayer.frame = CGRectMake(0, 0, rect.size.width, rect.size.height);
        pulsingLayer.borderColor = [UIColor colorWithRed:54 green:83 blue:254 alpha:1].CGColor;
        pulsingLayer.borderWidth = 1;
        pulsingLayer.cornerRadius = rect.size.height / 2;
        
        //縮放動畫
        CABasicAnimation * scaleAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
        scaleAnimation.fromValue = @0.8;
        scaleAnimation.toValue = @2.4;
        
        //關鍵幀動畫  透明度
        CAKeyframeAnimation * opacityAnimation = [CAKeyframeAnimation animationWithKeyPath:@"opacity"];
        opacityAnimation.values = @[@1, @0.9, @0.8, @0.7, @0.6, @0.5, @0.4, @0.3, @0.2, @0.1, @0];
        opacityAnimation.keyTimes = @[@0, @0.1, @0.2, @0.3, @0.4, @0.5, @0.6, @0.7, @0.8, @0.9, @1];
        
        //動畫執行的速度 默認
        CAMediaTimingFunction * defaultCurve = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionDefault];
        
        CAAnimationGroup * animationGroup = [CAAnimationGroup animation];
        animationGroup.beginTime = CACurrentMediaTime() + (double)i * animationDuration / (double)pulsingCount;
        animationGroup.duration = animationDuration;
        animationGroup.repeatCount = HUGE;
        animationGroup.timingFunction = defaultCurve;//動畫運行的節奏
        animationGroup.animations = @[scaleAnimation, opacityAnimation];
        
        [pulsingLayer addAnimation:animationGroup forKey:nil];
        [animationLayer addSublayer:pulsingLayer];

    }
    
    [self.layer addSublayer:animationLayer];
    
}

    5-2 圓形按鈕

      重繪drawRect方法    

- (void)drawRect:(CGRect)rect {
   
    self.backgroundColor = [UIColor clearColor];
    self.layer.borderWidth = 1;
    self.layer.borderColor = [UIColor whiteColor].CGColor;
    self.layer.cornerRadius = rect.size.width / 2;
    
}

    5-3 點擊去簡書按鈕以後會跳轉到其餘頁面    

[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"http://www.jianshu.com/users/28aed6e79eac/timeline"]];

三 相應的功能模塊

  1 分數管理器

    1-1 使用 NSUserDefaults 本地存儲,對全局變量bestScore進行更新,若currentScore小於bestScore,則bestScore不變,不然,將currentScore的值賦給bestScore 

+ (float)getBestScore{
    
    NSNumber *bestScore = [[NSUserDefaults standardUserDefaults]  objectForKey:BestScoreKey];
    if(bestScore == nil){
        [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithFloat:0.0] forKey:BestScoreKey];
        bestScore = [NSNumber numberWithFloat:0.0];
    }
    
    return bestScore.floatValue;
}

+ (void)updateWithCurrentScore:(float)currentScore{
    
    float bestScore = [self getBestScore];
    bestScore = bestScore < currentScore ? currentScore : bestScore;
    [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithFloat:bestScore] forKey:BestScoreKey];
}

      1-2 在失敗頁面中顯示出來以及在控制檯中輸出   

    _failureView.currentScoreLab.text = [NSString stringWithFormat:@"%.1f",_currentScore];
    _failureView.historyScoreLab.text = [NSString stringWithFormat:@"最佳成績:%.f",[ScoreManager getBestScore]];
    _failureView.tipLab.text = @"再接再勵哦";
    
    NSLog(@"歷史最佳:%.1f",[ScoreManager getBestScore]);
    NSLog(@"當前成績:%.1f",_currentScore);

 

    1-3 使用_currentScore來計算當前點擊正確的按鈕數,即分數,若按鈕的狀態爲勝利,則加一

    if (type == CompleteTypeVictory) {
        _currentScore += 1.0;
        
        [[SoundPlayer shareInstance] changeSound];
        [self updateClickOnTrue];
        [self updateGameSpeed];
        
    }

 

  2 速度控制器    

- (void)updateGameSpeed{
    
    if (_currentScore < 200) {
        _gameSpeed = 2.5 * (1 + _currentScore / 200);
    }else{
        _gameSpeed = 5.0;
    }
    
    [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithFloat:_gameSpeed] forKey:GameSpeedKey];
}

 

  3 音樂播放器

    使用AVAudioPlayer控制播放音樂    

dispatch_queue_t dispatchQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    dispatch_async(dispatchQueue, ^{
            //獲取音樂文件路徑
        NSURL *soundUrl = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"C-%d",i]  ofType:@"wav"]];
        if (!_audioPlayer) {
            _asset = [[AVURLAsset alloc] initWithURL:soundUrl options:nil];
            //實例化音樂播放控件
            _audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:_asset.URL error:nil];
        }
        if (_audioPlayer != nil) {
                
            _audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"C-%d",i] ofType:@"wav"]] error:nil];
            _audioPlayer.delegate = self;
            [_audioPlayer play];
            
            if (i < 213) {
                ++i;
            }else{
                i = 1;
            }

        }else{
            NSLog(@"初始化失敗");
        }
    });

 

四 項目總體都使用的重點

  1 單例模式

    若但願一個類只有一個實例存在,同時可獲得這個特定實例提供的服務入口,那麼能夠使用單例設計模式

      在整個項目中,這個累的對象只能被初始化一次,這種特性能夠用在某些須要全局共享的資源中,好比管理類,引擎類

      UIApplication,NSUserDefaults等都是iOS的系統單例

 

static SoundPlayer *instance;

//單例模式,保證只有一個soundPlayer對象

+ (SoundPlayer *)shareInstance{
    @synchronized(instance) {
        if (!instance) {
            instance = [[SoundPlayer alloc] init];
        }
        return instance;
    }
}

 

 

 

  2 多線程

    iOS中,只有主線程,才能當即刷新UI,若是是經過偵聽異步消息,觸發回調函數,或者調用異步方法,請求刷新UI,都會產生線程阻塞和延遲的問題

     多線程:讓CPU在同一時間內運行兩行以上代碼

     iOS是一個支持多任務的操做系統,所以在編寫iOS的多線程程序時,可分爲兩個部分:傳統的多線程處理方式(NSThread)或者使用GCD派遣隊列(Dispatch Queue)與block塊來分派程序

     GCD提供了3中類型的隊列:main,concurrent,serial

        main隊列:程序代碼默認運行的隊列,iOS會將全部跟可視化組件有關的運行程序放在這個隊列,main隊列必定要使用異步模式,若使用同步模式,會形成app運行程序產生死結

        concurr隊列:有4 種(優先權),高優先權,中優先權,低優先權,背景取得concurrent隊列的進入點後,能夠選擇異步或同步運行

        serial隊列:用戶本身建立的隊列,隊列建立時徐給出惟一識別的名字(字符串型),serial隊列必定是dispatch_sync()

     每一個區塊中程序代碼在各類隊列中運行有兩種方式:同步,異步

        同步:(sync)同一隊列,被設置爲同步模式的線程必定要先運行晚纔回輪到下一個線程運行:dispatch_sync()

        異步:(async)同一隊列全部線程一塊兒執行:dispatch_async()

    dispatch_queue_t dispatchQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
    
    dispatch_async(dispatchQueue, ^{

    
    });                     

  3 weakSelf

     防止block的循環引用 

#define WeakSelf __weak typeof(self) weakSelf = self
相關文章
相關標籤/搜索