나는 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)
참조와 복사가 무엇인지 위 코드의 아래부분을 보면 알 수 있는데 구조체의 경우 복제품만 변경되지만 클래스의 경우 참조한 객체속성까지 변경되는 것을 볼 수 있다.
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
이 역시 실제 프로젝트에서 어떻게 쓸지는 아직 모르겠다.
이 문법 정리글은 계속 업데이트 될 것이여요