241009 iOS프로그래밍기초 6주차

2024. 10. 14. 15:45·iOS프로그래밍 (2학년 2학기)

optional binding

  • 옵셔널에 할당된 값을 임시 변수 또는 상수에 할당
if let constantname = optionalName{
//옵셔널 변수가 값이 있다면 언래핑해서 일반 상수 constantname에 대입하고 if문 실행
//값이 없다면 if문의 조건이 거짓이 되어 if문을 실행하지 않음
}
if var variablename = optionalName {
//옵셔널 변수가 값이 있다면 언래핑해서 일반 변수 variblename에 대입하고 if문 실행
//값이 없다면 if문의 조건이 거짓이 되어 if문을 실행하지 않음
}

// 예시 코드 

var x : Int?
x = 10
if let xx = x { print(x,xx) } 
else { print("nil") }
//옵셔널 변수 x가 값(10)이 있으므로 언래핑해서 일반 상수 xx에 대입하고 if문 실행
// 출력 : Optional(10) 10

var x1 : Int?
if let xx = x1 { print(xx) } 
else { print("nil") }
//옵셔널 변수 x1이 값이 없어서 if문의 조건이 거짓이 되어 if문 실행하지 않고 else로 감
// 출력 : nil

var x2 : Int?
x2 = 10
if let x2 { print(x2) } 
else { print("nil") }
// 출력 : 10
// Swift 5.7 부터는 이런식으로 코드를 작성가능.

guard문

  • guard문은 표현식이 거짓(false)로 판단될 경우에 실행 그러므로 꼭 else절 포함해야함
// guard문 예시 코드

guard <불리언 표현식> else {
// 표현식이 거짓일 경우에 실행될 코드
<코드 블록을 빠져 나갈 구문>
}
// 표현식이 참일 경우에 실행되는코드는 이곳에 위치

guard ~ let의 활용

  • guard는 return, break, continue, throw 등 제어문 전환 키워드를 쓸 수 있는 상황이라면
    사용이 가능
  • 그래서 함수 뿐 아니라 반복문 등 특정 블록 내부에 있으면 사용 가능
  • 함수 내부에 있다면 보통 return을 써서 해당 함수를 조기에 빠져나오는 조기 출구
    용도로 사용

실제 앱을 만들다 보면 옵셔널 바인딩 때문에 다중 if~else를 사용해야 하는데, guard~let을
사용하면 다중 루프 없는 훨씬 가독성이 좋은 코드가 가능해서 그런 경우 많이 사용한다.

// 주의 이런 코드와같이 guard문은 사용하지않는다.
var x = 1 
while true { 
guard x < 5 else { break } //조건(x<5)이 거짓일 때 실행(break)
print(x) //1 2 3 4, 조건(x<5)이 참일 때 실행
x = x + 1 
}

guard let ~ else로 옵셔널 바인딩

func multiplyByTen(value: Int?) {
guard let number = value else { //조건식이 거짓(nil)일 때 else 블록 실행
	print("nil") 
	return // 함수 종료
}
print(number*10)
}
// 조건식이 참일 때 실행
// 이유 : 거짓이라면 이미 위에서 함수가 종료됨.
// 주의 : number를 guard문 밖인 여기서도 사용 가능

multiplyByTen(value: 3) //30
multiplyByTen(value: nil) 
multiplyByTen(value: 10) 

특징을 보자면 언래핑된 number 변수를 guard문 밖에 있는 코드가 사용할 수 있다!!
만약 if문을 사용한다면 언래핑된 변수는 그렇게 못함.

if let vs guard let

두개의 코드를 먼저 보여 드리겠습니다.

func printName(firstName:String, lastName:String?){ 
// 외부매개변서 2개인 함수.

// if let
if let lName = lastName { // lastName이 nil이 아닐때
    print(lName,firstName)
}else{ print("성이 없네요!") }

// guard let
guard let lName = lastName else { // lastName이 nil일때
    print("성이 없네요!")
    return // early exit
}
print(lName,firstName)

}// 함수 끝 
printName(firstName:"승현", lastName:"김")
printName(firstName: "승현", lastName:nil)

