카테고리 없음

iOS 프로그래밍 기초 11주차

sw0913 2024. 11. 13. 16:45

09 페이지 이동하기 - 페이지 컨트롤

page를 넘겨주는 컨트롤러 입니다

import UIKit // UIKit 프레임워크를 가져옴

// 이미지 파일 이름을 저장한 배열
var images = [ "01.png", "02.png", "03.png", "04.png", "05.png", "06.png" ] // 사용할 이미지 파일 이름 배열

class ViewController: UIViewController { // ViewController 클래스 정의, UIViewController를 상속
    @IBOutlet var imgView: UIImageView! // UIImageView를 IBOutlet으로 연결하여 이미지 표시
    @IBOutlet var pageControl: UIPageControl! // UIPageControl을 IBOutlet으로 연결하여 페이지 제어

    override func viewDidLoad() { // 뷰가 메모리에 로드된 후 호출되는 메서드
        super.viewDidLoad() // 부모 클래스의 viewDidLoad 호출

        // 페이지 컨트롤의 페이지 수를 이미지 배열의 개수로 설정
        pageControl.numberOfPages = images.count 
        // 현재 페이지를 3으로 설정 (0부터 시작하므로 4번째 페이지)
        pageControl.currentPage = 3 

        // 페이지 인디케이터의 기본 색상 설정
        pageControl.pageIndicatorTintColor = UIColor.blue // 기본 인디케이터 색상: 파란색
        // 현재 페이지 인디케이터의 색상 설정
        pageControl.currentPageIndicatorTintColor = UIColor.brown // 현재 페이지 인디케이터 색상: 갈색

        // imgView에 첫 번째 이미지를 설정
        imgView.image = UIImage(named: images[0]) // "01.png" 이미지 설정
    }

    // 페이지가 변경될 때 호출되는 액션 메서드
    @IBAction func pageChange(_ sender: UIPageControl) { // UIPageControl의 값이 변경될 때 호출
        // 선택된 페이지에 해당하는 이미지를 imgView에 설정
        imgView.image = UIImage(named: images[pageControl.currentPage]) // 현재 페이지의 이미지 설정
    }
}

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

화면 밑에 탭으로 여러개의 화면을 전환 할 수 있는 거이 탭 바 컨트롤러입니다.

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

누르면 화면이 이동하고 돌아오는 버튼을 누르면 다시 돌아오는 것이 네비게이션 컨트롤러 입니다

12 테이블 뷰 컨트롤러 이용해 할 일 목록 만들기

//
//  TableViewController.swift
//  Table
//
//  Created by BeomGeun Lee on 2021.
//

import UIKit // UIKit 프레임워크를 가져옴

// 항목 목록과 항목 이미지 파일 이름 배열 정의
var items = ["책 구매", "철수와 약속", "스터디 준비하기"] // 표시할 항목들
var itemsImageFile = ["cart.png", "clock.png", "pencil.png"] // 각 항목에 해당하는 이미지 파일 이름

class TableViewController: UITableViewController { // UITableViewController를 상속한 TableViewController 클래스 정의

    @IBOutlet var tvListView: UITableView! // UITableView를 IBOutlet으로 연결하여 테이블 뷰 참조

    override func viewDidLoad() { // 뷰가 메모리에 로드된 후 호출되는 메서드
        super.viewDidLoad() // 부모 클래스의 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() // 테이블 뷰의 데이터를 다시 로드하여 최신 상태로 업데이트
    }


    // MARK: - Table view data source

