목표 : Apple 공식 문서와 stack overflow를 활용해서 AVAudioPlayer를 활용
https://github.com/appbrewery/Xylophone-iOS13
IBAction 연결
main storyboard
의 실로폰 버튼을 ViewController
에 하나하나씩 모두 연결하는 것이 아닌 IBAction
함수 안에 모든 버튼을 연결해준다!
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func pressedBtn(_ sender: UIButton) {
}
}
sound play 함수
소리를 재생할 수 있는 함수를 사용하려면? AVFoundation
을 import
> var player: AVAudioPlayer
!
변수 생성 > 함수 작성
func playSound(title: String) {
let url = Bundle.main.url(forResource: title, withExtension: "wav")
player = try? AVAudioPlayer(contentsOf: url!)
player.play()
}
playSound
함수의 매개변수 이름을 title
로 String
으로 정해주고, Bundle
안에 있는 wav
확장자 파일을 불러온다. 그리고 player
에 url
을 할당해준 뒤에 player
를 play()
한다.
함수 사용
@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
다음 구현해볼것은 버튼을 누르면 해당 버튼이 반투명해지면서 다시 불투명하게 돌아오는 코드를 구현해보려고 한다. 이때 사용해야 할 것이 바로 Delay
와 Animation
이다.
@IBAction func pressedBtn(_ sender: UIButton) {
...
sender.alpha = 0.5
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
sender.alpha = 1
}
}
코드를 보면 첫 번째로 버튼이 클릭되었을때 sender
의 alpha
값이 0.5로 반투명해지도록 값을 넣어주고 DispatchQueue
의 비동기 처리를 사용하여 0.2초 후 sender
의 alpha
값이 다시 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
에 이미지를 저장하고 UIImage
나 NSImage
의 init(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)
주의
번들 객체는 항상 대소문자를 고려한다. 대소문자 구분을 염두에 두고 파일 이름을 지정해야 함.
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()
}
'SWIFT > Udemy iOS' 카테고리의 다른 글
[Udemy] 섹션9: MVC 패턴, Struct, mutating ( 퀴즈 앱 ) (0) | 2021.08.02 |
---|---|
[Udemy] 섹션8: Egg Timer / ProgressView ( Control Flow and Optionals ) (0) | 2021.07.31 |
[Udemy] 섹션6: Auto Layout and Responsive UIs (오토레이아웃, 반응형 UI) (0) | 2021.07.30 |
[Udemy] 섹션 4: Swift 프로그래밍 - IBOutlet, IBAction (2) | 2021.07.29 |
[Udemy] 섹션 2: Xcode 스토리보드 및 인터페이스 빌더 (0) | 2021.07.29 |