13장 음악 재생하고 녹음하기







//

//  ViewController.swift

//  Audio

//

//  Created by stayfoolish on 20/10/2018.

//  Copyright © 2018 stayfoolish. All rights reserved.

//


import UIKit

import AVFoundation


class ViewController: UIViewController, AVAudioPlayerDelegate, AVAudioRecorderDelegate {

    

    var audioPlayer: AVAudioPlayer!

    var audioFile: URL!

    var MAX_VOLUME: Float = 10.0

    var progressTimer: Timer!

    

    let timePlayerSelector:Selector = #selector(ViewController.updatePlayTime)

    let timeRecordSelector:Selector = #selector(ViewController.updateRecordTime)


    @IBOutlet var pvProgressPlay: UIProgressView!

    @IBOutlet var lblCurrentTime: UILabel!

    @IBOutlet var lblEndTime: UILabel!

    @IBOutlet var btnPlay: UIButton!

    @IBOutlet var btnPause: UIButton!

    @IBOutlet var btnStop: UIButton!

    @IBOutlet var slVolume: UISlider!

    

    @IBOutlet var btnRecord: UIButton!

    @IBOutlet var lblRecordTime: UILabel!

    

    var audioRecorder: AVAudioRecorder!

    var isRecordMode = false

    

    

    override func viewDidLoad() {

        super.viewDidLoad()

        // Do any additional setup after loading the view, typically from a nib.

       selectAudioFile()

        if !isRecordMode {

            initPlay()

            btnRecord.isEnabled = false

            lblRecordTime.isEnabled = false

        }else {

            initRecord()

        }

        

    }

    

    func selectAudioFile(){

        if !isRecordMode{

             audioFile = Bundle.main.url(forResource: "Sicilian_Breeze", withExtension: "mp3")

        }else {

            let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]

            audioFile = documentDirectory.appendingPathComponent("recordFile.m4a")

        }

    }

    

    func initRecord(){

        let recordSettings = [

            AVFormatIDKey : NSNumber(value: kAudioFormatAppleLossless as UInt32),

            AVEncoderAudioQualityKey : AVAudioQuality.max.rawValue,

            AVEncoderBitRateKey : 320000,

            AVNumberOfChannelsKey : 2,

        AVSampleRateKey: 44100.0] as [String : Any]

        do {

            audioRecorder = try AVAudioRecorder(url: audioFile, settings: recordSettings)

        }catch let error as NSError {

            print("Error-initRecord : \(error)")

        }

        audioRecorder.delegate = self

        audioRecorder.isMeteringEnabled = true

        audioRecorder.prepareToRecord()

        

        slVolume.value = 1.0

        audioPlayer.volume = slVolume.value

        lblEndTime.text = convertNSTimeInterval2String(0)

        lblCurrentTime.text = convertNSTimeInterval2String(0)

        setPlayButtons(false, pause: false, stop: false)

        

        let session = AVAudioSession.sharedInstance()

        do {

            try session.setCategory(AVAudioSessionCategoryPlayAndRecord)

        }catch let error as NSError {

            print(" Error-setCategory : \(error)")

        }

        do {

            try session.setActive(true)

        }catch let error as NSError {

            print(" Error-setActive : \(error)")

        }

    }

    

    func initPlay(){

        do {

            audioPlayer = try AVAudioPlayer(contentsOf: audioFile)

        }catch let error as NSError {

            print("Error-initPlay : \(error)")

        }

        slVolume.maximumValue = MAX_VOLUME

        slVolume.value = 1.0

        pvProgressPlay.progress = 0

        

        audioPlayer.delegate = self

        audioPlayer.prepareToPlay()

        audioPlayer.volume = slVolume.value

        lblEndTime.text = convertNSTimeInterval2String(audioPlayer.duration)

        lblCurrentTime.text = convertNSTimeInterval2String(0)

        setPlayButtons(true, pause: false, stop: false)

/*

        btnPlay.isEnabled = true

        btnPause.isEnabled = false

        btnStop.isEnabled = false

 */

    }

    

    func convertNSTimeInterval2String(_ time:TimeInterval) -> String {

        let min = Int(time/60)

        let sec = Int(time.truncatingRemainder(dividingBy: 60))

        let strTime = String(format: "%02d:%02d", min, sec)

        return strTime

    }

    

    func setPlayButtons(_ play: Bool , pause: Bool, stop: Bool){

        btnPlay.isEnabled = play

        btnPause.isEnabled = pause

        btnStop.isEnabled = stop

    }


    override func didReceiveMemoryWarning() {

        super.didReceiveMemoryWarning()

        // Dispose of any resources that can be recreated.

    }


    @IBAction func btnPlayAudio(_ sender: UIButton) {

        audioPlayer.play()

        setPlayButtons(false, pause: true, stop: true)

        progressTimer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: timePlayerSelector, userInfo: nil, repeats: true)

    }

    

    @objc func updatePlayTime() {

        lblCurrentTime.text = convertNSTimeInterval2String(audioPlayer.currentTime)

        pvProgressPlay.progress = Float(audioPlayer.currentTime/audioPlayer.duration)

    }

    

    @IBAction func btnPauseAudio(_ sender: UIButton){

        audioPlayer.pause()

        setPlayButtons(true, pause: false, stop: true)

    }

    @IBAction func btnStopAudio(_ sender: UIButton){

        audioPlayer.stop()

        audioPlayer.currentTime = 0

        lblCurrentTime.text = convertNSTimeInterval2String(0)

        setPlayButtons(true, pause: false, stop: false)

        progressTimer.invalidate()

        

    }

    @IBAction func slChangeVolume(_ sender: UISlider) {

        audioPlayer.volume = slVolume.value

    }

    

    func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {

        progressTimer.invalidate()

        setPlayButtons(true, pause: false, stop: false)

    }

    @IBAction func swRecordMode(_ sender: UISwitch) {

        if sender.isOn{

            audioPlayer.stop()

            audioPlayer.currentTime = 0

            lblRecordTime!.text = convertNSTimeInterval2String(0)

            isRecordMode = true

            btnRecord.isEnabled = true

            lblRecordTime.isEnabled = true

        }else {

            isRecordMode = false

            btnRecord.isEnabled = false

            lblRecordTime.isEnabled = false

            lblRecordTime.text = convertNSTimeInterval2String(0)

        }

        selectAudioFile()

        if !isRecordMode{

            initPlay()

        }else {

            initRecord()

        }

    }

    @IBAction func btnRecord(_ sender: UIButton) {

        if sender.titleLabel?.text == "Record" {

            audioRecorder.record()

            sender.setTitle("Stop", for: UIControlState())

            progressTimer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: timeRecordSelector, userInfo: nil, repeats: true)

        }else {

            audioRecorder.stop()

            progressTimer.invalidate()

            sender.setTitle("Record", for: UIControlState())

            btnPlay.isEnabled = true

            initPlay()

        }

    }

    @objc func updateRecordTime(){

        lblRecordTime.text = convertNSTimeInterval2String(audioRecorder.currentTime)

    }

}