guard let문을 썼을때 코드가 보기 편함

 

디폴트 매개변수(parameter) 정의하기

  • parameter로 전달하는 값이 없는 경우, 디폴트 매개변수 값을 사용
  • 함수를 선언할 때 매개변수에 디폴트 값을 할당
//이름이 인자로 전달되지 않을 경우에 디폴트로 "길동"이라는 문자열이 사용되도록 함
// 함수 이름 : sayHello(count:name:)
// 반환형 : String
func sayHello(count: Int, name: String = "길동") -> String {
return ("\(name), 너의 번호는 \(count)")
}

// 이름을 가지고 함수를 호출하면 argument를 사용
print(sayHello(count:10, name: "소프트"))
// 출력 : 소프트, 너의 번호는 10

// 이름을 전달하지 않고도 호출 가능하며 디폴트로 "길동"을 사용
print(sayHello(count:100))
// 출력 : 길동, 너의 번호는 100

함수로부터 여러 개의 결과 반환

  • 함수는 여러 결과 값들의 튜플로 감싸서 반환 가능(강점)
// 예시코드
// 함수 이름 : converter(length:)
// 반환형 : tuple
func converter(length: Float) -> (yards: Float, centimeters: Float, meters: Float) {
let yards = length * 0.0277778
let centimeters = length * 2.54
let meters = length * 0.0254
return (yards, centimeters, meters)
}

var lengthTuple = converter(length:10)
// converter함수를 호출해 lengthTuple 변수에 할당. 

print(lengthTuple) // 출력 : (yards: 0.277778, centimeters: 25.4, meters: 0.254)
print(lengthTuple.yards) // 출력 : 0.277778
print(lengthTuple.centimeters) // 출력 : 25.4
print(lengthTuple.meters) // 출력 : 0.254

2개의 정수를 입력받아 가감제 리턴

// 함수 이름 : sss(x:y:)
// 반환형 : tuple
import Foundation
func sss(x : Int, y : Int) -> (sum : Int, sub : Int, div : Double, rmd : Int)
{
  let sum = x + y
  let sub = x - y
  let div = Double(x) / Double(y) //같은 자료형만 연산 가능
  let rmd =  x % y // 나머지 연산
  return (sum, sub, div, rmd)
}
var result = sss(x:10,y:3)
// sss함수를 호출해 result 변수에 할당. 

print(result.sum) // 출력 : 13
print(result.sub) // 출력 : 7
print(result.div) // 출력 : 3.3333333333333335
print(result.rmd) // 출력 : 1

// swift print format으로 구글링하여 소수점 3자리에서 반올림하는 코드
print(String(format: "%.3f", result.div)) // 출력 : 3.333

// 가감승제,나머지까지 나오도록 소스 수정.
// 이 함수의 자료형 : (Int, Int) -> (sum: Int, sub: Int, div: Double)

가변 매개변수

  • 함수가 가변 매개변수를 받는다는 것을 가리키기 위해서 세 개의 점(...) 사용
// 예시코드
func displayStrings(strings: String...)
{
  for string in strings{
  print(string)
  }
}
displayStrings(strings: "일", "이", "삼", "사") 
displayStrings(strings: "one", "two")
// 출력 : 일 이 삼 사 one two (줄 바뀜 생략.)

// 임의의 개수의 정수 값의 합을 출력하는 함수
func add(numbers: Int...)
{
  var total = 0 // 타입 추론
  for num in numbers{
    total = total + num
  }
  print(total)
}
add(numbers:1,2,3) // 출력 : 6
add(numbers:2,2,2,2,2) // 출력 : 10 
add(numbers:1,1,1,1,1,1,1,1,1,1) // 출력 : 10 
add(numbers:1,1,1,1)  // 출력 : 4

inout매개변수 : call by address 구현

  • Swift는 기본적으로 call by value
  • Swift에서 call by address를 구현하는 방법
  • 함수가 값을 반환한 후에도 매개변수에 일어난 변화를 유지하려면, 함수의 선언부에서 매개변수를 입출력 매개변수(in-out parameter)로 선언해야 함
