Basic Swift - 개요, 및 기본

이은호·2023년 2월 17일
0

swift

목록 보기
1/8
post-thumbnail

스위프트 왜 씁니까?

나는 C를 써본적도 없다. 나름 최신이라는 파이썬, 자바스크립트을 제대로 핸들링 할 수 있는데 다른 언어와는 달리 타입등이 친절하다.(물론 그에 따른 비용도 만만치않지만(typescript라던지)) 마찬가지로 애플의 언어에도 모던한 변화가 이루어졌고, 그게 스위프트라고 보면 되겠다.

스위프트의 특징으로는 현대화,안전성,속도 인데, 사실 말만 들어서는 체감이 잘 안된다.🥹 모든 언어마다 자신을 소개할때만큼은 모두가 세계최강같다. 모든 프로그래밍언어가 그에 걸맞게 장단점이 있지만 지금으로써는 IOS 생태계의 대표 개발 언어로만 알고 있으면 되겠다.

Xcode - playground
맥북 사면 주는 IDE인데, 뭔가 무료로 쓸 수 있어서 기분이 좋다. 기본 문법을 공부해볼 playground을 실행해보자. 공부자료는 애플이 알아서 잘 해놨으니까 자알 챙겨보자.

변수 && 상수

변수 선언시 var을 사용하며, 동적 타이핑을 지원하지는 않는다. 타입도 함께 적어줄수도 있다.
상수 선언시 let을 사용하며, js와는 달리 그 의미가 180도 다른 것을 볼 수 있다.

import UIKit

var hi = "String Interpolation"
var name:String = "uno"
var greeting = "Hello, playground \(hi) \(name)"

let constant = "얘는 못바꿉니다."

파이썬의 fstring과 같은 String Interpolation도 확인해 보았다.

내장함수

let num = 360

// 3의 배수인지 확인하는 메소드
print(num.isMultiple(of: 3)) 

// 0~300 사이중 랜덤으로 수를 뽑아내는 메소드
let random = Int.random(in: 0...300)

var isDark = true
isDark.toggle()
print(isDark)

배열, 딕셔너리

let emptyArr:[Int] = []
let dyn:[Any] = [3,20,"하이"]
let ages = [3,20,60]
let colors = ["green","red","yellow"]
let color = colors[0]
print(ages)

let emptyDic:[String:String] = [:]
let languageCode = ["한국":"ko","미국":"en","일본":"ja",]

이넘

이노옴!!

서로 관계있는 값들을 모아서 표현한것이 바로 enum 이며, 특정 타입들을 표시할때 사용하기 좋다.

enum Week{
    case mon
    case tue
    case wed
    case thu
    case fri
    case sat
    case sun
}
var today: Week = .mon
// 위크라는 타입을 가진 today는 mon을 가진다.
print(today)

enum MediaType {
    case audio(String)
    case video(String)
}

var mp3:MediaType = .audio("mp3")
var h264:MediaType = .video("h264")

어떻게 사용될지는 두고 봐야할것 같으며, 보기좋은 코드를 완성하기 위해서 필요한것으로 이해하고 있겠다.

조건 & 반복

조건문 문법은 개인적으로 파이썬보다 이쁜 것 같다.

var age = 40

if age >= 10 && age < 20 {
    print("10대 입니다")
} else if age >= 20 && age < 30 {
    print("20대 입니다")
} else if age >= 30 && age < 40 {
    print("30대 입니다")
} else if age >= 40 && age < 50 {
    print("40대 입니다")
} else {
    print("......")
}

switch today {
case .sun:
    print("일요일이에유")
case .mon:
    print("월요일이에유")
case .tue:
    print("화요일이에유")
case .wed:
    print("수요일이에유")
case .thu:
    print("목요일이에유")
case .fri:
    print("금요일이에유")
case .sat:
    print("토요일이에유")
}

반복문

for lan in languageCode{
    print(lan.key)
}
for i in 0..<10{
    print("ios개발자다 \(i)")
}

var count = 10

while count > 0{
    print(count)
    if count == 5{
        break
    }
    count -= 1
}

옵셔널

있을수도 있고 없을 수도 있습니다.

깡통배열을 만드는 것처럼 변수도 nil이 할당될수 있다면 타입에 ?를 붙히면 된다.

var age: Int? = nil
print(age) // nil

age = 12
print(age) // Optional(12)

함수

void형태는 그냥 작성하면 되고
리턴값이 있는 경우 파라미터 옆에 -> 과 타입을 적어준다.
함수의 경우 클로저만 잘 알아주자. 클로저는 굳이 함수를 따로 작성해야 하나? 할 때 많이 사용한다. 처음보는 형태라서 조금 어지럽다.

func call(name:String){
    print("hello \(name)")
    
}
call(name: "이은호")
let callName = call
callName("hi")

클로저

클로저를 더 쉽게 이해하자면 이름이 없는 함수라고 보면 될 것같다. 파이썬의 람다와 비슷한 개념일까.
in을 기준으로 선언부와 실행부가 나뉜다.

let checking = {(name:String) in
        print("제 이름은 \(name)입니다:)")
}
checking("uno")

가만보면 js의 화살표함수와 비슷한 것을 볼 수 있다. 반갑다 ㅋㅋ

컬렉션의 메소드와 자주사용하는 것을 다음 예제로 확인할 수 있다.

// filter
let members = ["Jason", "Greg", "Tiffany"]
let nameHasT = members.filter{
    name in return name.hasPrefix("T")
}
// ["Tiffany"]

// map
let prices = [1000, 2000, 3000]
let doubledPrices = prices.map { price in
    return price * 2
}
// [2000, 4000, 6000]

