ㅇTL

기본 개념정리 본문

swift

기본 개념정리

정노르레기 2021. 5. 4. 23:08

웅난할수잇당

 

글고 또 정리한거 조금 날라가서 심기불편하다진짜 ㅡㅡ 하

 

 

이름짓기

camelcase (이름짓는 규칙)

lowercamelcase : function, method, variable

UpperCamelCase : type(class, struct ..)

 

콘솔로그

-print = 문자열 출력 용도 print(~)

-dump = 인스턴스의 자세한 설명(description)까지 출력 dump( ~ )

 

문자열 보간법

: 문자열 안에 변수/상수 실질적 값 넣기 위해서 사용. 자동치환 (역슬래시(값)) (\( ))

"저는 \(a) 살 입니다 " 하면 a값이 들어감~

 

또날라감진짜 ㅈㄴ빡친다

 

변수

var 이름: 타입=값

상수

let 이름: 타입=값

 

nil (=value가 없는 상태)

-일반적으로 변수값에 nil 들어가는거 허용x. 컴파일 에러! (옵셔널일때만가능)

 

함수

-기본 선언

func 함수이름(변수이름: 타입, 변수이름: 타입 ...(없으면 걍 가로안 비움)) -> 리턴타입(Void 등등) {

함수 구현

return 값 (void면 return만 쓰거나 암것도 안씀)

}

-호출

함수이름(변수이름: 값, 변수이름: 값)

-매개변수 기본값 설정 -> 매개목록 목록 중 뒤쪽에 위치하는게 굳

func 함수이름(변수이름: 타입, me: String="juny") {

어쩌구

}

 

-전달인자 레이블

-> 함수 호출시 매개변수 역할 더 명확히하거나 함수 사용자의 입장에서 표현하고자할때 사용,

함수의 중복정의도 가능 굳

func 이름(전달인자 이름: 타입)->{} 전달인자는 호출시, 매개변수는 함수 안에서 사용됨.

전달인자는 의미 더 명확하게 하기 위해서 사용

ex

func greeting(to friend: String, from me:String){ (그리팅 to fring까지모두 함수의 이름으로취급->중복정의조음)

print( "\(friend) and \(me)" ) -> 함수 내에선 매개변수 이름을 사용

}

greeting(to: "저니", from: "조니") ->함수 호출시에는 전달인자 레이블 사용해야함!!

-가변 매개변수 -> 몇개 올지모를때사용

func 함수이름(변수이름: 타입 ...) -> 리턴타입 {}

요로캐하면됩니다 마지막변수에 ... 찍으면 여러개받을수잇읍니다 한 함수당 한번입니당

부를 때

함수이름(변수이름: 값,값,값,값) 이런식으로 주면 댑니다

이때 nil넣거나 전달인자 값에 아무것도안넣으면 오류뜸

아무것도안넣고싶으면 걍 변수이름 안쓰면됨

 

-데이터 타입으로서의 함수

함수=객체 !! -> 매개변수를 통해 전달가능!

함수의 타입표현

(매개변수1 타입ㅇ, 매개변수 2 타입 ...)->반환타입

ex1 변수생성

var a: (String, String)->Void = greeting(to:from:)

ex2 함수 매개변수로

func newfunc(function: (Stirng, String)->Int) { ~ }

func(function: greeting(friend:me:))

func(function: a)

 

조건문

1. if-else

*조건에 ( )는 생략 가능, { }는 무조건 써야함

if 조건{ }

else if 조건 { }

else 조건 { }

 

2.switch

*범위연산자가잇다 -> 더 멋들어지게 스위치문사용가능

*정수 외 대부분의 기본 타입 사용 가능

*default 구문 꼭 작성해야댐! 없으면 에러

switch 변수이름{

case 0:

어쩌구

case 1..<100: (=1이상 100미만)

어쩌구

case 101...Int.max: (=...은 이상 이하)

어쩌구

default:

어쩌구

}

*무조건 break 걸림(안써도)

-case "jale", "kefms": 가능

-fallthrough

쓰면 break 안걸리고 다음 애까지넘어간다

 

2. 반복문

for a in array { ~ }

for (a,b) in dictonary { ~ }

-> 튜플 형태로!

while condition (()안쳐도됨.쳐도됨ㅋ) { ~ }

*조건문은 무조건 bool타입으로! 1 or 0 안됨!

 

3.repeat-while

repeat{

~

} while 조건

: 리핏문 돌아간 후에 조건확인한 후 조건이맞으면 다시실행~

 

Optional

= 값이 잇을수도,없을수도잇다!

-optional이 아닌애한테 nil 할당하면 에러뜸