14장 비디오 재생 앱 만들기




//

//  ViewController.swift

//  MoviePlayer

//

//  Created by stayfoolish on 21/10/2018.

//  Copyright © 2018 stayfoolish. All rights reserved.

//


import UIKit

import AVKit


class ViewController: UIViewController {


    override func viewDidLoad() {

        super.viewDidLoad()

        // Do any additional setup after loading the view, typically from a nib.

    }


    override func didReceiveMemoryWarning() {

        super.didReceiveMemoryWarning()

        // Dispose of any resources that can be recreated.

    }


    @IBAction func btnPlayInternalMovie(_ sender: UIButton) {

        // 내부 파일 mp4

        let filePath: String? = Bundle.main.path(forResource: "FastTyping", ofType: "mp4")

        let url = NSURL(fileURLWithPath: filePath!)

        

        playVideo(url: url)

        /*

        let playerController = AVPlayerViewController()

        

        let player = AVPlayer(url: url as URL)

        playerController.player = player

        

        self.present(playerController, animated: true){

            player.play()

        }

         */

    }

    

    @IBAction func btnPlayExternalMovie(_ sender: UIButton) {

        // 외부 파일 mp4

        let url = NSURL(string: "https://dl.dropboxusercontent.com/s/e38auz050w2mvud/Fireworks.mp4")!

        

        playVideo(url: url)

        /*

        let playerController = AVPlayerViewController()

        

        let player = AVPlayer(url: url as URL)

        playerController.player = player

        

        self.present(playerController, animated: true){

            player.play()

        }

        */

    }

    private func playVideo(url: NSURL) {

        let playerController = AVPlayerViewController()

        

        let player = AVPlayer(url: url as URL)

        playerController.player = player

        

        self.present(playerController, animated: true){

            player.play()

        }

    }

}





//

//  TableViewController.swift

//  Table

//

//  Created by stayfoolish on 19/10/2018.

//  Copyright © 2018 stayfoolish. All rights reserved.

//