// reduce
let revenues = [100, 200, 300]
let totalRevenue = revenues.reduce(0) { partialResult, next in
    return partialResult + next
}
//(0) 파라미터는 초기값
// 600

메소드와 클로저의 댄스는 좀 난해해보인다. 그런데 다 단축된 문법이라는 걸 알면 재밌을 것이다.

func validate(id: String, checking: (String) -> Bool) -> Bool {
    // Some Preparation work here..
    print("Validation 준비중...")
    let isValid = checking(id)
    return isValid
}
// 긴것을
let validationResult2 = validate(id: "User001", checking: { (id: String) in
    if id == "User000" {
          return false
      }

      return true
})


// 중간 단계
let validationResult3 = validate(id: "User001") { tomato in
    let isValid = tomato != "User000"
    return isValid
}


// 짧게
let validationResult4 = validate(id: "User002") { $0 != "User000" }
//

구조체 & 클래스

구조체는 사용자만의 데이터타입을 만들때 사용하며 struct로 선언한다.

struct Album{
    let title: String
    let artist: String
    var isReleased = false
    
    func description()->String{
        return "\(title) by \(artist)"
    }
    
    mutating func release(){
        self.isReleased = true
    }
}

var spaceFantasy = Album(title: "스페이스환타지", artist: "이박사")
print(spaceFantasy.description())
spaceFantasy.release()
print(spaceFantasy.isReleased)

우선은 미니 클래스라는 느낌으로 받아들이면 될 것 같다. 또한 속성의 값에 따라서, 다른 속성의 값을 변경해줄수도 있다.

struct Task {
    var name: String
    var progress: Int {
        didSet {
            print("Current Progress : \(progress) %")
        }
    }
    var isDone: Bool {
        return progress == 100
    }
}


var task = Task(name: "Very Important Task", progress: 0)

task.progress = 90 // Current Progress : 90 %
print(task.isDone)
task.progress = 100 // Current Progress : 100 %
print(task.isDone)
  • 클래스는 상속이 가능하며
  • 클래스는 참조, 구조체는 복사
  • 클래스는 생성자를 기본적으로 안만들어준다.
class Employee{
    var name: String
    var hours: Int
    init(name:String,hours:Int){
        self.name = name
        self.hours = hours
    }
    func work(){
        print("hard work")
    }
    func summary(){
        print("hard work \(hours)hours")
    }
}

class IOSDev:Employee{
    override func work(){
        print("IOS work")
    }
    override func summary(){
        print("hard work \(hours/2)hours")
    }
}

struct Phone {
    var modelName:String
    var manufacturer:String
    var version = 1.0
}

let normalWorker = Employee(name: "이경호", hours: 12)
let iosWorker = IOSDev(name: "이은호", hours: 12)
normalWorker.work()
iosWorker.work()
normalWorker.summary()
iosWorker.summary()

var iPhone1 = Phone(modelName: "13", manufacturer: "Apple")
var iPhone2 = iPhone1
iPhone2.modelName = "14"
print(iPhone1.modelName)
print(iPhone2.modelName)

let iosWorker2 = iosWorker
iosWorker2.name = "무야호"
print(iosWorker.name)
print(iosWorker2.name)

참조와 복사가 무엇인지 위 코드의 아래부분을 보면 알 수 있는데 구조체의 경우 복제품만 변경되지만 클래스의 경우 참조한 객체속성까지 변경되는 것을 볼 수 있다.

stored property && computed property

struct Watch{
    let model:String
    let manufacturer:String
    var description:String{
        return "\(model) by \(manufacturer)"
    }
}

struct Person{
    let firstName:String
    let lastName:String
    var fullname:String{
        return "\(firstName) \(lastName)"
    }
}

let appleWatch = Watch(model: "7", manufacturer: "Apple")
print(appleWatch.description)

let uno = Person(firstName: "uno", lastName: "lee")
print(uno.fullname)

let이 stored이고 var이 computed인데, stored는 말그대로 값을 저장하고 있지만 computed의 경우 기존의 stored를 이용하거나 특정값을 전달할때 사용하는 프로퍼티이다.

프로토콜

프로토콜은 제공하고자 하는 역할을 미리 정의한 것이다. 추상클래스와 비슷한 역할이라고 보면 될 것같다.

protocol Coach {
    var name: String { get set }
    var currentTeam: String { get }
    func training()
    func direct()
}

struct Mourinho: Coach {
    var name: String = "Jose Mourinho"
    var currentTeam: String = "AS Roma"
    
    func training() {
        print("Traing Player")
    }
    
    func direct() {
        print("Direct Game")
    }
}

let mourinho = Mourinho()
print("\(mourinho.name), \( mourinho.currentTeam)")
mourinho.training()
mourinho.direct()

get과 set은 해당 속성이 읽기,쓰기역할을 하는 것이라고 보면 되며 쓰기역할이 부여되었다면, let 상수선언이 불가능하겠다.

익스텐션

기존 타입에 새로운 역할을 추가할때 사용한다.

import Foundation
extension String {
    func contains(s: String) -> Bool {
        return self.contains(s)
    }
    
    func replace(target: String, with: String) -> String {
        return self.replacingOccurrences(of: target, with: with)
    }
}


let testString = "Hello iOS Developer!!"
let replaced = testString.replace(target: "Hello", with: "안녕하세요")

print(replaced)
//    안녕하세요 iOS Developer!!
print(testString.contains(s: "iOSs"))
// true

이 역시 실제 프로젝트에서 어떻게 쓸지는 아직 모르겠다.

이 문법 정리글은 계속 업데이트 될 것이여요

0개의 댓글