-optional의 가능성을 명시적으로 표현한다! optional이면 nil이 들어갈수잇다 아니면 안된다 요런느낌

-타입? 과 그냥 타입은 다른 타입! =불가 ;;

-표현법

-> Optional<타입> / 타입? (띄어쓰기 ㄴㄴ. 이방법이 훨씬쉽귀 ㅎ)

-값확인 -> switch!

switch a{

case .none:

어쩌구

case .some(let value):

어쩌구 (값은 value 안에~)

}

-타입! = 암시적 추출 옵셔널

-> nil 가능 , 기존 변수처럼 연산 가능 a=a+1 이런거

-타입? = 일반 옵셔널

-> nil 대입 가능, 기존 변수처럼 연산 불가

 

-옵셔널 사용 방법

1. 옵셔널 바인딩 : nil 체크+안전한 값 추출

var myName

if let name(: String 이거안해도되는듯) = myName{

print("\(name)은 \(myName)이다")

->name에는 실제 값 나오고 myName에는 Optional(값) 일케나옴

} else { ~ }

*여러개도 가능

if let name=myName, let friend=yourName{

~ } -> 이건 마이네임 유어네임 둘다 nil 이 아닐때 실행됨

 

2. 옵셔널 강제추출 -> 추천 x

-> 옵셔널변수이름! 하면 그 값이 강제로 추출됨!

-원래는 print(옵셔널 변수) 하면 얘네는 wrap 되어있기때문에

Optional(nil/"dfs"/12) 이런식으로 출력됨. 쌓여잇는그대로 나옴

근데 이걸 벗기는게우리의 목적이니까 강제로벗길수잇도록함

->옵셔널 강제추출! *근데 벗겻을 때 nil이면 오류가 뜨는거임

String? 이엇다면, 그냥 String타입이 되는 것

*nil 이라면 런타임오류발생!

*암시적 옵셔널(! 애초에 이거붙인애) 얘는 애초에 ! 해준거라고생각하면되서

