(Ctrl+F키로 찾기)
1 콘솔로그,문자열보간법,명명법
var Name: String = "김정환"
let age :Int = 10
class Person{
var Name: String = "김정환"
let age :Int = 10
}
let yagom:Person = Person()
print("저의 나이는\(age+15)입니다.")
print("제 이름은 \(Name)입니다.")
dump(yagom)//인스턴스까지 자세히 보여줌
2 상수,변수
let 상수:Int = 10 //constant
var 변수:Int = 11 //variable
3 기본 데이터 타입(Bool,Int,UInt,Float,Double,Character,String)
var someBool: Bool = true//false
var someInt: Int = -100
var someUInt: UInt = 100//양의정수
var someFloat: Float = 3.14
var someDouble: Double = 3.14195
var someCharacter: Character = "A"
var someString: String = "안녕 Hello world"
4 any,anyObject,nil
var someAny: Any = 100//모든타입을 지칭
class SomeClass{}
var someAnyObject : AnyObject = SomeClass()//모든클래스타입 지칭
var someNil:Any = 100 //nil은 없음을의미=Null과 비슷
5 컬렉션 타입(Array, Dictionary, Set)
5-1.Array
var integers: Array<Int> = Array<Int>()//integers라는 변수명으로 배열을 선언하는데 Int형으로 만들겠다.
//빈 배열선언 Array<Int>()로 선언
integers.append(1)//integers배열에 1이라는 멤버를 추가하겠다. 추가=append 메서드
integers.contains(1)//integers배열에 1이라는 멤버가 있는가? 묻는 메서드 contains, ture/false로 출력
integers.remove(at : 0)//integers배열에 0번 인덱스에 있는 값을 삭제하겠다.
//integers.removeLast()//integers배열에 마지막 인덱스에 있는 값을 삭제하겠다.
//integers.removeFirst()
integers.removeAll()//integers배열에 모든 인덱스에 있는 값을 삭제하겠다.
integers.count//integers배열에 몇개의 인덱스가 들어있는가? 묻는 메서드 count
var doubles: Array<Double> = [Double]()//배열 축약선언, <>와[]는 같은표현이다.
var characters: [Character] = []//더 축약해서 빈 Array 생성가능
let immutableArray = [1,2,3]//let키워드로 변경불가능한 배열선언가능
5-2.딕셔너리
var anyDictionary: Dictionary<String, Any> = [String:Any]()//딕셔너리 선언식 <키 의타입,값 의타입>
anyDictionary["somekey"] = "dictionary"//딕셔너리 키와 값 지정가능 -> 키는string 값은any=모든타입다됌
anyDictionary["anotherkey"] = 100
anyDictionary.removeValue(forKey: "somekey")//딕셔너리 값 삭제(키 호출)
anyDictionary["somekey"] = nil//somekey에 있는 값을 지우고싶다. nil=null비슷한 의미 ,removeValue와 비슷한의미
5-3.Set
var integerSet: Set<Int> = Set<Int>()//Set선언. 축약문법없음
integerSet.insert(1)//insert라는 메서드로 값 추가가능
integerSet.insert(2)
integerSet.insert(3)
integerSet.insert(3)
integerSet//3을 추가해도 중복추가가 되지않는다
let setA: Set<Int> = [1,2,3,4,5]
let setB: Set<Int> = [3,4,5,6,7]
let union: Set<Int> = setA.union(setB)//상수union에 A,B합집합을 대입하겠다.
//합집합=intersection, 차집합=subtracting 메서드
let sortedUnion:[Int] = union.sorted()//상수union을 오름차순 정렬시키기
6.함수기본
//func 함수이름 (매개변수1이름: 매개변수타입1, 매개변수2이름: 매개변수타입2) -> 반환타입{함수 구현부 return 반환값}//함수형태
func sum( a : Int, b : Int) -> Int{
return a+b
}
func MyName(Name:String)->Void{//"반환값"이 없는 함수선언 Void, 반환타입,매개변수를 생략도가능 "->Void","(Name:String)"생략!
print(Name)
}
sum(a: 3, b: 5)//함수 호출
func greeting(friend: String, me:String = "yagom"){//기본값을 갖는 함수 기본값:yagom
print("Hello\(friend), I'm\(me)")
}
func greeting(to friend:String, from me:String){}//전달인자 레이블 to,from사용
greeting(to:"ahaha", from:"yagom")//to,from 레이블사용 함수는 사용시에도 레이블에 매개변수값 넣어줌
func sayHello(me:String, friend:String...) -> String {//가변매개변수는 뒤에 ... 붙임 -> 전달받을값의 갯수를 모를때 사용
return "Hello\(friend)! I'm\(me)!"//대신 함수당 하나의 가변매개 변수만을 가질 수 있다.(특징중요)
}
print(sayHello(me: "yagom", friend: "haha","hoho","huhu"))//가변매개변수 사용하면 전달인자 갯수 여러개 전달 가능
var someFunction: (String, String) -> Void = greeting(to:from:)//변수안 함수 할당
someFunction("eric","yagom")//함수가 있는 변수기 때문에 이런식으로 할당가능하고 변수안에 포함된 함수가 실행됨
7.조건문
var kome = 1
if kome < 3 {//조건문if는 c언어와 유사하고 ()생략가능 하다는 것만 알자, 조건문엔 bool타입만 가능 1,0이런거 안됨
print("3미만")
}
else if kome > 2 {
print("2초과")
}
else{}
switch kome{
case 0 : print("0")
case 1..<100 : print("1~99")//범위연산자..< 를 쓰면 1이상 100미만
case 100 : print("100")
case 101...Int.max : print("over100")//범위연산자...을 쓰면 100이상
default:print("unknown")//꼭 디폴트구간 필수로 써야함
}
8.반복문
var integers2 = [1,2,3,]
let people = ["yagom":10, "eric":15, "mike":12]
for integers in integers2 {print(integers)}//for each 구문과 비슷함
while integers.count > 1 {integers.removeLast()}//while구문, 조건문의괄호 생략가능
repeat{integers2.removeLast()} while integers2.count > 0//repeat구문, do while과 비슷
9.옵셔널 : 값이 있을수도,없을수도있다 - nil의 할당유무
//옵셔널 바인딩 : 옵셔널의 값을 안전하고 nil체크를 할수 있게 추출한 방법-if let 구문으로 사용가능
let optionalValue: Optional<Int> = nil//옵셔널 선언 정석
var myName2: String? = "yagom"//옵셔널 선언 생략버전 ?표붙이기
var yourName: String? = "haha"//!는 암시적추출옵셔널형식 : nil할당, 기존변수처럼 사용가능
switch optionalValue {
case .none:print("This Optional variable is nil")
case .some(let value):print("Value is \(value)")
}
if let name = myName2, let friend = yourName{//yourName의 값이 nil이면 실행x
print("\(name) and \(friend)")
}
//옵셔널 강제추출
func printName(_ name: String){
print(name)
}
var myName: String? = "yagom"
printName(myName!)//yagom
//만약 강제추출시 값이 없으면(nil) 런타임오류 일어남
10.구조체
struct Sample {//구조체선언
var mutable: Int = 100//타입안에 들어있는 변수,상수를 프로퍼티라하고 가변프로퍼티,불변프로퍼티 선언
let immutable: Int = 100
func instanceMethod(){//타입안에 들어있는 함수를 메서드라하고 선언
print("Method instance")
}
static var typeProperty: Int = 100//구조체 내에서만 사용할수 있는 타입을 선언한것, static키워드로 선언
}//static으로 선언한 변수를 타입프로퍼티라고함 함수는 타입메서드
var mutable: Sample = Sample()//구조체사용, Sample이라는 타입이된것
mutable.mutable = 200//가변프로퍼티는 구조체안 값변경가능
11.클래스
class Sample2 {//구조체선언
var mutable2: Int = 100//타입안에 들어있는 변수,상수를 프로퍼티라하고 가변프로퍼티,불변프로퍼티 선언
let immutable2: Int = 100
func instanceMethod2(){//타입안에 들어있는 함수를 메서드라하고 선언
print("Method instance")//함수 종류2가지(재정의가능,불가능클래스)static func 와 class func로 선언
}
static var typeProperty2: Int = 100//클래스 내에서만 사용할수 있는 타입을 선언한것, static키워드로 선언
}
var mutableReference: Sample2 = Sample2()
mutableReference.mutable2 = 200//클래스사용
var immutableReference: Sample2 = Sample2()
//immutableReference.immutable2 = 200//불변프로퍼티는 값수정불가능,하지만 가변프로퍼티는 let으로 설정해도 값변경가능하다.
//클래스는 값전달타입, 구조체는참조타입-값이있는장소에참조함(값이동x)
12.열거형
enum Weekday{
case mon//각각의케이스는 그자체가 고유의값이고 할당돼는것이아님
}
var day = Weekday.mon
enum Fruit: Int {
case apple = 0//raw value 원시값 넣어줄수있음, 각각다른값가져야함
}
print("\(Fruit.apple.rawValue)")//원시값 꺼내오기 가능
enum Month{
case mar
func printMessage(){//swift 열거형은 안에 함수도 선언가능
switch self{
case.mar: print("더움")
}
}
}
Month.mar.printMessage()//열거형 함수값 꺼내쓰기
13.클로저 : 코드의블럭,일급시민, 함수는 클로저의 일종, 변수상수등으로 저장,전달인자전달가능
var result: Int
func sumFuntion(a:Int, b:Int) -> Int{//함수의선언
return a+b
}
var sum: (Int, Int) -> Int = {(a:Int, b:Int) -> Int in//클로저선언
return a + b
}
var sumResult : Int = sumFuntion(a: 1, b: 2)
sumResult = sum(1,2)
print(sumResult)//클로저 사용2
let add: (Int, Int) -> Int//클로저를 사용한 덧셈연산을 하는 알고리즘 만들기
add = {(a:Int, b:Int) -> Int in
return a+b
}
func calculate(a: Int, b:Int, method: (Int,Int) -> Int) -> Int{
return method(a,b)
}
var calculated:Int
calculated = calculate(a:50, b:10, method: add)
print(calculated)//60나옴
result = calculate(a: 10, b: 10){(left: Int, right: Int) -> Int in//후행클로저-마지막 매개변수이름생략가능,클로저가 함수의 마지막전달인자일경우
return left+right
}//반환타입도 생략가능, 후행클로저와 함께사용가능, 단축인자이름활용(생략)-매개변수 이름 불필요시 사용가능
result = calculate(a:10,b:10){$0+$1}
print(result)//20
14.프로퍼티고급 종류: 저장,연산,인스턴스,타입프로퍼티 -> 지역변수 전역변수 모두가능
struct Student{
//인스턴스 저장 프로퍼티
var name: String = ""
var clas: String = "Swift"
var koreanAge: Int = 0
//인스턴스 연산 프로퍼티
var westernAge: Int {
get{
return koreanAge - 1
}
set(inputValue){
koreanAge = inputValue + 1//이렇게 해주면 연산을해서 할당을 해줌 raw value
}
}
//타입 저장 프로퍼티
static var typeDescription: String = "학생"
//읽기 전용 연산 프로퍼티 - get 생략가능
static var selfIntroduction: String {
get{
return "학생타입입니다"
}
}
}
var yagom2: Student = Student()
yagom2.koreanAge = 10
print("한국나이\(yagom2.koreanAge), 미국나이\(yagom2.westernAge)")//이렇게 연산 프로퍼티사용
struct Money{//프로퍼티 감시자 사용
var currencyRate: Double = 1100{
willSet(newRate){//바뀔값
print("환율이\(currencyRate)에서 \(newRate)으로 변경될 예정입니다.")
}
didSet(oldRate){//바뀐값
print("환율이\(oldRate)에서 \(currencyRate)으로 바뀝니다.")
}
}
}
15.상속
//특징 : 1.클래스,프로토콜에서 사용가능, 2.열거형구조체는 상속불가능, 3.스위프트는 다중상속불가(단일상속)
class Person3 {//선언법 = class 클래스이름: 상속받을 클래스이름{구현부}
var name3:String = ""
func selfIntroduce(){
print("저는\(name3)입니다.")
}
final func sayHello(){//자식클래스로 물려줫을때 재정의를 방지하도록final키워드로 예방 = 오버라이드 할수없도록함
print("hi")
}
static func typeMethod(){//자식클래스 갔을때 재정의 물가능하도록함(final class랑같음=static)
print("type method - static")
}
class func classMethod(){//재정의 가능 타입 메서드
print("type method - class")
}
}
class Student3: Person3 {//Person3클래스를 student3클래스가 상속받음, 안에서 재정의불가=오버라이드
var major: String = ""
override func selfIntroduce() {//원래 Person3클래스에서 있었던 함수를 재정의하고싶을때 override키워드로 재정의하면 덮어쓰기기됨
print("덮어쓰기")//근데 static으로 정의했던 메서드는 override로 재정의불가
}
//super.selfIntroduce() 부모클래스에있는 메서드를 호출가능 super키워드로
}
let yagom3: Person3 = Person3()//상속 사용법
let hana: Student3 = Student3()
yagom3.name3 = "yaya"
hana.name3 = "heeheehee"
hana.major = "wee"
yagom3.selfIntroduce()//상속 사용법2
16.이니셜라이저
class PersonB{
var name:String
var age:Int
var nickName:String
init(name:String, age:Int, nickName:String){//이니셜라이저 를통해 초기값 선언
self.name = name
self.age = age
self.nickName = nickName
}
}//클래스를 선언과 동시에 초기화 완료
class PersonC {
var name: String
var age: Int
var nickName: String?
init(name: String, age: Int, nickName: String) {
self.name = name
self.age = age
self.nickName = nickName
}
// 위와 동일한 기능 수행
// convenience init(name: String, age: Int, nickName: String) {
// init(name: name, age: age)
// self.nickName = nickName
}
class PersonD {//인스턴스 생성 실패시 nil을 반환하는 클래스
var name: String
var age: Int
var nickName: String?
init?(name: String, age: Int) {
if (0...120).contains(age) == false {
return nil
}
if name.count == 0 {
return nil
}
self.name = name
self.age = age
}
}
class Puppy {
var name: String
var owner: PersonC!
init(name: String) {
self.name = name
}
}
class PersonE {
var name: String
var pet: Puppy?
var child: PersonC
init(name: String, child: PersonC) {
self.name = name
self.child = child
}
// 인스턴스가 메모리에서 해제되는 시점에 자동 호출
deinit {
if let petName = pet?.name {
print("\(name)가 \(child.name)에게 \(petName)를 인도합니다")
self.pet?.owner = child
}
}
}
17.옵셔널 체이닝, nil병합
//구조체,클래스안에 구조체나클래스를 계속 선언할때가 있는데 프로퍼티가 옵셔널이라면 nil인지 아닌지 계속확인해야할때 옵셔널체이닝으로 확인하는용도
class Person4 {
var name: String
var job: String?
var home: Apartment?
init(name: String) {
self.name = name
}
}
// 사람이 사는 집 클래스
class Apartment {
var buildingNumber: String
var roomNumber: String
var `guard`: Person4?
var owner: Person4?
init(dong: String, ho: String) {
buildingNumber = dong
roomNumber = ho
}
}
// 옵셔널 체이닝 사용
let yagom4: Person4? = Person4(name: "yagom")
let apart: Apartment? = Apartment(dong: "101", ho: "202")
let superman: Person4? = Person4(name: "superman")
// 옵셔널 체이닝을 사용하지 않는다면...
func guardJob(owner: Person4?) {
if let owner = owner {
if let home = owner.home {
if let `guard` = home.guard {
if let guardJob = `guard`.job {
print("우리집 경비원의 직업은 \(guardJob)입니다")
} else {
print("우리집 경비원은 직업이 없어요")
}
}
}
}
}
guardJob(owner: yagom4)
// 옵셔널 체이닝을 사용한다면
func guardJobWithOptionalChaining(owner: Person4?) {
if let guardJob = owner?.home?.guard?.job {
print("우리집 경비원의 직업은 \(guardJob)입니다")
} else {
print("우리집 경비원은 직업이 없어요")
}
}
var guardJob: String
guardJob = yagom4?.home?.guard?.job ?? "슈퍼맨"//앞의값이 nil이라면 guarJob에 슈퍼맨값을 넣어달라
print(guardJob) // 경비원
yagom4?.home?.guard?.job = nil
guardJob = yagom4?.home?.guard?.job ?? "슈퍼맨"
print(guardJob) // 슈퍼맨
18.타입 캐스팅
//인스턴스의 타입을 확인하는 용도, is와as를 사용
class Person5 {
var name: String = ""
func breath() {
print("숨을 쉽니다")
}
}
class Student5: Person5 {
var school: String = ""
func goToSchool() {
print("등교를 합니다")
}
}
class UniversityStudent5: Student5 {
var major: String = ""
func goToMT() {
print("멤버쉽 트레이닝을 갑니다 신남!")
}
}
// 인스턴스 생성
var yagom5: Person5 = Person5()
var hana5: Student5 = Student5()
var jason5: UniversityStudent5 = UniversityStudent5()
var result5: Bool
//result = yagom5 is Person5 // true
//result = yagom5 is Student5 // false
//result = yagom5 is UniversityStudent5 // false
//
//result = hana5 is Person5 // true
//result = hana5 is Student5 // true
//result = hana5 is UniversityStudent5 // false
//
//result = jason5 is Person5 // true
//result = jason5 is Student5 // true
//result = jason5 is UniversityStudent // true
//if yagom5 is UniversityStudent5 {
// print("yagom은 대학생입니다")
//} else if yagom5 is Student5 {
// print("yagom은 학생입니다")
//} else if yagom5 is Person5 {
// print("yagom은 사람입니다")
//} // yagom은 사람입니다
//
//switch jason5 {
//case is Person5:
// print("jason은 사람입니다")
//case is Student5:
// print("jason은 학생입니다")
//case is UniversityStudent5:
// print("jason은 대학생입니다")
//default:
// print("jason은 사람도, 학생도, 대학생도 아닙니다")
//} // jason은 사람입니다
//
//switch jason5 {
//case is UniversityStudent5:
// print("jason은 대학생입니다")
//case is Student5:
// print("jason은 학생입니다")
//case is Person5:
// print("jason은 사람입니다")
//default:
// print("jason은 사람도, 학생도, 대학생도 아닙니다")
//} // jason은 대학생입니다
//업캐스팅
// UniversityStudent 인스턴스를 생성하여 Person 행세를 할 수 있도록 업 캐스팅
var mike: Person5 = UniversityStudent5() as Person5
var jenny: Student5 = Student5()
//var jina: UniversityStudent = Person() as UniversityStudent // 컴파일 오류
// UniversityStudent 인스턴스를 생성하여 Any 행세를 할 수 있도록 업 캐스팅
var jina: Any = Person() // as Any 생략가능
//다운캐스팅
var optionalCasted: Student?
//optionalCasted = mike as? UniversityStudent5
//optionalCasted = jenny as? UniversityStudent5 // nil
//optionalCasted = jina as? UniversityStudent5 // nil
//optionalCasted = jina as? Student5 // nil
var forcedCasted: Student
//forcedCasted = mike as! UniversityStudent5
//forcedCasted = jenny as! UniversityStudent // 런타임 오류
//forcedCasted = jina as! UniversityStudent // 런타임 오류
//forcedCasted = jina as! Student // 런타임 오류
19.assert 와 guard : 앱 실행도중 중간에 값을 확인하고 동적으로 처리할수 있게 해주는 친구들
//assert 디버깅 모드에서만 동작, 디버깅 중 조건의 검증 확인용으로 사용
var someInt2: Int = 0
// 검증 조건과 실패시 나타날 문구를 작성해 줍니다
// 검증 조건에 부합하므로 지나갑니다
//assert(someInt == 0, "someInt != 0")
someInt = 1
//assert(someInt == 0) // 동작 중지, 검증 실패
//assert(someInt == 0, "someInt != 0") // 동작 중지, 검증 실패
// assertion failed: someInt != 0: file guard_assert.swift, line 26
func functionWithAssert(age: Int?) {
assert(age != nil, "age == nil")
assert((age! >= 0) && (age! <= 130), "나이값 입력이 잘못되었습니다")
print("당신의 나이는 \(age!)세입니다")
}
functionWithAssert(age: 50)
//functionWithAssert(age: -1) // 동작 중지, 검증 실패
//functionWithAssert(age: nil) // 동작 중지, 검증 실패
//guard:빠른종료, return 이나 breack를 꼭 사용해야함, 타입캐스팅(타입 바꾸기), 옵셔널에도 사용됨
func functionWithGuard(age: Int?) {
guard let unwrappedAge = age,
unwrappedAge < 130,
unwrappedAge >= 0 else {
print("나이값 입력이 잘못되었습니다")
return
}
print("당신의 나이는 \(unwrappedAge)세입니다")
}
var count = 1
while true {
guard count < 3 else {
break
}
print(count)
count += 1
}
func someFunction(info: [String: Any]) {
guard let name = info["name"] as? String else {
return
}
guard let age = info["age"] as? Int, age >= 0 else {
return
}
print("\(name): \(age)")
}
20.프로토콜 채택, 준수
//프로퍼티는 항상var이여야함
protocol Talkable {//프로토콜 선언
// 프로퍼티 요구
var topic: String { get set }
var language: String { get }
// 메서드 요구
func talk()
// 이니셜라이저 요구
init(topic: String, language: String)
}
//프로토콜 다중상속 : 클래스와 다르게 다중상속가능
protocol Readable {
func read()
}
protocol Writeable {
func write()
}
protocol ReadSpeakable: Readable {
func speak()
}
protocol ReadWriteSpeakable: Readable, Writeable {
func speak()
}
struct SomeType: ReadWriteSpeakable {
func read() {
print("Read")
}
func write() {
print("Write")
}
func speak() {
print("Speak")
}
}
//프로토콜을 준수하면 그에 맞는 메서드를 구현해야함!
//클래스에서 상속과 프로토콜 채택을 동시에 하려면 상속받으려는 클래스를 먼저 명시하고 그 뒤에 채택할 프로토콜 목록을 작성합니다.
class SuperClass: Readable {
func read() { }
}
class SubClass: SuperClass, Writeable, ReadSpeakable {
func write() { }
func speak() { }
}
//프로토콜 준수 확인
let sup: SuperClass = SuperClass()
let sub: SubClass = SubClass()
var someAny2: Any = sup
someAny2 is Readable // true
someAny2 is ReadSpeakable // false
someAny2 = sub
someAny2 is Readable // true
someAny2 is ReadSpeakable // true
someAny2 = sup
if let someReadable: Readable = someAny2 as? Readable {
someReadable.read()
} // read
if let someReadSpeakable: ReadSpeakable = someAny2 as? ReadSpeakable {
someReadSpeakable.speak()
} // 동작하지 않음
someAny2 = sub
if let someReadable: Readable = someAny2 as? Readable {
someReadable.read()
}
21.익스텐션 : 클래스,구조체,열거형,프로토콜 등등에 기능을 확장할 수 있음
//-스위프트의 익스텐션이 타입에 추가할 수 있는 기능
//1.연산 타입 프로퍼티 / 연산 인스턴스 프로퍼티
//2.타입 메서드 / 인스턴스 메서드
//3.이니셜라이저
//4.서브스크립트
//5.중첩 타입
//6.특정 프로토콜을 준수할 수 있도록 기능 추가
extension Int {
var isEven: Bool {
return self % 2 == 0
}
var isOdd: Bool {
return self % 2 == 1
}
}
print(1.isEven) // false
print(2.isEven) // true
print(1.isOdd) // true
print(2.isOdd) // false
var number: Int = 3
print(number.isEven) // false
print(number.isOdd) // true
number = 2
print(number.isEven) // true
print(number.isOdd) // false
'Swift > Swift 언어이해' 카테고리의 다른 글
swift mutating func 키워드란? (1) | 2023.12.02 |
---|---|
for ~ in과 for each의 차이 (0) | 2023.11.04 |
class와 struct의 차이 (0) | 2023.10.31 |
프로퍼티 옵저버란? (0) | 2023.10.30 |
Swift 기본문법 공부 (1) | 2023.04.28 |