功能就是功能,业务就是业务,不能将两者揉在一起,这样可以提高d代码复用率,
举例:
// AudioPlayer.swift
// DropProjectsGame
//
// Created by lin kang on 17/1/29.
// Copyright © 2017年 lin kang. All rights reserved.
//
import UIKit
import AVFoundation
enum GameAudioType{
case backround_one,
backround_two,
backround_three,
backround_four,
collison,
fallingon,
gameOver,
gameWin
func getStateMusicName() -> String! {
switch self {
case .backround_one:
return "backGroundMusic_1.mp3";
case .backround_two:
return "backGroundMusic_2.mp3"
case .backround_three:
return "backGroundMusic_3.mp3"
case .backround_four:
return "backGroundMusic_4.mp3"
case .collison:
return "collision.wav"
case .fallingon:
return "fallingOn.mp3"
case .gameOver:
return "gameOver.wav"
case .gameWin:
return "gameWin.wav"
}
}
}
class AudioPlayer: NSObject,AVAudioPlayerDelegate {
private var audioBackGourndMusicPlayer:AVAudioPlayer!
private var audioInstantMusicPlayer:AVAudioPlayer!
public var instantMusicRrepeateTime:Int = 0;
func playSoundWithSoundType(soundType:GameAudioType ) {
let soundName = soundType.getStateMusicName()
let path = Bundle.main.path(forResource: soundName, ofType: nil)
let url = URL(fileURLWithPath: path!)
do {
if soundType == .backround_one ||
soundType == .backround_two ||
soundType == .backround_three ||
soundType == .backround_four{
let sound = try AVAudioPlayer(contentsOf: url)
sound.delegate = self;
if audioBackGourndMusicPlayer != nil{
audioBackGourndMusicPlayer.stop();
audioBackGourndMusicPlayer = nil;
}
audioBackGourndMusicPlayer = sound
audioBackGourndMusicPlayer.play()
}else{
if audioInstantMusicPlayer == nil{
let sound = try AVAudioPlayer(contentsOf: url)
sound.delegate = self;
audioInstantMusicPlayer = sound
audioInstantMusicPlayer.play()
}
}
} catch{
print("\(soundName) 不能播放!")
}
}
func stopSoundWithSoundType(soundType:GameAudioType) {
if soundType == .backround_one ||
soundType == .backround_two ||
soundType == .backround_three ||
soundType == .backround_four{
if audioBackGourndMusicPlayer != nil{
audioBackGourndMusicPlayer.stop();
audioBackGourndMusicPlayer = nil;
}
}
}
public func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool)
{
if instantMusicRrepeateTime > 0 {
audioInstantMusicPlayer.play()
instantMusicRrepeateTime -= 1;
}else {
audioInstantMusicPlayer = nil;
}
//背景音乐循环播放
if player == audioBackGourndMusicPlayer{
player.play()
}
}
/* if an error occurs while decoding it will be reported to the delegate. */
public func audioPlayerDecodeErrorDidOccur(_ player: AVAudioPlayer, error: Error?)
{}
}
这是我之前的代码,将音乐类型和播放音乐的功能混合在了一起,类型是属于业务的,比如像是collison,fallingon,等,一旦类型变了,那么我的这个接口也就没办法用了。
于是,我单独写了一个和类型无关的音乐播放类,返回AVAudioCustomPlayer的uuid, 继承AVAudioPlayer增加repeat和uuid属性。
再增加一个业务类GameMusicEffectsDatasource 来管理业务逻辑,存储每种类型的音乐uuid.
这样代码逻辑及可读性大大增加了。
//
// AVAudioCustomPlayer.swift
// DropProjectsGame
//
// Created by lin kang on 17/2/3.
// Copyright © 2017年 lin kang. All rights reserved.
//
import UIKit
import AVFoundation
class AVAudioCustomPlayer: AVAudioPlayer {
var audioRepeat:Bool = false
var uuid:String?
}
//
// AudioPlayer.swift
// DropProjectsGame
//
// Created by lin kang on 17/1/29.
// Copyright © 2017年 lin kang. All rights reserved.
//
import UIKit
import AVFoundation
//笔记,将功能和业务分开
//新建数组或字典
class AudioHandler: NSObject,AVAudioPlayerDelegate {
var audioPlayers:[String: AVAudioCustomPlayer] = [String: AVAudioCustomPlayer]()
func playSoundWithSoundType(path:String, kRepeat:Bool) ->String? {
let url = URL(fileURLWithPath: path)
do {
let sound = try AVAudioCustomPlayer(contentsOf: url)
sound.audioRepeat = kRepeat
sound.delegate = self;
sound.play()
let playerKey = String.getUUID()
sound.uuid = playerKey
audioPlayers[playerKey] = sound
return playerKey
} catch{
print("\(path) 不能播放!")
}
return nil
}
func stopSoundWithSoundType(soundID:String) {
let audioPlayer = audioPlayers[soundID]
audioPlayer?.stop();
}
public func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool)
{
let customPlayer:AVAudioCustomPlayer = player as! AVAudioCustomPlayer
//音乐循环播放
if customPlayer.audioRepeat{
player.play()
}else{
player.stop()
audioPlayers.removeValue(forKey:customPlayer.uuid!)
}
}
/* if an error occurs while decoding it will be reported to the delegate. */
public func audioPlayerDecodeErrorDidOccur(_ player: AVAudioPlayer, error: Error?)
{}
}
//
// GameMusicEffectsDatasource.swift
// DropProjectsGame
//
// Created by lin kang on 17/2/3.
// Copyright © 2017年 lin kang. All rights reserved.
//
import UIKit
enum GameAudioType{
case backround_one,
backround_two,
backround_three,
backround_four,
collison,
fallingon,
gameOver,
gameWin
func getStateMusicName() -> String! {
switch self {
case .backround_one:
return "backGroundMusic_1.mp3";
case .backround_two:
return "backGroundMusic_2.mp3"
case .backround_three:
return "backGroundMusic_3.mp3"
case .backround_four:
return "backGroundMusic_4.mp3"
case .collison:
return "collision.wav"
case .fallingon:
return "fallingOn.mp3"
case .gameOver:
return "gameOver.wav"
case .gameWin:
return "gameWin.wav"
}
}
}
class GameMusicEffectsDatasource: NSObject {
let audioHandler:AudioHandler = AudioHandler()
var musicIDs:[String:String] = [String:String]()
func playMusic(musicType:GameAudioType) {
let soundName = musicType.getStateMusicName()
let path = Bundle.main.path(forResource: soundName, ofType: nil)
var kRepeat:Bool = false
if (musicType == .backround_one
|| musicType == .backround_two
|| musicType == .backround_three
|| musicType == .backround_four){
kRepeat = true
}
if (path != nil){
let uuid = audioHandler.playSoundWithSoundType(path: path! as String, kRepeat: kRepeat)
if uuid != nil{
musicIDs[musicType.getStateMusicName()] = uuid
}
}
else{
print("不存在音乐文件\(soundName)")
}
}
func stopMusic(musicType:GameAudioType) {
let uuid = musicIDs[musicType.getStateMusicName()]
audioHandler.stopSoundWithSoundType(soundID: uuid!)
}
}