궁금한 내용을 검색해보세요!
이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.
서근 개발노트
티스토리에 팔로잉
SWIFT/Udemy iOS

[Udemy] 섹션7: Play Sound 및 Bundle - 실로폰 만들기

서근
QUOTE THE DAY

-
Written by SeogunSEOGUN

반응형

 

목표 :  Apple 공식 문서와 stack overflow를 활용해서 AVAudioPlayer를 활용

 

https://github.com/appbrewery/Xylophone-iOS13

 

GitHub - appbrewery/Xylophone-iOS13: Learn to Code While Building Apps - The Complete iOS Development Bootcamp

Learn to Code While Building Apps - The Complete iOS Development Bootcamp - GitHub - appbrewery/Xylophone-iOS13: Learn to Code While Building Apps - The Complete iOS Development Bootcamp

github.com

IBAction 연결

main storyboard의 실로폰 버튼을 ViewController에 하나하나씩 모두 연결하는 것이 아닌 IBAction 함수 안에 모든 버튼을 연결해준다!

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
   
        super.viewDidLoad()
    }
    @IBAction func pressedBtn(_ sender: UIButton) {
        
    }

}

sound play 함수 

소리를 재생할 수 있는 함수를 사용하려면?  AVFoundationimportvar player: AVAudioPlayer! 변수 생성 > 함수 작성

    func playSound(title: String) {
        let url = Bundle.main.url(forResource: title, withExtension: "wav")
        player = try? AVAudioPlayer(contentsOf: url!)
        player.play()
    }

playSound함수의 매개변수 이름을 titleString으로 정해주고, Bundle 안에 있는 wav확장자 파일을 불러온다. 그리고 playerurl을 할당해준 뒤에 playerplay() 한다.

함수 사용

        @IBAction func pressedBtn(_ sender: UIButton) {
            
            playSound(title: sender.currentTitle!)
            
        }

함수를 호출할 때 sender의 정확한 이름인 currentTitle을 옵셔널로 가져와서 버튼의 title명과 wav파일의 이름이 일치할 때 sound가 실행되도록 해준다.

 

조금 더 안전한 함수를 호출하려면 다음과 같이 guard let을 사용할 수 있다.

        @IBAction func pressedBtn(_ sender: UIButton) {
            
            guard let currentSoundTitle = sender.currentTitle else { return }
            playSound(title: currentSoundTitle)
        }

처음 함수와 이 함수는 동일한 코드이다.

Delay 효과 및 Animation

다음 구현해볼것은 버튼을 누르면 해당 버튼이 반투명해지면서 다시 불투명하게 돌아오는 코드를 구현해보려고 한다. 이때 사용해야 할 것이 바로 DelayAnimation이다. 

        @IBAction func pressedBtn(_ sender: UIButton) {
                ...
            
            sender.alpha = 0.5
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
                sender.alpha = 1
            }
        }

코드를 보면 첫 번째로 버튼이 클릭되었을때 senderalpha 값이 0.5로 반투명해지도록 값을 넣어주고 DispatchQueue의 비동기 처리를 사용하여 0.2초 후 senderalpha 값이 다시 1로(불투명) 해지도록 해줬다. 

 

시뮬레이터를 실행해서 확인해보면 다음과 같다.

클릭되는것이 너무 부자연스럽기 때문에 애니메이션 효과를 줘볼까 한다.

                UIView.animate(withDuration: 2) {
                   // some code
                }

위 코드를 DispatchQueue안에 넣어주면 된다.

        @IBAction func pressedBtn(_ sender: UIButton) {
            
            guard let currentSoundTitle = sender.currentTitle else { return }
            playSound(title: currentSoundTitle)
            
            sender.alpha = 0.5
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
                UIView.animate(withDuration: 2) {
                    sender.alpha = 1
                }
            }
        }

코드 리뷰

import UIKit
import AVFoundation // AVFoundation을 import함 (AVAudioPlay 사용 가능)

class ViewController: UIViewController {
    
    // 플레이어 생성. 파일에서 부터 소리를 재생함
    var player: AVAudioPlayer!

    override func viewDidLoad() {
        super.viewDidLoad()
        
    }

