**Objective-C의 selector
=> Swift는 함수형 프로그래밍 언어이고 함수가 일급 객체라서 함수의 참조를 변수에 바로 대입, 리턴 가능
=> Objective-C는 함수가 일급 객체가 아니므로 함수단위 대입이나 리턴 불가
- 함수단위로 작업할 수 있도록 Selector라는 개념 도입
- 애플은 메소드나 함수를 Selector라고 표현
=> iOS프로그래밍에서 매개변수 중 Selector는 함수나 메소드를 요청하는 것
**생성자와 소멸자
=> Constructor : 인스턴스를 생성할 때 호출하는 메소드
- 인스턴스가 생성될때 가장 먼저 호출되는 메소드
- 생성자가 하는 일은 allocation(메모리 할당)과 initialize(초기화 작업)
- Objective-C는 생성자 호출시 alloc + init
- 모든 객체 지향 언어에서는 클래스 생성시 매개변수가 없는 생성자를 제공
- 이 생성자는 개발자가 생성자를 만들면 자동적으로 소멸
- 생성자의 첫줄에는 보이지 않는 상위클래스 생성자 호출 코드가 포함되어있음(매개변수가 없는 생성자)
- 생성자를 만드는 목적 : 초기화 작업을 위해
=> Destructor : 인스턴스가 파괴될때 호출되는 메소드
- 매개변수를 가질수 없으며 Overloading도 안됨
- 사용을 한 외부 자원에 대한 release 작업 수행
=> swift에서는 생성자를 init라고 정의
- 소멸자는 deinit
=> swift의 메모리 정리
- swift, Objective-C, kotlin 와 python은 참조 카운팅이라는 개념을 이용해서 메모리 정리
- 처음 메모리 할당을 받으면 참조 카운트는 1로 설정
- 이 메모리 영역을 다른 변수가 참조하면 참조 카운트가 1증가
- 변수가 소멸되거나 nil을 대입하면 참조 카운트가 1감소
- 참조 카운트가 0가 되면 Garbage Collection이 메모리를 회수
- 게임이나 오랜시간 동안 사용하는 애플리케이션은 메모리 정리가 중요
**swift의 상속
1. 상속 방법
class 클래스명 : 상위 클래스명{
=> 상위클래스의 멤버 사용 가능
}
2. Overriding(메소드 재정의)
=> 상위 클래스의 메소드를 하위 클래스에서 다시 정의하는 것
=> 목적은 상위 클래스에서 제공해주는 메소드의기능이 부족하여 기능 확장을 위해 수행
- 상위 클래스의 메소드를 호출하고 필요한 기능을 추가로 정의
=> swift에서는 overriding을 할 때 반드시 func 앞에 override를 붙여야 함
=> 프로퍼티도 오버라이딩 가능
=> init의 오버라이딩(생성자 오버라이딩) : 상위 클래스에 매개변수가 없는 생성자(Default Constructor)가 없는 경우
- View를 커스터마이징 할 때 필요
3. 상속관계에서의 대입
=> 상위 클래스 타입으로 선언된 변수에 하위 클래스 타입으로 만들어진 인스턴스의 참조를 바로 대입
=> 하위 클래스 타입으로 선언된 변수에 상위 클래스 타입으로 만들어진 변수의 참조는 강제 형변환을 해야한 대입 가능
- 이때 책임은 개발자가 져야 함
- 상위 클래스 타입의 변수에 저장된 인스턴스의 참조가 하위 클래스 타입으로 만들어진 경우만 가능
4. 인스턴스 참조 변수의 메소드 호출
=> 인스턴스 참조 변수는 기본적으로는 선언되었을 때 사용한 클래스의 멤버만 호출 할 수 있는데 예외적으로 오버라이딩 된 메소드는 선언되었을 때 사용한 클래스 타입이 아니고 대입된 인스턴스의 자료형의 메소드를 호출
**enum
=> 나열형 상수
=> 여러개의 상수를 하나로 묶어둔 것
=> 옵션(선택제한)을 만들때 사용
enum 이름 : 자료형{
case 항목명 = 값,
case 항목명 = 값...
}
=> 사용시 이름.항목명으로 사용
=> iOS에서는 만드는 것보다 사용하는 것이 더 중요
=> iOS에서는 변수의 자료형이 결정되어 있다면 이름을 생략하고 .항목명 만으로 대입 가능
=> iOS SDK의 최근 버전의 가장 큰 변화 2가지는 Swift UI의 도입과 항목명을 소문자로 사용하는 것
- 이전에는 대문자로 사용
- 2019년 이전에 나온 책들의 소스에러의 대부분은 이부분
//열거형 상수 정의
enum Comm : Int{
case SK = 1
case LG = 9
}
var x : Comm = Comm.SK
print(x)
x = .LG
print(x)
//Apple에서 열거형 상수는 전부 내부 클래스형태
//iOS Framework를 사용하다가 매개변수가 ?.?로 되어있으면 이건 전부 열거형 상수
**protocol
=> 자바의 인터페이스와 유사한 개념
- 자바의 인터페이스가 Protocol을 가져온 개념
=> 공통으로 구현해야 할 기능 목록을 가진것
=> 메소드와 속성, init의 선언만 포함할 수 있음
1. 속성의 경우
- var 속성명 : 자료형{get, set}
2. 메소드의 경우
- func 메소드명(매개변수)
3. init
- init(매개변수)
4. 클래스에서 conform
Class 클래스명 : 프로토콜명 나열{
}
=> 여러개를 나열하고자 하는 경우 ,로 구분
=> 프로토콜의 모든 요소를 전부 구현해야 함
5. 선택적 구현
=> 메소드나 프로퍼티 앞에 @objc optional 추가해주면 됨
- 이렇게 만들어진 프로토콜을 confirm하는 클래스는 클래 앞에 @objc를 추가하거나 Objective-C의 클래스로부터 상속 받아야 함
//프로토콜
@objc protocol MediaPlayer{
//필수 구현 메소드
func play()
func stop()
//선택적 구현 메소드
@objc optional func pause()
}
//프로토콜을 구현한 클래스
//이 클래스는 NSObject로 상속받아서 @objc를 생략
class VideoMediaPlayer : MediaPlayer{
func play() {
print("재생")
}
func stop() {
print("중지")
}
}
6. iOS에서는 프로토콜의 이름을 공통된 방법으로 사용
- 클래스명 DataSource : 데이터 출력을 위한 메소드를 소유한 프로토콜(필수 메소드 존재)
- 클래스명 Delegate : 이벤트 처리를 위한 메소드를 소유한 프로토콜(전부 선택적 구현)
**Extension
=> 클래스의 기능을 확장하는 개념
=> 이전에는 Category라고 함
extension 기존클래스명{
속성
메소드
}
=> 기존 클래스에 속성과 메소드가 추가(현재 프로젝트에서만 적용)
=> 하나의 프로젝트에서 추가를 했더라도 다른 프로젝트에서는 영향이 없음
=> protocol을 conform 할때 클래스에 직접 메소드를 구현하기 보다는 extension을 이용하여 구현하는 경우가 많음
=> protocol의 메소드를 클래스에 직접 구현시, 이 클래스에서 만들어진 것인지 protocol에 있는 메소드를 conform한 것인지 구별이 되
지 않아 extension을 이용하여 구현
**Swift에서 제공하는 자료구조 클래스
1. 종류
=> Array : 배열, 리스트의 개념으로 동작, Double Linked List 구조
=> Set : 중복되지 않도록 해싱하여 데이터를 저장하는 자료구조
=> Dictionary : Key와 Value를 쌍으로 저장하는 자료구조
=> Tuple : 데이터의 모임 - DTO의 성격
=> String : Character의 모임
=> Tuple을 제외하고는 동일한 자료형의 모임
- 여러 자료형을 저장하고자 하면 Any, AnyObject를 이용
=> Objective-C에는 Tuple을 제외한 자료형의 클래스가 존재
- NSArray, NSSet, NSDictionaray, NSString : 변경이 불가능한 자료형
- NSMutableArray, NSMutableSet, NSMutableDictionary, NSMutableString : 변경이 가능한 자료형
2. String
=> String은 구조체 - 값의 모임
=> =로 대입하면 데이터를 복제하여 대입
=> +와 +=이 재정의 되어있어 다른 문자열과 결합 가능
- append 메소드를 이용하여 이어붙이기 가능
=> 데이터의 모임이므로 for~in을 이용하여 하나의 문자 단위로 접근 가능
=> 문자열 템플릿(보간) 기능을 소유 : 다른 변수의 값을 문자열 상수 안에 삽입하여 하나의 문자열을 만드는 것이 가능
=> ”\u{유니코드}”를 이용해서 문자열 생성하는 것이 가능
=> count 속성으로 문자열 개수 파악 가능 : swift4에서 제공되는 문법
=> 문자열 크기 비교를 >, < 로 가능
//문자열 변수 생성
var str : String = "Swift String"
//문자열을 추가
str += "\u{1F496}"
print(str)
//문자열 크기 비교를 연산자를 이용해서 가능
var str1 : String = "ABCD"
var str2 : String = "abcd"
print(str1 > str2)
//struct 는 값의 형태이고 class는 참조의 형태
var str3 = str1
//값을 복사했기 때문에 복사본에서 작업을 수행해도 원본에는
//영향이 없습니다.
str3 = "EFGH"
//Swift에서는 String을 Character의 모임으로 보기 때문에
//이터레이터를 접근이 가능
for imsi in str1{
print(imsi)
}
3. Array
=> 배열, 동적인 배열이라서 Double Linked List 구조로 동작
1) 배열의 생성
=> 정적 생성 : var or let 배열명 : [자료형] = [데이터 나열]
=> 동적 생성 : var or let 배열명 = [자료형]()
2) 배열에 데이터를 추가
=> 마지막에 데이터를 추가 : append(데이터)
=> 중간에 추가 : insert(데이터, at: 위치)
=> +연산자를 이용하여 다른 배열 추가 가능
3) 배열의 데이터를 순서대로 순회
=> 빠른 열거(이터레이터)이용
for 임시변수 in 배열명{
임시변수를 이용한 데이터의 순차적인 접근
}
=> 직접 순서대로 접근
- count 속성을 이용하면 데이터의 개수를 알수 있음
- [인덱스]를 이용시 특정 인덱스에 해당하는 데이터에 접근 가능, 인덱스는 0부터 count-1까지
var idx : Int = 0
while(idx < 배열.count){
배열[idx]
idx = idx+1
}
4) 배열의 특정번째 데이터를 가져오는 것
=> 배열[idx]
=> 배열[시작인덱스...종료인덱스] : 범위내의 데이터를 가져오기 - slicing
5) 배열의 데이터를 정렬
=> Array.sorted()를 호출시 오름차순 정렬 가능 : 배열의 각 요소가 되는 데이터가 >가 사용가능해야 함
=> >가 없는 경우 함수를 생성하여 대입 : 이 함수는 2개의 매개변수를 가지고 Bool을 리턴해야 함
6) 배열의 전체 데이터를 확인
=> 배열명을 print 메소드에 대입하면 description이라는 속성을 호출하여 각 요소의 description을 []로 묶어서 출력
=> Java에서는 toString을 이용했지만 swift에서는 description이라는 속성 사용
=> Swift에서 toString을 사용하고자 하면 description이라는 프로퍼티를 오버라이딩 하면 됨
//배열 생성
//기존 데이터를 가지고 배열을 생성
var names:[String] = ["을지문덕", "척준경", "남이"]
//기존 데이터가 없는 경우
var songs:[String] = [String]()
songs.append("혼자가 아닌 나") //마지막에 데이터를 추가
songs.insert("나의 20년", at: 0) //첫번째에 데이터를 추가
//배열의 데이터 확인
print(names)
//배열의 데이터 정렬
names.sort() // sort는 자신의 데이터를 정렬
//sorted()는 정렬한 결과를 리턴
print(names)
//sort 함수의 by라는 매개변수에 2개의 매개변수를 가지고
//Bool을 리턴하는 함수를 대입하면 함수를 가지고 비교해서
//데이터를 정렬해줍니다.
//함수를 생성해서 대입
/*
func mycompare(str1:String, str2:String) -> Bool{
return str1 > str2
}
names.sort(by:mycompare)
*/
//클로저를 이용한 정렬
/*
names.sort(by:{(str1:String, str2:String) -> Bool in return str1 > str2})
*/
//트레일링 클로저를 이용한 정렬
//함수가 마지막 매개변수인 경우 함수를 호출하는 구문 외부에
//클로저를 생성 - iOS의 샘플 코드가 대부분 이방식
names.sort(){(str1:String, str2:String) -> Bool in
return str1 > str2}
print(names)
7) 배열에 Map - Reduce Programming을 위한 함수
=> map: 하나의 매개변수와 리턴 타입을 갖는 함수를 대입
- 배열의 각 요소를 대입받아서 리턴하는 값의 배열로 리턴해주는 함수
- 데이터를 변환해주는 역할을 수행하는 함수
=> filter: 하나의 매개변수와 Bool 리턴 타입을 갖는 함수를 대입
- 배열의 각 요소를 대입받아서 true를 리턴하는 요소들의 배열로 리턴해주는 함수
- 데이터를 필터필해주는 역할을 수행하는 함수
=> reduce: 2개의 매개변수와 하나의 값을 리턴 타입으로 갖는 함수를 대입
- 첫번째 매개변수는 중간 결과이고 두번째 매개변수는 배열의 각 요소가 되서 집계를 수행해서 리턴하는 함수
4. Set
=> 데이터를 중복없이 저장하는 자료구조
=> 해싱을 이용해서 데이터를 저장
=> 터치를 처리하는 메소드에서 터치의 값을 가져오기 위한 정도로만 사용
=> 정적으로 만들 때 배열과 방법은 같은데 [자료형] 대신에 Set<자료형>
5.Tuple
=> 여러가지 종류의 데이터를 하나로 묶을 수 있는 자료형
=> 한 번 묶이면 수정이 불가능
=> 자료형 만들기
- (자료형, 자료형, …)
=> 데이터 만들기
- (값, 값, …)
=> 데이터 접근
- 튜플.인덱스
=> 데이터 앞에 이름을 부여하면 인덱스 대신에 이름으로도 접근 가능
=> 스위프트에서는 DTO별도로 잘 안만들고 튜플을 사용하는 것을 권장
//트레일링 클로저를 이용한 정렬
//함수가 마지막 매개변수인 경우 함수를 호출하는 구문 외부에
//클로저를 생성 - iOS의 샘플 코드가 대부분 이방식
names.sort(){(str1:String, str2:String) -> Bool in
return str1 > str2}
print(names)
//문자열 1개와 정수 1개를 저장하는 튜플을 생성
var user01 : (String, Int) = ("아이린", 31)
//전체 출력
print(user01)
//부분 출력
print(user01.0)
//튜플을 만들 때 각 항목에 이름을 부여해서 생성
//마치 DTO 클래스를 만들어서 사용하는 효과
var user02 : (name:String, age:Int) = (name:"배수지", age:27)
print(user02)
print(user02.name)
print(user02.age)
6. Dictionary
=> Key 와 Value를 쌍으로 저장하는 자료구조
1) 생성
- var 또는 let 변수명:[key의 자료형 : value의 자료형] = [key:value, key:value…]
- var 또는 let 변수명:Dictionary<key의 자료형 : value의 자료형> = [:]
=> key의 자료형은 모든 자료형이 가능하지만 특별한 경우를 제외하고는 String
2) 데이터 개수는 count를 이용해서 찾아옴
3) 접근
=> 데이터 추가 및 갱신
- 디셔너리이름[키] = 값 //존재하는 키면 수정이고 존재하지 않는 키면 삽입 - upsert
=> 데이터를 리턴받을 때는 디셔너리이름[키]
- swift에서는 디셔너리로 데이터를 가져올 때는 Optional로 가져옴
- 사용을 할 때는 !를 이용해서 Optional을 해제하고 사용
=> 삭제는 nil을 대입해도 되고 removeValueForKey(키이름)
4) 모든 데이터 접근
=> Dictionary를 for-in을 이용해서 접근하면 모든 데이터를 튜플로 하나씩 리턴
=> keys 속성을 호출하면 모든 key의 값을 리턴
**예외처리
do{
try{
예외가 발생할 가능성이 있는 코드
}
catch 예외이름{
예외가 발생했을 때 사용할 코드
}
catch 예외이름{
예외가 발생했을 때 사용할 코드
}
..
}
=> 이전 API에서 예외처리를 강제하는 경우에는 예외처리 구문을 사용해야 하는데 try! 을 앞에 붙이면 예외처리를 하지 않아도 됨
**defer
=> defer{내용} 을 사용하면 위치에 상관없이 블럭이 끝나면 호출
**Thread의 우선순위 설정
=> 1~10까지만 사용할 수 있도록 하고 싶음
=> 우선 순위를 int로 priority로 만들게 되면 1~10이외의 값을 설정한 경우 어떻게 할지
=> 자바
class Thread{
final static int ONE = 1;
final static int TEN = 10;
}
=> priority에는 final 상수를 대입하는 것을 권장
- setPriority(Thread.TEN) : 다른 정수를 대입할 수 있으므로 예외 발생 가능성이 있음
enum ThreadPriority : Int{
case one = 1,
cases TEN = 10
}
- ThreadPriority priority 이렇게 선언시 priority에는 ThreadPriority안에 있는 값만 대입가능(다른 값 대입하면 에러)
- priority = .ONE
'수업 정리' 카테고리의 다른 글
93일차 수업정리(Swift - UIView, Gesture, 이벤트 처리) (0) | 2020.08.17 |
---|---|
92일차 수업정리(swift - SDK) (0) | 2020.08.14 |
90일차 수업 정리(Swift - Function, 구조체, Class, Method) (0) | 2020.08.12 |
Swift 에러 정리 (1) | 2020.08.11 |
89일차 수업정리(Swift - 자료형, 변수, 제어문, 반복문, 함수) (0) | 2020.08.11 |