    override func numberOfSections(in tableView: UITableView) -> Int { // 섹션 수를 반환하는 메서드
        // #warning Incomplete implementation, return the number of sections
        return 1 // 현재 섹션 수는 1로 설정
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { // 섹션 내의 행 수를 반환하는 메서드
        // #warning Incomplete implementation, return the number of rows
        return items.count // items 배열의 개수만큼 행 수를 반환
    }


    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { // 각 셀을 구성하는 메서드
        let cell = tableView.dequeueReusableCell(withIdentifier: "myCell", for: indexPath) // 재사용 가능한 셀을 큐에서 가져옴

        // 셀의 텍스트 레이블에 항목 이름 설정
        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: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { // 셀 편집 커밋 메서드
        if editingStyle == .delete { // 삭제 편집 스타일일 경우
            // 데이터 소스에서 해당 행 삭제
            items.remove(at: (indexPath as NSIndexPath).row) // items 배열에서 항목 삭제
            itemsImageFile.remove(at: (indexPath as NSIndexPath).row) // 항목 이미지 배열에서 이미지 삭제
            tableView.deleteRows(at: [indexPath], with: .fade) // 테이블 뷰에서 행 삭제 애니메이션과 함께 삭제
        } else if editingStyle == .insert { // 삽입 편집 스타일일 경우
            // 새로운 항목을 생성하고 배열에 삽입 후 테이블 뷰에 새 행 추가
        }
    }

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

iOS앱에서 가장 많이 사용하는 컨트롤러

UITableViewController: 목록 형태의 데이터를 표시하는 데 사용됩니다. 데이터의 행을 표시하고, 선택 및 편집 기능을 제공합니다.

UICollectionViewController: 격자 형태의 데이터를 표시하는 데 사용됩니다. 유연한 레이아웃을 지원하며, 다양한 방식으로 아이템을 배치할 수 있습니다.

UINavigationController: 여러 화면 간의 네비게이션을 관리하는 컨트롤러로, 스택 구조를 사용하여 화면 전환을 처리합니다.

UITabBarController: 여러 개의 뷰 컨트롤러 간에 탭을 통해 전환할 수 있도록 하는 컨트롤러입니다.

이 외에도 특정 기능에 따라 다양한 컨트롤러들이 사용되지만, 기본적으로 UIViewController를 중심으로 다른 컨트롤러들이 구성됩니다.

13 음악 재생하고 녹음하기

//
//  ViewController.swift
//  Audio
//
//  Created by BeomGeun Lee on 2021.
//

import UIKit // UIKit 프레임워크를 가져옴
import AVFoundation // 오디오 재생 및 녹음을 위한 AVFoundation 프레임워크를 가져옴

class ViewController: UIViewController, AVAudioPlayerDelegate, AVAudioRecorderDelegate { // UIViewController를 상속하고 AVAudioPlayerDelegate 및 AVAudioRecorderDelegate 프로토콜을 채택

    var audioPlayer: AVAudioPlayer! // 오디오 재생을 위한 AVAudioPlayer 인스턴스
    var audioFile: URL! // 오디오 파일의 URL

    let MAX_VOLUME: Float = 10.0 // 최대 볼륨 상수

    var progressTimer: Timer! // 재생 상태 업데이트를 위한 타이머

    // 타이머 업데이트 메서드를 위한 선택자
    let timePlayerSelector: Selector = #selector(ViewController.updatePlayTime)
    let timeRecordSelector: Selector = #selector(ViewController.updateRecordTime)

    // UI 요소 IBOutlet 연결
    @IBOutlet var pvProgressPlay: UIProgressView! // 재생 진행 상태를 표시하는 UIProgressView
    @IBOutlet var lblCurrentTime: UILabel! // 현재 재생 시간을 표시하는 UILabel
    @IBOutlet var lblEndTime: UILabel! // 오디오의 총 시간을 표시하는 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! // 녹음 시간을 표시하는 UILabel

    var audioRecorder: AVAudioRecorder! // 오디오 녹음을 위한 AVAudioRecorder 인스턴스
    var isRecordMode = false // 녹음 모드 여부를 나타내는 플래그

    override func viewDidLoad() { // 뷰가 로드된 후 호출되는 메서드
        super.viewDidLoad() // 부모 클래스의 viewDidLoad 호출
        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") // 번들에서 오디오 파일 URL 가져오기
        } else { // 녹음 모드일 경우
            let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] // 문서 디렉토리 경로 가져오기
            audioFile = documentDirectory.appendingPathComponent("recordFile.m4a") // 녹음 파일 URL 설정
        }
    }

    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) // AVAudioRecorder 인스턴스 생성
        } catch let error as NSError {
            print("Error-initRecord: \(error)") // 오류 발생 시 출력
        }

        audioRecorder.delegate = self // 델리게이트 설정
        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 AVAudioSession.sharedInstance().setCategory(.playAndRecord, mode: .default) // 세션 카테고리 설정
            try AVAudioSession.sharedInstance().setActive(true) // 세션 활성화
        } 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) // AVAudioPlayer 인스턴스 생성
        } 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) // 플레이 버튼 상태 설정
    }

    func setPlayButtons(_ play: Bool, pause: Bool, stop: Bool) { // 버튼 상태 설정 메서드
        btnPlay.isEnabled = play // 재생 버튼 상태 설정
        btnPause.isEnabled = pause // 일시 정지 버튼 상태 설정
        btnStop.isEnabled = stop // 정지 버튼 상태 설정
    }

    func convertNSTimeInterval2String(_ time: TimeInterval) -> String { // NSTimeInterval을 문자열로 변환하는 메서드
        let min = Int(time / 60) // 분 계산
        let sec = Int(time.truncatingRemainder(dividingBy: 60)) // 초 계산
        let strTime = String(format: "%02d:%02d", min, sec) // 형식 지정 문자열 생성
        return strTime // 변환된 문자열 반환
    }

    @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) { // 오디오 재생 완료 시 호출

14 비디오 재생 앱 만들기

//
//  ViewController.swift
//  MoviePlayer
//
//  Created by Ho-Jeong Song on 2021/11/26.
//

import UIKit
import AVKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }

    @IBAction func btnPlayInternalMovie(_ sender: UIButton) {
        // 내부 파일 mp4
        let filePath:String? = Bundle.main.path(forResource: "FastTyping", ofType: "mp4")
        let url = NSURL(fileURLWithPath: filePath!)

        playVideo(url: url)
    }

    @IBAction func btnPlayerExternalMovie(_ sender: UIButton) {
        // 외부 파일 mp4
        let url = NSURL(string: "https://dl.dropboxusercontent.com/s/e38auz050w2mvud/Fireworks.mp4")!

        playVideo(url: url)
    }

    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()
        }
    }
}