    @IBAction func keyPressed(_ sender: UIButton) {
        
        // playSound(songTitle: sender.currentTitle!)  아래와 동일함
        guard let currentSoundTitle = sender.currentTitle else { return }
        playSound(songTitle: currentSoundTitle)
        
        // 버튼 투명도 설정
        sender.alpha = 0.5
        
        // 0.2초의 지연 설정. (애니메이션 효과와 함께 반투명한 색을 투명하게 변경)
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
            UIView.animate(withDuration: 0.5) {
                sender.alpha = 1
            }
        }

    }

    // 번들에 있는 파일을 재생할 수 있는 함수 생성
    func playSound(songTitle: String) {
        let url = Bundle.main.url(forResource: songTitle, withExtension: "wav")
        player = try! AVAudioPlayer(contentsOf: url!)
        player.play()
    }
}

Bundle

디스크 위에 폴더에 리소스를 넣고 스트링이나 url을 써서 접근하는 것

하나의 번들은 실행 코드, 이미지, 사운드, nib 파일, private 프레임워크와 라이브러리, 플러그인, loadable bundles, 기타 다른 코드와 리소스들을 포함할 수 있다.

 

  • 번들 객체 사용방법:
    • 번들 폴더에 번들 객체 생성
    • 위치를 지정하거나 자원을 가져오기 위해 번들 메서드 사용
    • system API 활용하기

 

예를 들어

이미지를 로딩할 때, Assets에 이미지를 저장하고 UIImageNSImageinit(named:) 메서드를 실행시킨다.

 

문자열 자원을 다룰 때, 전체 .strings 파일을 로딩하는 게 아닌 NSLocalizedString 메서드를 사용해 필요한 문자열을 로딩한다.

번들에서 리소스 찾기

NSBundle개체를 사용 하여 번들 내부의 특정 리소스 위치를 얻는다. 자원을 찾을 때 최소한 자원의 이름과 유형을 제공한다. 특정 하위 디렉터리에 있는 리소스의 경우 해당 디렉터리를 지정할 수도 있다. 리소스를 찾은 후 번들 루틴은 파일을 여는 데 사용할 수 있는 경로 문자열 또는 URL을 반환한다.

NSBundle *main = [NSBundle mainBundle];
NSString *resourcePath = [main pathForResource:@"Seagull" ofType:@"jpg"];

탐색 순서

  • Global resources
  • Region-specific localized resources (based on the user’s region preferences)
  • Language-specific localized resources (based on the user’s language preferences)
  • Development language resources (as specified by the CFBundleDevelopmentRegion key in the bundle’s Info.plist file)

TIP
 
 

주의
번들 객체는 항상 대소문자를 고려한다. 대소문자 구분을 염두에 두고 파일 이름을 지정해야 함.

main

현재 실행 파일을 포함하는 번들 객체를 반환

class var main: Bundle { get }

- 앱이 실행 중이면, 앱의 번들 디렉터리에 대한 접근을 제공

let mainBundle = Bundle.main

 - 코드가 프레임워크에서 실행 중이면, 프레임워크의 번들 디렉토리에 대한 접근을 제공한다.

 

클래스를 받아 NSBundle 리턴

let myBundle = Bundle(for: NSClassFromString("MyPrivateClass")!)

문법

Challenge - Function 

//Don't change this code:
func calculator() {
  let a = Int(readLine()!)! //First input
  let b = Int(readLine()!)! //Second input
  
  add(n1: a, n2: b)
  subtract(n1: a, n2: b)
  multiply(n1: a, n2: b)
  divide(n1: a, n2: b)
  
}

//Write your code below this line to make the above function calls work.

func add(n1: Int, n2: Int) {
    print(n1 + n2)
}
func subtract(n1: Int, n2: Int) {
    print(n1 - n2)
}
func multiply(n1: Int, n2: Int) {
    print(n1 * n2)
}
func divide(n1: Int, n2: Int) {
    let value1 = Double(n1)
    let value2 = Double(n2)
    print(value1 / value2)
}

parameters(매개변수), arguments(매개변수 값)

- parameter : 매개변수 이름 ex) songTitle

- argument : 매개변수  ex) String

    func playSound(songTitle: String) {
        let url = Bundle.main.url(forResource: songTitle, withExtension: "wav")
        player = try! AVAudioPlayer(contentsOf: url!)
        player.play()
    }

 


잘못된 내용이 있으면 언제든 피드백 부탁드립니다.


서근


위처럼 이미지 와 함께 댓글을 작성할 수 있습니다.