import UIKit


// 앱 시작 시 기본적으로 나타낼 목록

var items = ["책 구매","철수와 약속","스터디 준비하기"]

var itemsImageFile = ["cart.png","clock.png","pencil.png"]


class TableViewController: UITableViewController {


    @IBOutlet var tvListView: UITableView!

    

    override func viewDidLoad() {

        super.viewDidLoad()


        // Uncomment the following line to preserve selection between presentations

        // self.clearsSelectionOnViewWillAppear = false


        // Uncomment the following line to display an Edit button in the navigation bar for this view controller.

         self.navigationItem.leftBarButtonItem = self.editButtonItem

    }

    

    // 뷰가 노출될 때마다 리스트의 데이터를 다시 불러옴

    override func viewWillAppear(_ animated: Bool) {

        tvListView.reloadData()

    }

    

    override func didReceiveMemoryWarning() {

        super.didReceiveMemoryWarning()

        // Dispose of any resources that can be recreated.

    }


    // MARK: - Table view data source

    // 테이블 안의 섹션 개수를 1로 설정함

    override func numberOfSections(in tableView: UITableView) -> Int {

        // #warning Incomplete implementation, return the number of sections

        return 1

    }


    // 섹션당 열의 개수를 전달

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        // #warning Incomplete implementation, return the number of rows

        return items.count

    }


    // items와 itemsImageFile의 값을 셀에 삽입함

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let cell = tableView.dequeueReusableCell(withIdentifier: "myCell", for: indexPath)


        // Configure the cell...

        cell.textLabel?.text = items[(indexPath as NSIndexPath).row]

        cell.imageView?.image = UIImage(named: itemsImageFile[(indexPath as NSIndexPath).row])

        

        return cell

    }

    


    /*

    // Override to support conditional editing of the table view.

    override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {

        // Return false if you do not want the specified item to be editable.

        return true

    }

    */


    

    // Override to support editing the table view.

    // 목록 삭제 함수

    override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {

        if editingStyle == .delete {

            // Delete the row from the data source

            // items와 itemsImageFile에서 해당 리스트를 삭제함

            items.remove(at: (indexPath as NSIndexPath).row)

            itemsImageFile.remove(at: (indexPath as NSIndexPath).row)

            tableView.deleteRows(at: [indexPath], with: .fade)

        } else if editingStyle == .insert {

            // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view

        }    

    }

    

    // 삭제 시 "Delete" 대신 "삭제"로 표시

    override func tableView(_ tableView: UITableView, titleForDeleteConfirmationButtonForRowAt indexPath: IndexPath) -> String? {

        return "삭제"

    }

    

    

    // Override to support rearranging the table view.

    // 목록 순서 바꾸기

    override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) {

        

        let itemToMove = items[(fromIndexPath as NSIndexPath).row]

        let itemImageToMove = itemsImageFile[(fromIndexPath as NSIndexPath).row]

        items.remove(at: (fromIndexPath as NSIndexPath).row)

        itemsImageFile.remove(at: (fromIndexPath as NSIndexPath).row)

        items.insert(itemToMove, at: (to as NSIndexPath).row)

        itemsImageFile.insert(itemImageToMove, at: (to as NSIndexPath).row)

    }

    


    /*

    // Override to support conditional rearranging of the table view.

    override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {

        // Return false if you do not want the item to be re-orderable.

        return true

    }

    */


    

    // MARK: - Navigation


    // 세그웨이를 이용하여 디테일 뷰로 전환하기

    // In a storyboard-based application, you will often want to do a little preparation before navigation

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

        // Get the new view controller using segue.destinationViewController.

        // Pass the selected object to the new view controller.

        if segue.identifier == "sgDetail" {

            let cell = sender as! UITableViewCell

            let indexPath = self.tvListView.indexPath(for: cell)

            let detailView = segue.destination as! DetailViewController

            detailView.receiveItem(items[((indexPath as NSIndexPath?)?.row)!])

        }

    }

    


}


//

//  AddViewController.swift

//  Table

//

//  Created by stayfoolish on 19/10/2018.

//  Copyright © 2018 stayfoolish. All rights reserved.

//


import UIKit


class AddViewController: UIViewController {


    @IBOutlet var tfAddItem: UITextField!

    override func viewDidLoad() {

        super.viewDidLoad()


        // Do any additional setup after loading the view.

    }


    override func didReceiveMemoryWarning() {

        super.didReceiveMemoryWarning()

        // Dispose of any resources that can be recreated.

    }

    