한가지는 외부에 있는 동영상을 가져오는 것이고 다른 하나는 내부에 있는 동영상을 가지고 오는 것 입니다

 

15 카메라와 포토 라이브러리에서 미디어 가져오기

 

 

 

 

 

BMI 앱 만들어보기 

https://apps.apple.com/kr/app/bmi-%EA%B3%84%EC%82%B0%EA%B8%B0-%EC%B2%B4%EC%A7%88%EB%9F%89%EC%A7%80%EC%88%98-%EA%B3%84%EC%82%B0%EA%B8%B0-%EB%AC%B4%EA%B2%8C-%EC%9D%BC%EA%B8%B0/id1572432663

 

‎BMI 계산기 - 체질량지수 계산기 & 무게 일기

‎이 무료 BMI 계산기를 사용하면 나이, 성별, 키, 체중을 입력하여 간편하게 자신의 BMI(체질량 지수)를 계산할 수 있습니다. WHO BMI 분류 방식에 근거하여 설계되었으며, 미터법 및 야드파운드법

apps.apple.com

기존 BMI 앱들을 벤치마킹


BMI 앱 기획서
1. 앱 개요
앱 이름: BMI Calculator (가칭)
목표: 사용자가 자신의 체질량지수(BMI)를 쉽게 계산하고, 건강한 체중 범위를 이해하며, 맞춤형 건강 정보를 제공하는 앱.
2. 주요 기능
2.1 BMI 계산기
사용자 입력: 키(㎝), 체중(㎏) 입력
BMI 계산: BMI = 체중(kg) / (키(m) * 키(m))
결과 표시: 계산된 BMI 값과 함께 체중 범주(저체중, 정상, 과체중, 비만) 표시
2.2 건강 정보 제공
BMI 범주 설명: 각 BMI 범주에 대한 설명과 건강 위험 요소 안내
체중 목표 설정: 사용자가 목표 체중을 설정할 수 있도록 지원하고, 목표 달성을 위한 권장 체중 조절 방법 제공
2.3 식단 및 운동 가이드
추천 식단: 각 BMI 범주에 맞는 건강한 식단 예시 제공
운동 추천: 체중 감량 또는 유지에 도움이 되는 운동 프로그램 제공
2.4 사용자 맞춤형 기능
사용자 프로필: 나이, 성별, 활동 수준 등을 입력하여 개인 맞춤형 BMI 계산 및 건강 정보 제공
진행 상황 추적: 사용자가 체중 변화를 기록하고, 목표 체중에 도달하는 과정을 시각적으로 보여주는 그래프 제공
2.5 알림 기능
목표 체중 달성을 위한 알림: 주기적인 알림 설정 기능 제공
운동 및 식사 알림: 사용자가 설정한 시간에 운동 또는 식사 알림 전송
3. 디자인
3.1 UI/UX
심플하고 직관적인 인터페이스: 사용자가 쉽게 탐색할 수 있도록 설계
모바일 친화적인 디자인: 다양한 화면 크기에 맞춰 최적화
비주얼 요소: 그래프, 아이콘, 이미지 등을 활용하여 시각적 정보 제공
3.2 색상 및 테마
색상 팔레트: 건강과 관련된 색상(녹색, 파란색) 사용
다크 모드 지원: 사용자 설정에 따라 다크 모드 지원
4. 마케팅 전략
4.1 타겟 사용자
건강 관리에 관심이 있는 성인
체중 조절을 원하는 사용자
운동 및 식단 관리에 관심이 있는 사용자
4.2 홍보 방법
SNS 마케팅: 인스타그램, 페이스북 등 소셜 미디어를 활용하여 사용자 사례 및 건강 정보 공유
블로그 및 유튜브: 건강 관련 블로그 및 유튜브 채널과 협력하여 앱 리뷰 및 사용법 소개
앱스토어 최적화: 키워드 최적화 및 사용자 리뷰 관리
5. 기술 스택
프로그래밍 언어: Swift
프레임워크: UIKit, Core Data (사용자 데이터 저장)
API: 건강 관련 정보 제공을 위한 외부 API 연동 가능성 검토
6. 출시 일정
MVP 개발: 3개월
테스트 및 피드백: 1개월
최종 출시: 4개월 후
7. 예산
개발 비용: 인건비, 서버 비용, 디자인 비용 포함
마케팅 비용: 광고, 프로모션 비용 포함
이 기획서는 기본적인 구조를 제공하며, 필요에 따라 추가적인 세부사항을 조정하거나 추가할 수 있습니다. 사용자 피드백을 통해 지속적으로 개선해 나가는 것이 중요합니다.

 

BMI 계산하는 방법

 

 

UI디자인 -> Outlet 작성 -> Action 기능 작성 -> Connection inspector 로 한번만 연결된 게 맞는지 확인 -> 소스코드 작성

 

과거에는 프로그램 이름이었습니다.

 

IBOutlet과 IBAction이 잘 생성 되었고 한번만 연결 되었는지 꼭 체크.

일반 아이폰 같은 경우는 1x만 써도되지만 iPad나 화면이 커질경우 2x와 3x도 써줘야 해요

해상도 높은 사진을 가져와 사진 크기를 줄여가면서 넣는것이 가장 좋은 방법입니다.

Decimal Pad를 지정해주면 숫자패드만 나옵니다!