그냥 print(변수이름) 이런식으로해도댐! (!붙일필요x. 안붙여도강제. nil일때만 런타임오류

 

 

<struct>

->대부분의 타입이 구조체로 이루어져잇을정도로 중요하다

-구현

struct 이름 {

변수들

var //가변 프로퍼티

let //불변 프로퍼티

static var a: 타입=100 //타입 프로퍼티

 

func ~ //인스턴스 매서드

 

static func~ //타입 매서드

}

-객체(인스턴스) 생성

var 이름: struct이름=struct( )

- 이름.프로퍼티 이렇게 접근(당연)

-static -> struct타입 자체에서 사용가능하다는것

약간 깊게박혀잇눈 느낌 애초에 구조체꺼

-> struct이름.static애들 이렇게 바로 접근 가능! 다른애들은 객체로 접근해야함 근데 얘는 구조체로 접근!

 

<class>

-다중상속불가

-구현

class 이름{

 ~

}

-type 매소드

1 static func 이름(){} = 상속시 재정의 불가 타입 매서드

2 class func 이름(){} = 상속시 재정의 가능 타입 매서드

 

 

<열거형> 안녕하세용

=연관된 항목을 묶어서 표현할 수 있는 타입. 정의된 항목 값 외에 추가, 수정이 불가

-switch문에서 마니사용

-각각의 케이스가 하나의 타입

-정수값 자동 할당x

enum은 대문자카멜케이스 ,case는 소문자 카멜케이수

-구현enum 이름 {   

case a   

case b   

case c, d, e (한줄로도 표현 가능)}

-case 나타내는 변수var 이름: 열거형이름=열거형이름.case중 하나변수이름= .case중 하나이러캐도 가능~(:열거형이름 이걸하든지 = 열거형이름.case중하나 이걸하든지 한번이라도어떤열거형인지말해주긴해야함아예생략해서 var 변수=.a 이건 안대잉 수정할땐 당연히 ㄱㅊ)

-switch에 case 다 잇음- > default 필요없음

-switch에 case 다 없음 -> default 필수

-원싯값 (정수값 등등 값을 가지도록할수잇는거, 케이스마다 다른값가져야함)

enum 이름: 원싯값 타입{ case a=0 case b case c}-> 자동으로 1씩 증가 (b=1, c=2)-> 값 꺼내기 

열거형이름.case이름.rawValue-->문자열을 원싯값으로한다면case a="hi" case b="D" case c -> +1?? c값 모름 -> rawValue 부르면 그냥 c 나옴(케이스이름 고대로 가져옴_

-rawValue가 정의된 case들은 옵셔널 변수임! (해당 값이 아닐수도잇어서)

->열거형이름(rawValue:0) 하면 값이 0인거 찾는건데, 

열거형이름이 A라고 하면

let a: A=A(rawValue: 0) -> 에러 (0인 애가 없으면 nil이라서 옵셔널변수이기때문)

let a: A?=A(rawValue: 0) 이러캐해야댕 (그럼 wrap에 싸져서나옴)

->바인딩방법해서 하면 apple 이런식으로 케이스나옴

if let a: A=A(rawValue: 0) 

-메소드 추가 가능(함수)

func 이름(){

 switch self { 

  case .mon, .apr:

    print("~")

  case .다른애들..:

    print("~")

..

}}

-> 열거형이름.case이름.함수() -> 저 위에 함수 나옴

 

 

 

<값 타입 / 참조타입>

Class 

-참조타입 (레퍼런스)

-Apple 프레임워크의 대부분 큰 뼈대는 모두 클래스로 구성

-상속가능, 단일상속만!

 

Struct

-상속불가

-다른언어의 구조체보다 다양한 기능을 가짐

-값 타입(벨류)

-Swift의 큰 뼈대는 구조체로 구성

-when 사용? -> 값타입이기때문에 다른 객체또는 함수 등으로 전달될 때 참조가 아닌 복사를 원할 때!/상속필요없을 때

 

Enum

-상속불가

-값타입(벨류)

-열거형 자체가 하나의 데이터 타입,

 열거형의 case 하나하나 전부 하나의 유의미한 값으로 취급 (값넣을수잇돠~)

 

값타입

1. Value : 전달시 단순히 값 복사하여 전달

2. Reference(참조) : 데이터 전달시 값의 메모리 위치를 전달(하나의값을 가리키게됨~)

 

데이터타입 -> 모두 구조체로 구성되어잇다

Apple 프레임워크 -> 대부분 클래스사용한다

 

<클로저 closure>

=코드의 블럭. 일급시민임

-변수, 상수등으로 저장가능, 전달인자로 전달 가능( 당연 )

-함수사용한거랑 똑같이 가능

-함수 = 이름이 있는 클로저임

-정의방법

{ (매개변수 목록) -> 반환타입 in

    실행코드

}

-클로저의 타입 = (매개변수 타입, 타입) -> 반환타입타입

-ex

var sum: (Int, Int) -> Int = { (a: Int, b: Int) -> Int in

    return a+b

}

sum(1,2)

sum=f(a:b:) (sum변수는 클로저 변수 -> 함수는 클로저의 일종 -> sum변수 안에 다른 함수 넣을 수 ㅇ)

 

-func cal(a:Int, b:Int, method: (Int,Int)->Int (클로저임!!) -> Int {

    return method(a,b)

}

-함수의 전달인자 마지막이 클로저면 그거생략하고 그 뒤에 구현가능

cal(a:3, b:4) { (left: Int, right: Int) -> Int in 

    return left+right

}

이렇게 가능하다는 것!

글고 함수정의 후 함수불러서 매개변수 넘겨줄 때

cal(a:3, b:4, method: {(left: Int, right: Int) in 어쩌구 }) 이렇게 리턴타입 안적어줘도 됨 (어짜피 컴파일러가 아니까)

cal(a:3, b:4, method: { ~ return 어쩌구 }) 이렇게 아예 전달 매개변수들이랑 in 안적어줘도 됨)

글고 마지막줄에잇는거 return 키워드도 생략해도됨(어짜피 return 일 테니까

cal(a: 3, b: 4){ e+d } 이렇게까지 축약이 가능! 

 

 

<프로퍼티 property>

: 구조체, 클래스, 열거형 내부에 구현 가능 (멤버애들)

- 그냥 변수들 = 인스턴스 저장 프로퍼티

*구조체는 저장 프로퍼티를 모두 포함하는 이니셜라이저를 자동으로 생성
  하지만 클래스의 저장 프로퍼티는 옵셔널이 아니라면 프로퍼티 기본값을 지정해주거나 사용자정의 이니셜라이저를 통해 반드시 초기화해주어야 함

 

-인스턴스 연산 프로퍼티 = 연산을 해서 값 저장하는 변수

var a: Int {

    get{ return b-1 //이게 a 값이 됨}

    set(inputValue) { b=inputValue+1 } // 입력받은 값이 a가 되고 그 뒤 구문들이 실행됨(b 세팅)

    * set{ b=newValue+1 } //이렇게도 가능. 입력받는거 명시적으로 안써놓으면 받는 변수를 newValue라고써야댐

}

 

-읽기 전용 인스턴스 연산 프로퍼티 = get 만 하는거. 입력안받구 값만 세팅하는거

(매개변수 없고 반환값 없는 함수들 대체)

var selfIntroduce: String{

    get{

        return "저는\(self.class)반 \(name)입니다" }

//class에 self(=this)한건 더 명확히구분되라고한거잉 원래 class머시기가잇으니깐

 

-타입 저장 프로퍼티 = static 변수들

 

*이런 모든 프로퍼티들은, 이런 성질들은 그냥  밖에서, 지역 전역 변수들에서도 사용가능하다

 

-프로퍼티 감시자

= 프로퍼티 값이 변경될 때 원하는 동작을 수행할 수 있음

by willSet (바뀌기직전에실행), didSet(바뀐 후에 실행) 블럭!!

-ex)

var credit: Int = 0 {
willSet {
print("잔액이 \(credit)에서 \(newValue)원으로 변경될 예정입니다.")
}

didSet {
print("잔액이 \(oldValue)에서 \(credit)으로 변경되었습니다.")
}
}

아니면

willSet(a) {
print("잔액이 \(credit)에서 \(a)원으로 변경될 예정입니다.")
}

didSet(b) {
print("잔액이 \(b)에서 \(credit)으로 변경되었습니다.")
}

이렇게 매개변수 넣어서도 가능

*연산 프로퍼티에서는 프로퍼티감시자 사용 불가

->사용어캐되냐면

//잔액이 어쩌구 예정입니다

변수이름.credit=3//잔액이 어쩌구로변경되었습니다

*이 프로퍼티감시자 기능은 함수 메서드 클로저 등 안에서만 되는 게 아니라 외부의 지역,전역 변수에서도 사용 가능

 

<상속>

- 클래스, 프로토콜 등에서 가능

-열거형, 구조체에서 불가

 

클래스 상속

-how?

class 이름: 상속받을 클래스 이름 { ~ 구현 ~ }

-final 키워드(맨앞에)-> 자식 클래스에서 재정의 불가

-static 키워드-> 자식 클래스에서 재정의 불가

-class func ~ -> 자식 클래스에서 재정의 가능한 타입 메서드!

-final class 붙임 = static 붙임

-저장프로퍼티(변수들)은 재정의 불가

-매소드들 재정의하고시픔

-> override 라는 키워드 맨앞에붙임

override func a(){~} 이렇게 (class 붙엿던거는? override class a(){~})

-부모클래스꺼 호출하고싶다 -> super.머시기 요로콤

 

 

<인스턴스(객체) 생성과 소멸>

-클래스같은데에서 저장 프로퍼티(변수들)에는 무조건 초기값 설정해두어야함. =머시기 이렇게 꼭 설정해야댐!!!

 

-초기값(기본값)저장안하고싶으면 ?? -> 이니셜라이저 !!

init(받을 매개변수들) {

 저장 프로퍼티들 값 설정

}

-이니셜라이저 만들떄 여러개만들고, 한 이니셜라이저에서 자기 안에 있는 다른 이니셜라이저를 사용할 수도 잇음

-> 

convenience init(어쩌구){

    self.init(어쩌구)

    어쩌구

} 하면 됨!

convenience 붙여주기~.~

 

 

-초기값이 꼭 필요없는 애/꼭 필요한 프로퍼티는 아님

->저장 프로퍼티(변수)를 옵셔널로 설정! -> 이니셜라이저에서 설정 안해도 됨

 

-인스턴스 사용에 꼭 필요하지만,, 초기값 할당안할때 사용!! (이니셜라이저에 전달어렵거나..등)

 -> 암시적 추출 옵셔널 사용 !! (느낌표 붙이는거)

(나중에 밖에서  클래스변수.해당 변수=머시기 이렇게 값할당할수잇도록)

 

-실패 가능한 이니셜라이저 (=조건잇는 이니셜라이저)

  - 실패하면 nil 반환 (return nil)

  -init? 이렇게 정의(옵셔널)

  - if 어쩌구 {~} if 어쩌구{~} 값 설정 

   이런식으로 조건주는 것

  -이친구를 받는 인스턴스 (변수)는 옵셔널로 꼭 설정해야함! (nil을 받을수도잇으니까)

 

-deinit = 클래스의 인스턴스가 메모리에서 해제되는 시점에 호출됨 !

(클래스에서만잇다)

 *매개변수전달불가)

deinit(){~}

클래스인스턴스(변수) = nil 

이렇게되면 deinit 불림 (메모리에서 해제되므로)

'swift' 카테고리의 다른 글

class  (0) 2021.05.12
함수  (0) 2021.05.12
제어흐름 -> 반복제어 흐름(반복문)/조건부 흐름 제어(if)  (0) 2021.05.12