var myValue = 10
// call by address하고 싶은 매개변수의 자료형 앞에 inout 씀
func doubleValue (value: inout Int) -> Int {
  value += value
  return(value)
}
print(myValue) // 출력 : 10
print(doubleValue(value : &myValue)) // 출력 : 20
print(myValue) // 출력 : 20

이제 함수의 마지막으로 BMI 계산 결과 판정하는 프로그램을 다양한 형태로 만들어보겠습니다.

// 평범한 if-else문을 이용한 코드
let weight = 60.0
let height = 170.0
let bmi = weight / (height*height*0.0001) // kg/m*m 
var body = ""
if bmi >= 40 { 
body = "3단계 비만"
} else if bmi >= 30 && bmi < 40 {
body = "2단계 비만"
} else if bmi >= 25 && bmi < 30 {
body = "1단계 비만"
} else if bmi >= 18.5 && bmi < 25 {
body = "정상"
} else {
body = "저체중"
}
print("BMI:\(bmi), 판정:\(body)")
// 츨력 : BMI:20.761245674740483, 판정:정상

// Swift문자열 서식을 이용한 코드
import Foundation
let weight = 60.0
let height = 170.0
let bmi = weight / (height*height*0.0001) // kg/m*m 
let shortenedBmi = String(format: "%.1f", bmi) // 소수점 1자리까지 출력
var body = ""
if bmi >= 40 { 
body = "3단계 비만"
} else if bmi >= 30 && bmi < 40 {
body = "2단계 비만"
} else if bmi >= 25 && bmi < 30 {
body = "1단계 비만"
} else if bmi >= 18.5 && bmi < 25 {
body = "정상"
} else {
body = "저체중"
}
print("BMI:\(shortenedBmi), 판정:\(body)")
// 출력 : BMI:20.8, 판정:정상

// BMI를 판정하는 calcBMI()함수 정의
import Foundation
func calcBMI(weight : Double, height : Double) -> String{
    let bmi = weight / (height*height*0.0001) // kg/m*m
    let shortenedBmi = String(format: "%.1f", bmi) // 소수점 1자리 까지 출력
    var body = "" // 타입추론(String)

    if bmi >= 40 { 
    body = "3단계 비만"
    } else if bmi >= 30 && bmi < 40 {
    body = "2단계 비만"
    } else if bmi >= 25 && bmi < 30 {
    body = "1단계 비만"
    } else if bmi >= 18.5 && bmi < 25 {
    body = "정상"
    } else {
    body = "저체중"
    }
    return "BMI : \(shortenedBmi), 판정 : \(body)"
}
print(calcBMI(weight:82, height: 179.8))
// 출력 : BMI : 25.4, 판정 : 1단계 비만

// switch~case를 이용한 코드
import Foundation
func calcBMI (weight : Double, height : Double) { // Void형(없다는 뜻)
let bmi = weight / (height*height*0.0001) // kg/m*m 
let shortenedBmi = String(format: "%.1f", bmi) // 소수점 1자리까지 표현
switch bmi {
	// 범위 연산자 사용
    case 0.0..<18.5: // 0.0 ~ 18.5 미만
    print("BMI:\(shortenedBmi),판정:저체중")
    case 18.5..<25.0 : // 18.5 ~ 25.0 미만
    print("BMI:\(shortenedBmi),판정:정상")
    case 25.0..<30.0 : // 25.0 ~ 30.0 미만
    print("BMI:\(shortenedBmi),판정:1단계 비만")
    case 30.0..<40.0 : // 30.0 ~ 40.0 미만
    print("BMI:\(shortenedBmi),판정:2단계 비만")
    default : // 위의 조건이 아무것도 아닐때 
    print("BMI:\(shortenedBmi),판정:3단계 비만") 
    }
}
calcBMI(weight:62.5, height: 172.3)
// 출력 : BMI:21.1,판정:정상