    /*

    // MARK: - Navigation


    // In a storyboard-based application, you will often want to do a little preparation before navigation

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

        // Get the new view controller using segue.destinationViewController.

        // Pass the selected object to the new view controller.

    }

    */

    // 새 목록 추가하기

    @IBAction func btnAddItem(_ sender: UIButton) {

        items.append(tfAddItem.text!)

        itemsImageFile.append("clock.png")

        tfAddItem.text=""

        _ = navigationController?.popViewController(animated: true)

    }

    

}


//

//  DetailViewController.swift

//  Table

//

//  Created by stayfoolish on 19/10/2018.

//  Copyright © 2018 stayfoolish. All rights reserved.

//


import UIKit


class DetailViewController: UIViewController {

    

    var receiveItem = ""


    @IBOutlet var lblItem: UILabel!

    

    override func viewDidLoad() {

        super.viewDidLoad()


        // Do any additional setup after loading the view.

        lblItem.text = receiveItem

    }


    override func didReceiveMemoryWarning() {

        super.didReceiveMemoryWarning()

        // Dispose of any resources that can be recreated.

    }

    

    // Main View에서 변수를 받아오기 위한 함수

    func receiveItem(_ item: String){

        receiveItem = item

    }

    


    /*

    // MARK: - Navigation


    // In a storyboard-based application, you will often want to do a little preparation before navigation

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

        // Get the new view controller using segue.destinationViewController.

        // Pass the selected object to the new view controller.

    }

    */


}












10장 탭 바 컨트롤러 이용해 여러 개의 뷰 넣기




//

//  ViewController.swift

//  Tab

//

//  Created by stayfoolish on 18/10/2018.

//  Copyright © 2018 stayfoolish. All rights reserved.

//


import UIKit


class ViewController: UIViewController {


    override func viewDidLoad() {

        super.viewDidLoad()

        // Do any additional setup after loading the view, typically from a nib.

    }


    override func didReceiveMemoryWarning() {

        super.didReceiveMemoryWarning()

        // Dispose of any resources that can be recreated.

    }


    @IBAction func btnMoveImageView(_ sender: UIButton) {

        tabBarController?.selectedIndex = 1

    }

    

    @IBAction func btnMoveDatePickerView(_ sender: UIButton) {

        tabBarController?.selectedIndex = 2

    }

    

}



//

//  ViewController.swift

//  ImageView

//

//  Created by stayfoolish on 16/10/2018.

//  Copyright © 2018 stayfoolish. All rights reserved.

//


import UIKit


class ImageViewController: UIViewController {

    

    var isZoom = false

    var imgOn: UIImage?

    var imgOff: UIImage?


    @IBOutlet var imgView: UIImageView!

    

    @IBOutlet var btnResize: UIButton!

    override func viewDidLoad() {

        super.viewDidLoad()

        // Do any additional setup after loading the view, typically from a nib.

        imgOn = UIImage(named: "lamp_on.png")

        imgOff = UIImage(named: "lamp_off.png")

        

        imgView.image = imgOn

    }


    override func didReceiveMemoryWarning() {

        super.didReceiveMemoryWarning()

        // Dispose of any resources that can be recreated.

    

    }


    @IBAction func btnResizeImage(_ sender: UIButton) {

        let scale:CGFloat = 2.0

        var newWidth:CGFloat, newHeight:CGFloat

        

        if (isZoom) { // true

            newWidth = imgView.frame.width/scale

            newHeight = imgView.frame.height/scale

            imgView.frame.size = CGSize(width: newWidth, height: newHeight)

            btnResize.setTitle("확대", for: .normal)

        }

        else { // flase

            newWidth = imgView.frame.width*scale

            newHeight = imgView.frame.height*scale

            imgView.frame.size = CGSize(width: newWidth, height: newHeight)

            btnResize.setTitle("축소", for: .normal)

        }

        isZoom = !isZoom

    }

    

    @IBAction func switchImageOnOff(_ sender: UISwitch) {

        if sender.isOn {

            imgView.image = imgOn

        }else {

            imgView.image = imgOff

        }

    }

}



//

//  ViewController.swift

//  DatePicker

//

//  Created by stayfoolish on 16/10/2018.

//  Copyright © 2018 stayfoolish. All rights reserved.

//


import UIKit


class DateViewController: UIViewController {

    let timeSelector: Selector = #selector(DateViewController.updateTime)

    let interval = 1.0

    var count = 0

    @IBOutlet var lblCurrentTime: UILabel!

    @IBOutlet var lblPickerTime: UILabel!

    

