1년 4개월정도 현업으로 외주일을 하다보니 너무 결과에만 치중된 개발을 하고 있는것 같아서 기초부터 다시 다져볼려고 한다.
책은 꼼꼼한 재은씨(문법)으로 정했다!
오브젝트 C에서 개발 언어 대체
서버프로그래밍도 스위프트로 가능하다는 뜻
컴파일러가 타입 추론을 해줘서 동적 바인딩인 것 처럼 보이지만 정적 바인딩 언어이다.
안정성을 높임
프로젝트 내에서 작성된 객체들은 반입 과정 없이 참조가능 -> 일일히 import를 해줄 필요가 없다는 뜻
대괄호를 사용하여 해시 테이블 만듦
해시 테이블은 (Key, Value)로 데이터를 저장하는 자료구조
var airprots = [String : String?]()
airprots["ICN"] = "Inchon International Airport"
컴파일러가 알아서 변수에 데이터 형식을 지정할 수 있음
데이터 타입 생략
let myString = "Hello, World!" // Strng
let myInt = 42 // Int
let myDouble = 3.14 // Double
어떤 타입의 데이터가 데이터 구조에 저장될지 제네릭 타입으로 미리 알려 줌
제네릭 타입은 <> 기호를 통해 형식을 지정해준다
var airprots = Dictionary<String, String?>()
미리 데이터가 어떤 타입으로 저장될지 알려주면 생기는 장점
1.타입의 안정성: 컴파일러가 코드를 더 엄격하게 검사
2. 코드의 가독성: 일반적으로 읽기 쉬움
3. 런타임 오버헤드 감소: 컴파일 시점에 타입 체크를 하기 때문에 타입변환 오버헤드를 감소시킨다.
등등
역슬래쉬와 소괄호를 작성하고 그 안에 평가할 식이나 변수를 넣어 출력해주는 템플릿 시스템
let name = "KangJaeHyeok"
let age = 25
let introduce = "내 이름은 \(name)이고 나이는 \(age)살 이야"
스위프트는 세미클론을 생략해도 되고 안해도 된다.
프로토콜은 특정한 역할이나 기능을 정의하며, 이를 채택한 타입에서 구현해야 하는 규약
프로토콜을 사용하는 이유
1.코드 재사용과 확장: 여러 타입에서 동일한 기능을 사용, 새로운 타입이 프로토콜을 채택함으로써 기능 확장
2. 다형성: 다양한 타입을 하나의 프로토 타입으로 다룰 수 있음
3. 의존성 역전 원칙: 추상적인 프로토콜에 의존할 수 있음
의존성 역전원칙은 높은 수준의 모듈이 저수준의 모듈에 의존하면 안됨 두 모듈은 추상화된 인터페이스에 의존해한다는 개념
// 고수준 모듈
class OrderSystem {
private var orderRepository = OrderRepository()
private var paymentProcessor = PaymentProcessor()
func placeOrder(order: Order) {
orderRepository.save(order)
paymentProcessor.processPayment(order)
}
}
// 저수준 모듈
class OrderRepository {
func save(order: Order) {
// 주문을 저장하는 로직
}
}
class PaymentProcessor {
func processPayment(order: Order) {
// 결제 처리 로직
}
}
OrderSystem이 OrderRepository와 PaymentProcessor에 직접 의존하고 있음
이는 변경이 발생할 경우 OrderSystem의 수정이 필요
//고수준 모듈
protocol OrderHandler {
func placeOrder(order: Order)
}
class OrderSystem {
private var orderHandler: OrderHandler
init(orderHandler: OrderHandler) {
self.orderHandler = orderHandler
}
func placeOrder(order: Order) {
orderHandler.placeOrder(order: order)
}
}
//저수준 모듈
class OrderRepository: OrderHandler {
func placeOrder(order: Order) {
// 주문을 저장하는 로직
}
}
class PaymentProcessor: OrderHandler {
func placeOrder(order: Order) {
// 결제 처리 로직
}
}
OrderSystem이 OrderHandler에만 의존하고 있습니다. 구체적인 구현(OrderRepository, PaymentProcessor)에는 의존하지 않음
만약 OrderRepository나 PaymentProcessor의 구현이 변경되더라도 OrderSystem은 수정하지 않아도 됨
이렇게 의존성 역전 원칙을 따르면 코드의 유연성이 높아지고, 유지보수가 쉬워지고 단위 테스트 작성이 용이해지며, 코드의 재사용성도 높아짐
함수나 메소드에서 n개의 값을 변환할때 사용
func getNames() -> (String, String, String) {
return ("강재혁", "강재호", "강철수")
}
더 이상 사용하지 않는 객체를 메모리에서 해제하는 프로세스를 자동으로 처리하는 기술
일급 객체(first-class citizen)로서, 함수나 메서드로 전달되거나 변수/상수에 할당될 수 있는 독립적인 코드 블럭.
※ 일급 객체란? 변수나 데이터 구조 안에 담을 수 있고 상태 변환도 가능하며, 함수의 인자로 전달할 수 있는 객체이다
클로저의 특징
- 후행 클로저: 함수의 마지막 인자로 전달되는 클로저는 함수 호출의 괄호 밖으로 뺄 수 있음
- 클로저 표현 간소화: 인자와 반환 타입의 타입 추론을 통해 코드를 더 간결하게 작성 가능
- 캡쳐 : 클로저는 자신이 정의된 환경을 캡쳐할 수 있음. 이는 클로저가 자신을 둘러싼 범위의 변수나 상수를 가져다 사용할 수 있게 해줌
- Escaping Closures: 클로저가 함수의 인자로 전달되지만, 함수가 리턴된 후에도 실행될 수 있는 경우
// 1.후행 클로저
func someFunction(argument: Int, closure: () -> Void) {
// 함수 내부 로직
closure()
}
// 후행 클로저 사용
someFunction(argument: 5) {
print("클로저가 호출되었습니다.")
}
// 2. 클로저 표현 간소화
let numbers = [1, 2, 3, 4, 5]
let squared = numbers.map { $0 * $0 }
// 3. 캡쳐
func makeIncrementer(incrementAmount: Int) -> () -> Int {
var total = 0
let incrementer: () -> Int = {
total += incrementAmount
return total
}
return incrementer
}
let incrementByTwo = makeIncrementer(incrementAmount: 2)
print(incrementByTwo()) // 2
print(incrementByTwo()) // 4
//4. Escaping Closures
func delayedExecution(closure: @escaping () -> Void) {
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
closure()
}
}
큰따옴표 세 개를 겹친 """로 문자열의 시작과 끝을 나타냄 -> 내부에 인위적인 줄바꿈 문자("\n")을 넣어주지 않아도 됨
let multiLineString = """
이것은
멀티 라인
쿼우팅입니다.
"""
컴파일러에서 제공하는 코드 최적화기를 사용하여 소스 컴파일과 최적화를 수행함으로써 스위프트의 성능을 극대화할 수 있음
변수나 상수는 반드시 선언한 후에 사용하도록 강제, 타입 추론 기능에 의해 변수의 초기값을 기준으로 타입을 정의
배열과 정수는 오버플로우에 대비하여 확인
정의하지 않은 배열 값에 승인하지 않은 값들이 주입될 수 없도록 Array bounds check 기능 추가
포인터에 직접 접근 차단하고 클래스를 통해 간접적으로만 레퍼런스 참조
ARC를 이용해여 자동으로 메모리를 관리 -> 메모리 누수에 대한 안전성
읽고 쓰기 쉬운 파이썬언어를 기반
오브젝트-C보다 적은 양의 코드(헤더 파일 대신 메인 파일에 통합)
현대 프로그래밍 언어 사용
플레이그라운드를 통해 메모리 스택등의 정보 확인을 즉시 확인 가능
디버깅 쉬움
코코아 프레임워크나 코코아 터치 프레임워크의 모든 API를 스위프트로 호출
오브젝티브-C 코드에 의존하지 않고도 프로그램을 작성 가능
C언어나 오브젝티브-C 언어를 완전히 대체할 수 있음
하나의 앱프로젝트내에서 오브젝티브-C 참조 가능
헤더 파일과 소스 파일 구분
.swift 확장자를 가진 파일 하나로 통합
헤더 파일에 클래스의 인터페이스를 정의하고 소스파일에서는 정의된 인터페이스를 구현
반드시 상위 클래스 상속
아무것도 없을때는 NSObject를 상속받아야됨
인터페이스 정의 없이 바로 구현 가능
다중상속 지원 안함, 프로토콜을 정의하여 클래스 객체가 준수해야 할 형식 제공
카테고리 개념을 통해 상속 대신 기존 객체 자체를 직접 확장
Extension을 통해 확장
범용 타입이란 모든 데이터 타입을 저장할 수 있는 타입 -> 개발의 편의와 효율성을 높임
범용 타입으로 id 타입을 제공
범용 타입으로 Any, AnyObject 제공
Any: 구조체, 클래스, 열거형, 함수 등
AnyObject: 클래스에 한함
메소드 호출을 메시지 전송 방식으로 처리
객체와 메시지는 공백을 통해 연결되어 대괄호를 사용하여 구분
ex) [인스턴스명 incrementBy: 3]
일반적인 객체지향에서의 메소드 호출 방식
객체와 메소드 사이에 점(.)을통해 연결
ex) 인스턴스명.incrementBy(3)
존재하지 않는 객체에 대한 참조
옵셔널 타입의 기본값
값이 존재하지 않음
C문법을 그대로 물려받아서 사용
개발자가 안하고 컴파일러가 직접 레퍼런스를 참조할 것인지 아니면 객체를 복사할 것인지 결정
객체지향을 위한 타입으로 클래스를 제공
객체지향용 타입으로 클래스, 구조체, 열거형까지 제공
모두 인스턴스화 가능
※ 인스턴스란? 실제로 메모리가 할당된 개별 객체
블록이라는 개념으로 표현
클로저를 통해 표현
오류 발생이 예상되는 지점에 미리 오류 검출 코드를 작성하고 실제롤 오류가 발생할 때 정해진 코드 블록 바깥으로 오류 정보를 던짐
읽고 쓸 수 있는 매개변수를 사용하여 오류를 검출해내는 방법
오류 처리를 위한 구문이 별도롤 제공된 것은 아님
Try~Catch를 통해 오류가 발생하더라도 프로그램이 중단되는것을 막음
꼼꼼한 재은씨의 Swift (문법)