// switch~case + 판정 결과 리턴하는 함수
import Foundation
func calcBMI(weight : Double, height : Double) -> String {
    let bmi = weight / (height*height*0.0001) // kg/m*m
    let shortenedBmi = String(format: "%.1f", bmi) 
    var body = ""
    switch bmi {
        case 0.0..<18.5:
        body = "저체중"
        case 18.5..<25.0:
        body = "정상"
        case 25.0..<30.0:
        body = "1단계 비만"
        case 30.0..<40.0 :
        body = "2단계 비만"
        default :
        body = "3단계 비만"
        }
    return "BMI:\(shortenedBmi), 판정:\(body)"
}
print(calcBMI(weight:60.0, height: 170.0))
// 출력 : BMI:20.8, 판정:정상
// 이 코드가 보기 편하고 제일 간결함

강의 2번째 프린트문 17:31

1급 객체 1급 시민

다음 조건을 충족하는 객체를 1급 객체라고 한다.

  • 변수에 저장할 수 있다.
    Swift는 함수를 데이터 타입처럼 처리할 수 있음
    함수를 상수 또는 변수에 할당하는 것이 가능
    함수를 호출하려면 원래의 함수 이름 대신에 상수 이름을 이용하여 호출 가능
    func inchesToFeet (inches: Float) -> Float {
    return inches * 0.0833333
    }
    let toFeet = inchesToFeet //함수를 자료형처럼 사용
    print(inchesToFeet(inches:10))
    print(toFeet(10)) //주의 : argument label인 (inches:) 안 씀
  • 매개변수로 전달할 수 있다.
    // Int와 Double형을 매개변수로 받아서 String을 반환하는 함수의 데이터 타입
	// (Int, Double) -> String // (매개변수형, 매개변수형) -> 리턴형
    // 매개변수로 함수를 받으려면, 함수를 받게 될 함수는 함수의 데이터 타입을 선언함
	func outputConversion(converterFunc: (Float) -> Float, value: Float) {//함수를 매개변수로 사용
	let result = converterFunc(value) //toFeet(10)
	print("Result = \(result)")
	}
	outputConversion(converterFunc:toFeet, value: 10) // 피트로 변환는inchesToFeet함수 호출
  • 리턴값으로 사용할 수 있다.
func inchesToFeet (inches: Float) -> Float {
return inches * 0.0833333
}
func inchesToYards (inches: Float) -> Float {
    return inches * 0.0277778
}
let toFeet = inchesToFeet
let toYards = inchesToYards

//단위를 변환하고 콘솔에 결과를 출력하는 다른 함수
func outputConversion(converterFunc: (Float) -> Float, value: Float) { //함수를 매개변수로 사용
    let result = converterFunc(value)
    print("Result = \(result)")
}
// outputConversion 함수를 호출할 때 선언된 데이터 타입과 일치하는 함수를 전달

// 매개변수로 적절한 변환 함수를 전달하면 인치를 피트 또는 야드로 변환하기 위하여 동일한 함수가 호출될 수 있음



outputConversion(converterFunc: toYards, value: 10) // 야드로 변환하는 inchesToYards함수 호출
outputConversion(converterFunc: toFeet, value: 10) // 피트로 변환하는 inchesToFeet함수 호출

//반환 타입으로 함수의 타입을 선언하면 함수도 반환될 수 있음
//다음 함수는 Boolean 매개변수의 값에 따라 toFeet 함수 또는 toYards 함수를 반환
func decideFunction(feet: Bool) -> (Float) -> Float
{ //매개변수형 리턴형이 함수형
    if feet{
        return toFeet //함수를 리턴
    }else{
        return toYards
    }
}

함수 : 일급 객체 길습

func up(num: Int) -> Int {
return num + 1
}
func down(num: Int) -> Int {
return num - 1
}
let toUp = up
print(up(num:10)) // 출력 : 11
print(toUp(10)) // 출력 : 11

let toDown = down

func upDown(Fun: (Int) -> Int, value: Int){
  let result = Fun(value)
  print("결과 = \(result)") // 출력 : 결과 = 11
}
upDown(Fun:toUp, value: 10) //toUp(10), 출력 : 결과 = 11
upDown(Fun:toDown, value: 10) //toDown(10), 출력 : 결과 = 9

