일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- 백준
- view 이동
- Blockchain
- 알고리즘
- Mining
- Report
- PBFT
- 암호화폐
- 이더리움
- 재진입공격
- reentrancy
- 블록체인 기술
- DPOS
- ethereum
- Crash
- 블록체인
- .dsym
- Algorithm
- DEFI
- viewcontroller
- Xcode
- 분산원장
- 비트코인
- ios
- POS
- pow
- External Call
- solidity
- dsYM
- 프로그래머스
- Today
- Total
개발하기좋은날
Swift 문법 간단 정리 본문
- Nil == NULL 같은 의미
- Swift 에서는 nil은 optional 변수 이외에 사용할 수 없다
- NIL은 NULL 같이 pointer가 없다는걸 말하는게 아니라 value값이 없다는 뜻으로 사용 혼동 주의!
- 변수 선언 var,let
- Var = 수정가능한 변수
- Let = 수정불가능한 변수 수정하면 에러 const 같은거
- Var asmr : Double = 70
- : 같은경우는 명시적으로 자료형을 정해줄때 사용
- \() -> String 에 변수 합병
let appleSummary = "I have \(apples) apples." let fruitSummary = "I have \(apples + oranges) pieces of fruit." |
- 위와같이 문자열 안에 변수를 선언하는데 사용할수있음
- String 줄이 여러 개면 """ , """ 이렇게 사용한다
|
let quotation = """I said "I have \(apples) apples."And then I said "I have \(apples + oranges) pieces of fruit."""" |
- 출력
- print("hello world");
- 배열
-
var shoppingList = ["catfish", "water", "tulips"]
shoppingList[1] = "bottle of water" //지정된 인덱스 데이터 수정가능
var occupations = [
"Malcolm": "Captain",
"Kaylee": "Mechanic",
]
occupations["Jayne"] = "Public Relations" // map 형태 데이터를 추가하는 방법
- [ ] 사용하여 배열을 만듬
- shoppingList.append("blue paint")
- 데이터 삽입시 자동으로 배열의 크기가 증가 한다
- let emptyArray = [String]() // 일반 배열 선언
- let emptyDictionary = [String: Float]() // map 형태 배열 선언 시
- 빈 배열은 위와 같이 생성 한다
- if, , for - in, while, repeat -while
let individualScores = [75, 43, 103, 87, 12] var teamScore = 0 for score in individualScores { if score > 50 { teamScore += 3 } else { teamScore += 1 } } |
- If문은 별도의 () 사용하지않고, () 사용해도됨
- 언더바 (_) 활용
- If, for문에서 언더바를 활용 예를 들수가있다
- If 같은 경우 스위프트3 부터 시행되는 함수호출에서 사용되는데
- 기존의 함수 호출은 라벨을 별도로 지정하지않은경우는
-
1
2
3
4
//보통 함수 선언 시
func functions(name: String, age : Int) -> Void {}
// 호출 시
functions(name : "알통몬", age : 26)
- 위와 같이 사용합니다
- 라벨을 사용하는 경우는
-
1
2
3
func functions(first name : String, second age : Int) -> Void {}
functions(first : "알통몬", second : 26) 처럼 사용할 수 있습니다.
- 위와 같이 지정한 라벨을 사용하여 호출을 해야합니다
- 하지만 이런 라벨 사용이 귀찮거나 사용하고싶지 않다면 " _ " 사용하여 생략 할수있음
-
1
2
3
func functions(_ name : String, second age : Int) -> Void {}
functions("알통몬", second : 26)
- 위와 같이 생략하고 넣을수있습니다
- FOR 문에서 언더바는 인덱스를 생략 하고 단순하게 루프를 돌릴떄 사용 합니다
-
1
2
3
4
5
6
7
for _ in 0..<4 {
print(“hello”)
}
for index in 0..<4 {
print(“hello \(index)”)
}
- _ 는 for loop 에서 인덱스를 할당하지 않겠다는 의미로 사용 됩니다
- 출력 결과를 보면 _ 사용했을때 for문 그냥 단순하게 루프를 4번 돌릴때 사용하고
- 반대로 index for문은 그 값을 사용하여 for문을 이용하는걸 확인할수있습니다
- Optional Type
- TypeCasting or nil value 체크에 사용하는 형태
1 2 |
var optionalString: String = nil var optionalString: String? = nil |
- 1번째 출은 에러 , 두번째는 optional 선언하여 오류 x
-
1
2
3
var optionalString: String?
var optionalString2: String? = nil
// 두 값 모두 nil
- Ios 개발에서 nil 상당한 부분에서 다루기떄문에 주의 하자
- 위와 같이 명시하지않아도 nil로 자동으로 초기화
- TypeCasting
-
1
2
3
4
let possibleNumber = “123”
let convertedNumber = Int(possibleNumber)
print(convertedNumber)
// 출력 결과 : Optional(123)
- 변수 형태가 맞지않는경우 에러가 발생하지만 Optional Int <-> (int?) 형으로 선언하여 오류x
- Wrapping
- Optional 은 기본적으로 wrap 되어있는 상태이므로 nill인지 아니면 value가 초기화 되어있는지 wrap되어서 모르기떄문에
- 출력을 하더라도 value값을 바로 출력 하지 않는다
-
1
2
3
var optionalString: String? = “Hello”
print(optionalString)
// 출력 결과: Optional(“Hello”)
- 위 문제는 제대로 string으로 초기화 되었지만 출력할떄 hello 출력되는것이 아닌 optional("Hello") 출력된다
- Forced Unwrapping
- Wrapping된 변수가 확실히 nill 아닌경우 ! 를 사용하여 강제적으로 값을 출력시킬수있다
-
1
2
3
var optionalString: String? = “Hello”
print(optionalString!)
// 출력 결과: Hello
- 기본적으로 optional ! 선언시 에러는 발생하지 않지만 값을 출력하는 행위를 할시 에러가 발생
- Example
-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Square {
var sideLength: Double
init(sideLength: Double){
self.sideLength = sideLength
}
}
let optionalSquare1: Square? = Square(sideLength: 2.5)
let sideLength1 = optionalSquare1?.sideLength
let optionalSquare2: Square? = Square(sideLength: 2.5)
let sideLength2 = optionalSquare2!.sideLength
let optionalSquare3: Square! = Square(sideLength: 2.5)
let sideLength3 = optionalSquare3!.sideLength
print(optionalSquare1) // Optional(Square)
print(optionalSquare2!) // Optional(Square)
print(optionalSquare3) // Square
print(sideLength1) // Optional(2.5)
print(sideLength2) // 2.5
print(sideLength3) // 2.5
print(sideLength1!) // 2.5
print(sideLength2!) // error // ! 제거해야 2.5 출력
print(sideLength3!) // error // ! 제거해야 2.5 출력
- Nil - coalescing operator
- 값이 nil인 경우 다른 변수로 초기화시킬때 사용한다 기호는 -> ??
-
1
2
3
a ?? b
a != nil ? a! : b
// (true/false ? a:b 구조)
- Optional Binding ( if let 변수 = 옵셔널 값 { ... } == if case let 변수? = 옵셔널 값 )
- 변수타입이 nil아닌경우 변수로 바인딩하여 그값을 사용할수있는 조건문 + 지역 변수여서 괄호 밖에서 사용할수없음;
- 기능은 nil 체크와 nil 아닐경우 새로운 변수 생성 을 한줄로 가능!
- Let 대신 var로 사용도 할수있음
-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Optional type으로 선언한 myNumber
let myNumber: Int? = 1234
if let actualNumber = myNumber {
print(“\(myNumber)은 실제로 \(actualNumber)입니다.”)
}
else {
print(“\(myNumber)는 변환될 수 없습니다.”)
}
// 출력 결과 : Optional(1234)은 실제로 1234입니다.
// {} 밖에서는 사용할수없다 ㅠ
print(actualNumber) // error
if let firstNumber = Int("4"), let secondNumber = Int("42"), firstNumber < secondNumber && secondNumber < 100 {
print(“\(firstNumber) < \(secondNumber) < 100”)
}
// 출력 결과: 4 < 42 < 100
- SWITCH or IF
- Case 99…125 : 이렇게 범위 scope를 정할수도있음
- If case
- 이거 찾느라 고생좀 했네
- Switch case를 간편하게 쓰기위해서 만든 구문인데 예를들어
-
1
2
3
4
5
6
7
8
9
10
11
// 이구문은 case 20...30 범위안에 데이터 있는 경우 조건을 만족하여 {} 실행되는것이다
// 이걸 스위치 구문으로 풀었으면 아래와 같다
if case 20...30 = age {
// do stuff
}
switch age {
case 20...30:
// do stuff
default:break
}
- Case let
- 값 바인딩 패턴으로 패턴에 부합하는 값을 상수(let) or 변수(var) 이름에 바인딩 합니다
-
1
2
3
4
5
6
7
8
9
10
var point = (2,6)
// 포인터의 엘리멘트들을 let x,y 에 바인딩 한다
switch point {
case let (x, y) where y>5 :
print("The point is at (\(x), \(y)).")
default:
print("asdasdasd")
}
// Prints "The point is at (2, 6)."
- 간단하게 그냥 바인딩 하는 구조
- If Case let
- If case에 옵셔널 바인딩을 붙인 경우다
- 주어진 변수 y 값이 패턴 에 일치하는지를 확인하는 구문 으로 예를 들어
-
1
2
3
4
5
6
7
8
if case let x = y {
...
}
// 위 구문은 풀어서 쓰면 아래와 같습니다
switch y {
case let x: ...
default: ()
}
- WHERE ( ',' 로 대체가능하다 -> if case let(var) where 구문 사용할때만 이떄 where 사용하면 에러남)
- 특정 문법과 결합하여 조건을 추가하는 역할
- 패턴과 결합하여 조건을 추가, 타입에 대한 제약을 추가할때 사용
- 간단하게 if case let where 구문을 보자면
-
1
2
3
4
var age: Int = 1
if case let x = age, x<10 {
print("value 111 \(x) ")
}
- x에 바인딩하여 x 의 조건을 체크하고 x의 값을 활용하여 출력할수있음 x nil이면 에러는 나지는 않지만 다른값이 출력되니 주의
1 |
if case let x? = age, x<10 |
- Age 값에 optional 패턴 사용하여 nil 값인경우 에러나지않게 지나갈수있고 생략되고 프로그램이 정상적으로 호출됨
- For
- Stride
- FOR CASE LET … [WHERE]
-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
enum Media {
case book(title: String, author: String, year: Int)
case movie(title: String, director: String, year: Int)
case website(urlString: String)
}
let mediaList: [Media] = [
.book(title: "Harry Potter and the Philosopher's Stone", author: "J.K. Rowling", year: 1997),
.movie(title: "Harry Potter and the Philosopher's Stone", director: "Chris Columbus", year: 2001),
.book(title: "Harry Potter and the Chamber of Secrets", author: "J.K. Rowling", year: 1999),
.movie(title: "Harry Potter and the Chamber of Secrets", director: "Chris Columbus", year: 2002),
.book(title: "Harry Potter and the Prisoner of Azkaban", author: "J.K. Rowling", year: 1999),
.movie(title: "Harry Potter and the Prisoner of Azkaban", director: "Alfonso Cuarón", year: 2004),
.movie(title: "J.K. Rowling: A Year in the Life", director: "James Runcie", year: 2007),
.website(urlString: "https://en.wikipedia.org/wiki/List_of_Harry_Potter-related_topics")
]
print("Movies only:")
for case let Media.movie(t, a, y) in mediaList {
print(" \(a)")
}
// 변수로 사용하는건 title , director, year mediaList 에서 하나씩 받아오고 조건은 변수 director 값이 == string 과 조건이 일치하는 여부를 확인한다
print("Movies by C. Columbus only:")
for case let Media.movie(title, director, year) in mediaList where director == "Chris Columbus" {
print(" - \(title) (\(year))")
}
- 기본적으로 신텍스 흐름은 똑같다 기존의 신텍스 + for 신텍스 만 있는 느낌임
- FOR (KEY,VALUE) IN VAR
-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
let interestingNumbers = [
"Prime": [2, 3, 5, 7, 11, 13],
"Fibonacci": [1, 1, 2, 3, 5, 8],
"Square": [1, 4, 9, 16, 25],
]
var largest = 0
for (kind, numbers) in interestingNumbers {
for number in numbers {
if number > largest {
largest = number
}
print(kind,numbers)
}
}
print(largest) // Prints "25"
- Key, value 형태로 사용한다는 뜻
- Reapeat {} while () 이건 do while 이거랑 똑같음
- Fun 함수
- func greet(person: String, day: String) -> String { }
- -> 이후 반환값을 설정하는거임
- 마찬가지로 라벨은 생략이 가능하거나 붙여서 사용가능함
- func greet(_ person: String, on day: String) -> String { }
- greet("John", on: "Wednesday")
- 배열 을 인자로 받고 return 값으로 여러 개를 지정할수있다
func calculateStatistics(scores: [Int]) -> (min: Int, max: Int, sum: Int) { var min = scores[0] var max = scores[0] var sum = 0 //**// return (min, max, sum) } let statistics = calculateStatistics(scores: [5, 3, 100, 3, 9]) print(statistics.sum) // Prints "120" print(statistics.2) // Prints "120" |
- 함수안에 함수를 선언하여 중복할수있고 함수를 통해 또다른 중복? 방지할수있을거같은데?
-
1
2
3
4
5
6
7
8
9
func returnFifteen() -> Int {
var y = 10
func add() {
y += 5
}
add()
return y
}
print(returnFifteen()) // 15
- 반환값 == 파라미터 인자 형태가 같으면 호출할때 다른걸 쓸필요가없음.. ? 근데 이게 함수의 중복에서만 가능한 부분인듯
-
1
2
3
4
5
6
7
8
9
10
func makeIncrementer() -> ((Int) -> Int) // 반환값 형태가 이따구인데
{
func addOne(number: Int) -> Int
{
return 1 + number
}
return addOne // 여기서 따로 인자를 넣을 필요없이 addOne 파라미터와 makeIncrementer return 값이 같으니 별도의 선언은 안해도됨
}
var increment = makeIncrementer()
print(increment(7))
- 함수에서 함수를 파라미터로 전달할수있는 형태
-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
func hasAnyMatches(list: [Int], condition: (Int) -> Bool) -> Bool {
for item in list {
if condition(item) {
return true
}
}
return false
}
func lessThanTen(number: Int) -> Bool {
return number > 10
}
var numbers = [20, 19, 7, 12]
// 리스트 number, 함수 lessThanTen 인자로 넣어줌
// 만약 함수인자가 numver: int -> bool 이 아니라면 오류또는 실행이 안댐
print(hasAnyMatches(list: numbers, condition: lessThanTen))
- 클로저 란? 클로저의 형태
- 함수를 블록 모양으로 표현한것
- 클로저의 함수 매개변수, 반환타입 생략할수있고 클로저 코드가 한줄이라면 그 코드의 반환값 , 클로저 자신의 반환값등 알아서 유추한다
- 클로저의 기본 문법
{ (매개변수) -> 반환타입 in
실행 코드
}
- Cocoa Touch 클로저 매개변수가없는 경우 in 키워드를 생략할수있다
- 어렵다 다시 봐보자
- Object and Classes
-
1
2
3
4
5
6
7
8
9
class Shape {
var numberOfSides = 0
func simpleDescription() -> String {
return "A shape with \(numberOfSides) sides."
}
}
var shape = Shape()
shape.numberOfSides = 7
var shapeDescription = shape.simpleDescription()
- 기본적으로 클래스 생성 또는 호출 방법
-
1
2
3
init(name: String) {
self.name = name
}
- 생성자는 위와 같이
-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Square: NamedShape {
var sideLength: Double
init(sideLength: Double, name: String) {
self.sideLength = sideLength
super.init(name: name)
numberOfSides = 4
}
func area() -> Double {
return sideLength * sideLength
}
override func simpleDescription() -> String {
return "A square with sides of length \(sideLength)."
}
}
let test = Square(sideLength: 5.2, name: "my test square")
test.area()
test.simpleDescription()
- 상속하고 init 하고 호출
-
1
2
3
4
5
6
7
8
var perimeter: Double {
get {
return 3.0 * sideLength
}
set {
sideLength = newValue / 3.0
}
}
- Get/set 은 위와 같이 선언하여 사용할수있음 Set은 파라미터를 가질수있다
- Get/set 시 var perimeter 값을 직접 return 하게되면 에러가 발생한다 반드시 다른 변수에 get,set 할수있게 만들어야한다
- willSet, didSet
- willset은 변경 직전
- Didset은 변경 직후
- 라는 Event를 감지하여 해당 시점에 작업을 수행할수있는 기능을 지원한다
-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Account {
var balance: Int = 0 {
willSet(newValue) {
print("잔액: \(balance) -> \(newValue) 변경 예정")
}
didSet(oldValue) {
print("잔액: \(oldValue) -> \(balance) 변경 완료")
}
}
}
let test = Account()
test.balance = 500
test.balance = 300
/*
잔액: 0 -> 500 변경 예정
잔액: 0 -> 500 변경 완료
잔액: 500 -> 300 변경 예정
잔액: 500 -> 300 변경 완료
*/
- Enumerations and Structures
-
1
2
3
4
5
6
7
8
9
10
enum CompoassPoint: String {
// 열거 사례들의 raw value의 타입
case north // 물론 raw value를 지정하지 않아도 상관없다. 이 때는 "north"가 됨
case south="South", east="East", west="West"
}
let p = CompoassPoint.north
let p2 = CompoassPoint.south
print(p.rawValue) // "north"
print(p2.rawValue) // "South"
- 열거형은 rawValue를 지정할수도 안할수도있음
-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
enum Rank: Int {
case ace = 1
case two, three, four, five, six, seven, eight, nine, ten
case jack, queen, king
func simpleDescription() -> String {
switch self {
case .ace:
return "ace"
case .jack:
return "jack"
case .queen:
return "queen"
case .king:
return "king"
default:
return String(self.rawValue)
}
}
}
let ace = Rank.ace
let aceRawValue = ace.rawValue
let va = ace.simpleDescription()
print(ace) //jack ace
print(aceRawValue) //11 1
print(va) // jack ace
- 아래와 같은 switch 문도 작성할수있음
-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
enum ServerResponse {
case result(String, String)
case failure(String)
}
let success = ServerResponse.result("6:00 am", "8:09 pm")
let failure = ServerResponse.failure("Out of cheese.")
switch success {
case let .result(sunrise, sunset):
print("Sunrise is at \(sunrise) and sunset is at \(sunset).")
case let .failure(message):
print("Failure... \(message)")
}
- 간단한 구조체 형태 알고넘어가자 일단
-
1
2
3
4
5
6
7
8
9
struct Card {
var rank: Rank
var suit: Suit
func simpleDescription() -> String {
return "The \(rank.simpleDescription()) of \(suit.simpleDescription())"
}
}
let threeOfSpades = Card(rank: .three, suit: .spades)
let threeOfSpadesDescription = threeOfSpades.simpleDescription()
- Protocols and Extensions
- 인터페이스랑 같은 맥락
- 클래스, 구조체와 함꼐 사용
- 메소드,프로퍼티 구현을 약속함
- 정의
- protocol PROTOCOL_NAME { }
- 채택
- class CLASS_NAME: PROTOCOL_NAME {}
- 클래스 전용 프로토콜은 아래와 같이 명시
protocol MyProtocol: class {}
-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
protocol ExampleProtocol {
var simpleDescription: String { get }
mutating func adjust()
}
class SimpleClass: ExampleProtocol {
var simpleDescription: String = "A very simple class."
var anotherProperty: Int = 69105
func adjust() {
simpleDescription += " Now 100% adjusted."
}
}
struct SimpleStructure: ExampleProtocol {
var simpleDescription: String = "A simple structure"
mutating func adjust() {
simpleDescription += " (adjusted)"
}
}
- Mutating 은 클래스, 스트럭트 에서 자신의 변수 프로퍼티를 수정할떄 발생하는에러를 제거하는 역할을 한다
- Extensions
- 구조체, 클래스, 열거형, 포토콜 타입에 새로운 기능을 추가할수 있는 기능 !
기능을 추가하려는 타입의 구현된 소스 코드를 알지 못하거나 볼 수 없다 해도, 타입만 알고 있다면 그 타입의 기능을 확장할 수도 있습니다.
- 추가 할수 있는 기능은 아래와 같음
- 연산 타입 프로퍼티 / 연산 인스턴스 프로퍼티
- 타입 메서드 / 인스턴스 메서드
- 이니셜라이저
- 서브스크립트
- 중첩 타입
- 특정 프로토콜을 준수할 수 있도록 기능 추가
- 예를들어
-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
extension Int {
var isEven: Bool {
return self % 2 == 0
}
var isOdd: Bool {
return self % 2 == 1
}
}
print(1.isEven) // false
print(2.isEven) // true
print(1.isOdd) // true
print(2.isOdd) // false
var number: Int = 3
print(number.isEven) // false
print(number.isOdd) // true
number = 2
print(number.isEven) // true
print(number.isOdd) // false
- Int 연산자에 isEven, isOdd 등같은 옵션을 추가하여 사용할수있다
- 같은 방법으로 메서드도 추가할수있다 아래와 같다
-
1
2
3
4
5
6
7
8
9
10
11
extension Int {
func multiply(by n: Int) -> Int {
return self * n
}
}
print(3.multiply(by: 2)) // 6
print(4.multiply(by: 5)) // 20
var number: Int = 3
print(number.multiply(by: 2)) // 6
print(number.multiply(by: 3)) // 9
- Error Handling
- 에러의 표현은 다음과같이 표현할수있다
-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// throws
enum PrinterError: Error {
case outOfPaper
case noToner
case onFire
}
func send(job: Int, toPrinter printerName: String) throws -> String {
if printerName == "Never Has Toner" {
throw PrinterError.noToner
}
return "Job sent"
}
// do ~ catch 문
do {
let printerResponse = try send(job: 1440, toPrinter: "Gutenberg")
print(printerResponse)
} catch PrinterError.onFire {
print("I'll just put this over here, with the rest of the fire.")
} catch let printerError as PrinterError {
print("Printer error: \(printerError).")
} catch {
print(error)
}
- Generics
- <> 제네릭 타입은 똑같은듯
https://jusung.gitbook.io/the-swift-language-guide/language-guide/25-access-contr
참조
'iOS > Tip' 카테고리의 다른 글
GIT 다 계정 SSH 설정 방법 (0) | 2023.04.01 |
---|---|
간단하게 .Crash Report 정보 확인하기 (0) | 2021.02.02 |
iOS .dsym에 대하여 (0) | 2021.02.02 |
iOS 간단 UDID 확인 방법 (1) | 2021.01.11 |