들어가기전
- 이 문서는 swift에 문법적 특징들을 서술하였다.
- Swift만 안다고 iOS앱을 만들 수 있지않다. ( cocoa touch framework와 XCode 사용법 등등 필요 )
Swift란?
Swift는 애플의 iOS와 macOS를 위한 프로그래밍 언어로 2014년 6월 2일 애플 세계 개발자 회의(WWDC)에서 처음 소개되었다. 기존의 애플 운영체제용 언어인 Objective-C와 함께 공존할 목적으로 만들어졌다. Objective-C와 마찬가지로 LLVM으로 빌드되고 같은 런타임을 공유한다
- 2010년 크리스 래트너를 필두로한 애플 프로그래머들이 개발.
- Obj-C, C#, Python, Rust, haskell 등의 기존언어와 신생언어를 참조하여 만듬.
- 클로저, 다중리턴타입, 네임스페이스, 제네릭스, 타입인터페이스 등 Obj-C에는 없었던 현대 프로그래밍 언어가 갖고 있는 기능들이 많이 포함됨.
- 2015년 12월 오픈소스전환 Github
- LLVM
Swift 특징
안전성(Safe)
- 안전한프로그래밍을 지향함
- 엄격한 문법으로 개발자실수를 방지
- 옵션널, guard, 오류처리, 타입통제 등등
Swift 특징
신속성(Fast)
- C,C++,Obj-C를 대체를 목적으로 개발
- 실행속도 최적화 및 컴파일러 개량으로 더 빠른 컴파일 성능구현
Swift 특징
더 나은 표현성(Expressive)
- 사용하기 편하고 보기좋은 문법
- 현대적이고 세련된 문법구현
Swift 사용환경
지원OS
- macOS
- Ubuntu
Swift 사용환경
지원도구
- XCode
- REPL
- IBM Swift Sandbox (웹)
- RunSwift (웹)
- iPad Swift Playground (앱)
명명규칙
- 소문자 Camel Case : 함수, 메서드, 변수, 상수
- 대문자 Camel Case : 클래스, 구조체, enum, extension … etc (type)
- 대소문자구분함
- Swift API 디자인 가이드라인
콘솔로그
- print : 단순문자열 출력
- dump : 객체에 자세한 설명까지 출력
class Inswave {
var product: String = ""
}
let company: Inswave = Inswave()
company.product = "웹스퀘어"
dump(company)
/* 출력결과
__lldb_expr_11.Inswave #0
- product: "웹스퀘어"
*/
문자열보간법
- 문자열내에 변수와 상수에 값을 출력하기 위해서 사용함
- \ (변수나상수)
let name: String = "Inswave systems"
print("회사이름은 \(name) 입니다.")
주석
- 중첩주석지원
- XCode에 퀵헬프기능이 있어 마크업 문법에 맞춰 주석을 작성하면 문서에 큰도움이됨.
- 자세한 마크업은 애플에서 제공하는 Markup Formatting Reference문서를 참조
// 한줄 주석
/*
여러줄 주석
*/
/* 주석시작
/* 중첩주석
// 한줄주석추가
*/
이부분도 주석됨
*/
퀵헬프 마크업
/// 오류타입의 열거형
/// - noAppID : hybrdApp id가 서버 Config에 없는 경우
/// - unavailableServer : 하이브리드앱 서버를 사용할 수 없음
/// - unknown : 알수없는 오류
enum hybridAppError : Error {
case noAppID
case unavailableServer
case unknown
}
상수
- let 키워드를 사용하여 상수생성
- let [상수명] : [데이터타입] = [값]
- 데이터타입 생략가능
let cname: String = "inswave systems"
let myname = "changok"
let age: Int = 30
변수
- var 키워드를 사용하여 변수생성
- var [변수명] : [데이터타입] = [값]
- 데이터타입 생략가능
var job: String = "iOS Programmer"
var height = 180.0
height = 160.0
기본 데이터 타입 1
- Int : +,- 부호를 포함한 정수
- UInt : 0을 포함한 양의 정수
- Bool : 참(true),거짓(false)만 값으로 가짐. 0,1은 타입에러
- Float : 32비트 부동소수 표현 (소수점 6자리)
- Double : 64비트 부동소수 표현 (소수점 15자리)(권장)
- nil : 없음. 값이들어있지않고 비어있음을 나타내는 키워드
기본 데이터 타입 2
- Character : 한문자 (swift는 유니코드문자를 사용, 모든언어 및 특수문자 사용가능)
- String : 문자열, 유니코드를 사용하여 문자열앞뒤에 큰따옴표를 사용하여 표현
- 특수문자/제어문자 : 문자열내에 일정기능을하는 특수문자 ( \n, \ , * , \t ,\0 )
- Any : 모든 데이터 타입
- AnyObject : 제한적인 Any, 클래스에 인스턴스만 할당가능
타입추론
- 변수나 상수 선언시 특정타입을 명시하지않아도 컴파일러가 할당된값을 기준으로 타입을 결정
// name은 타입어노테이션이 있어 추론할 필요가없음. age의 경우 입력값 19를 보고 타입을 Int로 추론한다.
var name: String = "tester"
var age = 19
// 변수나 상수에 선언과 초기화를 분리시에는 선언부에 타입어노테이션을 넣어야 된다.
var number
number = 2 // error발생
컬렉션 1
- 튜플 : 지정된 데이터의 묶음. 파이선의 튜플과 유사, 타입이름은 따로없고 일정타입의 나열생성됨
var cat: (name:String, age:Int, size:String) = ("name",2,"big")
- 배열 : 같은 타입의 데이터를 일렬로 순서대로 저장하는 형태의 컬렉션
var names: Array<String> = ["inswave","rnd1","rnd2"]
var names:[String]
컬렉션 2
- 딕셔너리 : 순서없이 키와 값의 쌍으로 구성되는 컬렉션
var codeForName: Dictionary<String, Int> = Dictionary<String,Int>()
var codeForName:[String,Int] = [String:Int]()
var codeForName:[String,Int] = [:]
컬렉션 3
- 세트 : 같은타입의 데이터를 순서없이 하나의 묶음으로 저장, 중복없음
var codes: Set<String> = Set<String>()
let 새: Set<String> = ["비둘기","닭","꿩","매"]
- 열거형 : 연관된 항목들을 묶어서 표현, enum키워드를 사용하여 생성
enum School { case primary, elementary, middle, high }
조건문
- if문 : 정수,실수 등 0이 아닌 모든 값을 참으로 취급하여 조건 값이 될 수 있었던 다른언어와 달리 스위프트는 조건값이 꼭 Bool 타입이어야한다.
- switch문 : 다른언어에 비해 많이 다르다. switch구문에 ()를 생략가능, break문은 선택사항.
- case문 내부코드 실행후 자동 break됨.
switch문 예
switch 입력값 {
case 비교값1:
실행구문
case 비교값2:
실행구문
fallthrough // 이번케이스를 마치고 switch문이 끝나지않음. 다음으로 진행
case 비교값3, 비교값4, 비교값5 : //여러개비교 가능
실행구문
break //break문을 통한 종료는 선택사항
default: // 한정된 범위가 명확하지않으면 default케이스는 필수
실행구문
}
반복문
- 스위프트의 반복문은 기존언어의 반복문과 크게 다르지않음.
- C스타일에 for문 삭제됨.
- 조건에 괄호 생략가능.
- do-while문은 repeat-while문으로 구현
반복문 예
//for-in 반복문
for 임시 상수 in 시퀀스 아이템 {
실행코드
}
// while
var items = ["ins1","ins2","ins3"]
while items.isEmpty == false {
print("hello \(items.removeFirest())")
}
// repeat-while
var items = ["ins1","ins2","ins3"]
repeat {
print("hello \(items.removeFirest())")
} while items.isEmpty == false
함수
- 스위프트의 함수는 재정의(오버라이드)와 중복정의(오버로드)를 모두지원
- 함수정의 키워드 func
- 반환타입은 ->를 사용하여 명시
- 매개변수이름,전달인자레이블
- 매개변수이름을 사용하지않을때는 와일드카드 식별자사용
- 종료되지않는 함수( 비반환함수, 비반환메서드 ) : 반환타입을 Never로 명시
함수 예
//함수정의
func 함수이름 (매개변수...) -> 반환타입 {
실행구문
return 반환값
}
//매개변수이름, 전달인자레이블
func 함수이름 (매개변수이름 전달인자레이블:매개변수타입, 매개변수이름 전달인자레이블:매개변수타입) -> 반환타입 {
실행구문
return 반환값
}
//와일드카드 사용예
func sayHelo(_ name:String) -> String {
print("Helo \(name)!")
}
//종료되지않는 함수
func crashAndReport() -> Never {
fatalError("something crash")
}
옵셔널
- 옵셔널은 단어 뜻대로 ‘선택적인’
- 값이 있을 수도, 없을 수도 있음
- 즉 이 변수는 꼭 값이 있다는 것을 보장못함. nil일수도있음.
- nil은 옵셔널로 선언된 곳에서만 사용가능. 옵셔널변수 또는 상수는 데이터타입 뒤에 물음표를 붙여서 사용
옵셔널 예
// 옵셔널변수 선언과 nil할당
var vname: String? = "changok"
print(vname)
vname = nil
print(vname)
//옵셔널강제추출
var myName: String? = "changok"
if myName != nil {
print("my name is \(myName!)")
} else {
print("my name is nil")
}
//옵셔널바인딩
var yourname: String? = "changok"
if let name = yourname {
print("your name is \(name)")
} else {
print("your name is nil")
}
구조체
- 데이터타입들을 묶어서 사용할 때 필요함.
- swift의 구조체는 메서드를 가질 수 있음.
- struct 키워드로 정의
struct 구조체이름 {
프로퍼티
메서드
...
}
구조체 예
struct base{
var name: String
var age: Int
}
var base1: base = base(name:"inswave",age:16)
base1.name = "websquare" //변경가능
base1.age = 10
let base2: base = base(name:"proworks",age:14)
base2.age = 15 // 변경불가
클래스
- swift 클래스는 부모클래스없이 단독으로 정의 가능
- class 키워드를 사용하여 정의
class 클래스이름: 부모클래스이름 {
프로퍼티
메서드
}
//deinit
class Person {
var height: Double = 0.0
var weight: Double = 0.0
deinit {
print("person is died")
}
}
var tester: Person? = Person()
tester = nil // print 'persion is died'
구조체와 클래스의 차이
- 구조체는 상속없음
- 타입캐스팅은 클래스의 인스턴스에만 허용
- 디이니셜라이저는 클래스이 인스턴스만 활용가능
- 참조횟수계산은 클래스의 인스턴스에만 적용
- 구조체는 값타입이고 클래스는 참조타입이다.
값타입과 참조타입 차이
struct Info {
var name :String
}
var myInfo: Info = Info(name: "changok")
var friendInfo: Info = myInfo
friendInfo.name = "tom"
print("my name is \(myInfo.name)")
print("my friend name is \(friendInfo.name)")
// friendInfo는 myInfo으 값을 복사해서 서로 별개의 값을 가짐.
class Person {
var name: String = "changok"
var age: Int = 30
}
var myObj: Person = Person()
var myFriend: Person = myObj
print("my age is \(myObj.age)") // 30
print("my friend age is \(myFriend.age)") // 30
myFriend.age = 29
print("my age is \(myObj.age)") // 29
print("my friend age is \(myFriend.age)") // 29
클래스
- 프로퍼티
- 저장 프로퍼티 : 인스터스의 변수 나 상수
- 연산 프로퍼티 : 특정연산을 수행한 결과값을 가짐
- 타입 프로퍼티 : 인스턴스가 아닌 타입자체에 속한 프로퍼티
- 프로퍼티 감시자 : 프로퍼티값이 변경이되면 호출되는 메서드 (willSet,didSet)
- 메서드
- 인스턴스 메서드 : 특정타입에 인스턴스에 속한 메서드 (일반적인)
- 타입 메서드 : 타입자체에서 호출이 가능한 메서드
- 접근제어 : 코드끼리 상호작용할 때 파일 간 또는 모듈간에 접근을 제한 할 수 있는 기능, 접근제어를 통해 구현은 숨기고 허용된 기능만 노출할 수 있음.
접근수준 | 키워드 | 접근도 | 범위 | 비고 |
---|---|---|---|---|
개방접근 | open | 높음 | 모듈 외부까지 | 클래스에서만 사용 |
공개접근 | public | 모듈 외부까지 | ||
내부접근 | Internal | 모듈 내부 | ||
파일외부비공개 접근 | fileprivate | 모듈 내부 | ||
비공개접근 | private | 낮음 | 기능 정의 내부 |
클로저
- 스위프트의 클로저는 C나Obj-C에 블록 다른언어의 람다와 유사한 합니다.
- 일정기능을 하는 코드를 하나의 블록으로 모아놓은 것을 뜻함. 함수는 클로저의 한 형태
- 클로저는 세가지 모양을 가질 수 있다.
- 이름을 가지면서 어떤 값도 획득하지않는 전역함수
- 이름을 가지면서 다른함수내부의 값을 획득할 수 있는 중첩된 함수의 형태
- 이름이 없고 주변 문맥에 따라 값을 획득할 수 있는 축약문법으로 작성된 형태
- 클로저의 표현방법
- 클로저는 매개변수와 반환값의 타입을 문맥을 통해 유추할 수 있어 매개변수와 반환 값의 타입을 생략가능
- 클로저에 단 한 줄의 표현만 들어있다면 암시적으로 이를 반환 값으로 취급
- 축약된 전달인자 이름을 사용할 수 있음
- 후행 클로저 문법을 사용가능
// 클로저형식
{ (매개변수들) -> 반환타입 in
실행코드
}
//함수전달예
func backwards(first: String, second: String) -> Bool {
print("\(first) \(second) compare")
return first > second
}
let reversed: [String] = names.sorted(by: backwards)
print(reversed)
//메서드에 클로저전달
let reversed: [String] = names.sorted(by:{first: String, second:String) -> Bool in return first > second
})
print(reversed)
//후행클로저표현
//후행클로저 : 함수나 메서드의 마지막인자로 위치하는 클로저는 함수나 메서드의 소괄호를 닫은 후 작성가능
let reversed: [String] = names.sorted() { first: String, second:String) -> Bool in return first > second
}
프로토콜
- 프로토콜은 특정 역할을 수행하기 위한 메서드, 프로퍼티, 기타 요구사항 등의 청사진을 정의
- 프로토콜은 정의와제시만할뿐 스스로 기능을 구현하지는 않는다.
- 구조체,열거형,클래스는 프로토콜을 채택해 특정기능을 구현할 수 있다.
- 프로토콜 청사진의 기능을 모두 구현해야된다.
protocol 프로토콜이름 {
프로토콜정의
}
// 사용예
struct SomeStruct: AProtocol, BProtocol {
//구조체정의
}
class SomeClass: AProtocol, BProtocol {
//클래스정의
}
enum SomeEnum: AProtocol, BProtocol {
//열거형 정의
}
익스텐션 1
- 구조체, 클래스, 열거형, 프로토콜 타입에 새로운 기능을 추가할 수 있는 기능
- Obj-C 카테고리와 유사한 기능이다. Obj-C는 카테고리마다 이름을 붙였지만 스위프트 익스텐션은 이름이 없다.
- 익스텐션은 타입에 새로운 기능을 추가할 수 있지만, 기존기능을 재정의 할 수는 없다.
익스텐션 2
- 익스텐션이 타입에 추가할 수 있는 기능
- 연산 타입 프로퍼티 / 연산 인스턴스 프로퍼티
- 타입 메서드/ 인스턴스 메서드
- 이니셜라이저
- 서브스크립트
- 중첩타입
- 특정프로토콜을 준수할 수 있도록 기능 추가
상속과 익스텐션비교
상속 | 익스텐션 | |
---|---|---|
확장 | 수직확장 | 수평확장 |
사용 | 클래스 타입에서만 사용 | 클래스, 구조체, 프로토콜, 제네릭 등 모든타입 |
재정의 | 재정의 가능 | 재정의 불가 |
extension 확장할 타입 이름 {
// 타입에 추가될 새로운 기능 구현
}
// 프로토콜확장
extension 확장할 타입 이름 : 프로토콜1, 프로토콜2, 프로토콜3 {
// 프로토콜 요구사항 구현
}
참고
- 위키백과
- The Swift Programming Language (3.0.1 edition)