func decideFun(x: Bool) -> (Int) -> (Int){ //매개변수형 리턴형이 함수형
    if x {
        return toUp
    } else {
        return toDown
    }
}
let r = decideFun(x:true) // let r = toUp
print(type(of:r)) //(Int) -> Int
print(r(10)) // toUp(10), 출력 : 11

클로저 표현식

특정 작업(함수)과 그 작업이 일어난곳(환경 또는 상태)을 모두 기억하고 있는 도구

  • 클로저 표현식은 독립적인 코드 블록
// 클로저 표현식은 매개변수를 받거나, 값을 반환하도록 만들 수도 있다
// 클로저 표현식 코드
{func <함수명>(<매개변수 이름>: <매개변수 타입>, … ) -> <반환 타입> in
}
두 개의 정수 매개변수를 받아서 정수 결과 값을 반환
let multiply = {(val1: Int, val2: Int) -> Int in
//매개변수 리턴형
return val1 * val2
}
// 여기서 multiply의 자료형은 (Int, Int) -> Int
let result = multiply(10, 20) //상수를 함수처럼 호출,200
func add(x: Int, y: Int) -> Int {
return(x+y)
}
print(add(x:10, y:20))

let add1 = { (x: Int, y: Int) -> Int in
return(x+y)
}

// print(add1(x:10, y:20))
//주의 error: extraneous(관련 없는) argument labels 'x:y:' in call

print(add1(10, 20)) //OK,  출력 : (Int, Int) -> Int
print(type(of:add1)) // 출력 : (Int, Int) -> Int

위의 코드에서 in 키워드는 클로저(closure) 문법의 일부입니다.

 

Swift에서 클로저를 사용할 때 in 키워드는 중요한 역할을 합니다:

  • 목적: in 키워드는 클로저의 매개변수 및 반환 타입 선언부와 실제 클로저 본문을 구분함
  • 위치: in 키워드는 클로저의 매개변수 목록과 반환 타입 선언 다음에 위치
  • 의미: "이 다음에 오는 코드가 클로저의 실제 구현부입니다"라는 의미를 나타냄

 

저작자표시 (새창열림)

'iOS프로그래밍 (2학년 2학기)' 카테고리의 다른 글

241031 iOS프로그래밍기초 9주차  (5) 2024.10.31
241017 iOS프로그래밍기초 7주차  (1) 2024.10.17
241002 iOS프로그래밍기초 5주차  (2) 2024.10.14
240926 iOS프로그래밍기초 4주차  (3) 2024.09.26
240919 iOS 프로그래밍기초 3주차  (0) 2024.09.19
'iOS프로그래밍 (2학년 2학기)' 카테고리의 다른 글
  • 241031 iOS프로그래밍기초 9주차
  • 241017 iOS프로그래밍기초 7주차
  • 241002 iOS프로그래밍기초 5주차
  • 240926 iOS프로그래밍기초 4주차
Z2AE
Z2AE
  • Z2AE
    딩코.log
    Z2AE
  • 전체
    오늘
    어제
    • 분류 전체보기 (67)
      • C++ 프로그래밍 (1학년 2학기) (12)
      • 서버프로그래밍 (1학년 2학기) (0)
      • C# 프로그래밍 (1학년 2학기) (2)
      • 프론트엔드 웹개발 (1학년 2학기) (2)
      • 데이터베이스 (2학년 1학기) (8)
      • 자료구조 (2학년 1학기) (2)
      • JAVA프로그래밍 (2학년 1학기) (7)
      • PHP쇼핑몰실무 (2학년 1학기) (2)
      • 운영체제 (2학년 1학기) (3)
      • 모바일게임개발 (2학년 1학기) (1)
      • iOS프로그래밍 (2학년 2학기) (11)
      • 네트워크보안 (2학년 2학기) (1)
      • iOS프로그래밍실무 (3학년 1학기) (11)
      • 소프트웨어설계 (3학년 1학기) (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
Z2AE
241009 iOS프로그래밍기초 6주차
상단으로

티스토리툴바