    override func viewDidLoad() {

        super.viewDidLoad()

        // Do any additional setup after loading the view, typically from a nib.

        

        Timer.scheduledTimer(timeInterval: interval, target: self, selector: timeSelector, userInfo: nil, repeats: true)

    }


    override func didReceiveMemoryWarning() {

        super.didReceiveMemoryWarning()

        // Dispose of any resources that can be recreated.

    }


    @IBAction func changeDatePicker(_ sender: UIDatePicker) {

        let datePickerview = sender

        

        let formatter = DateFormatter()

        formatter.dateFormat = "yyyy-MM-dd HH:mm:ss EEE"

        lblPickerTime.text = "선택시간: " + formatter.string(from: datePickerview.date)

    }

    

    @objc func updateTime() {

//        lblCurrentTime.text = String(count)

//        count = count + 1

        

        let date = NSDate()

        

        let formatter = DateFormatter()

        formatter.dateFormat = "yyyy-MM-dd HH:mm:ss EEE"

        lblCurrentTime.text = "현재시간: " + formatter.string(from: date as Date)

    }

    @IBAction func btnMoveFirst(_ sender: UIButton) {

        tabBarController?.selectedIndex = 0

    }

}




11장 내비게이션 컨트롤러 이용해 화면 전환하기




//

//  ViewController.swift

//  Navigation

//

//  Created by stayfoolish on 18/10/2018.

//  Copyright © 2018 stayfoolish. All rights reserved.

//


import UIKit


class ViewController: UIViewController,EditDelegate {


    let imgOn = UIImage(named: "lamp_on.png")

    let imgOff = UIImage(named: "lamp_off.png")

    

    var isOn = true

    


    @IBOutlet var txMessage: UITextField!

    @IBOutlet var imgView: UIImageView!

    

    override func viewDidLoad() {

        super.viewDidLoad()

        // Do any additional setup after loading the view, typically from a nib.

        imgView.image = imgOn

    }


    override func didReceiveMemoryWarning() {

        super.didReceiveMemoryWarning()

        // Dispose of any resources that can be recreated.

    }


    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

        let editViewController = segue.destination as! EditViewController

        if segue.identifier == "editButton" {

            editViewController.textWayValue = "segue : use button"

        }else if segue.identifier == "editBarButton" {

            editViewController.textWayValue = "segue: use Bar button"

        }

        editViewController.textMessage = txMessage.text!

        editViewController.isOn = isOn

        editViewController.delegate = self

    }

    

    func didMessageEditDone(_ controller: EditViewController, message: String) {

        txMessage.text = message

    }

    

    func didImageOnOffDone(_ controller: EditViewController, isOn: Bool){

        if isOn {

            imgView.image = imgOn

            self.isOn = true

        }else {

            imgView.image = imgOff

            self.isOn = false 

        }

    }

    


}



//

//  EditViewController.swift

//  Navigation

//

//  Created by stayfoolish on 18/10/2018.

//  Copyright © 2018 stayfoolish. All rights reserved.

//


import UIKit


protocol EditDelegate {

    func didMessageEditDone(_ controller: EditViewController, message: String)

    func didImageOnOffDone(_ controller: EditViewController, isOn: Bool)

    

}


class EditViewController: UIViewController {


    

    

    var textWayValue: String = ""

    var textMessage: String = ""

    var delegate: EditDelegate?

    var isOn = false


    @IBOutlet var lblWay: UILabel!

    @IBOutlet var txMessage: UITextField!

    @IBOutlet var swIson: UISwitch!

    

    override func viewDidLoad() {

        super.viewDidLoad()


        // Do any additional setup after loading the view.

        lblWay.text = textWayValue

        txMessage.text = textMessage

        swIson.isOn = isOn

    }


    override func didReceiveMemoryWarning() {

        super.didReceiveMemoryWarning()

        // Dispose of any resources that can be recreated.

    }

    

    @IBAction func btnDone(_ sender: UIButton) {

        if delegate != nil {

            delegate?.didMessageEditDone(self, message: txMessage.text!)

            delegate?.didImageOnOffDone(self, isOn: isOn)

        }

        _ = navigationController?.popViewController(animated: true)

    }

    

    @IBAction func swImageOnOff(_ sender: UISwitch) {

        if sender.isOn {

            isOn = true

        }else {

            isOn = false

        }

    }

    /*

    // MARK: - Navigation


    // In a storyboard-based application, you will often want to do a little preparation before navigation

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

        // Get the new view controller using segue.destinationViewController.

        // Pass the selected object to the new view controller.

    }

    */


}









+ Recent posts