일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 29 | 30 | 31 |
- FlutterView MethodChannel
- 안드로이드 바로가기
- Swift flutterview
- Swift flutterviewcontroller
- native flutter view
- 스위프트 테이블 뷰 셀
- 안드로이드 에러
- 푸시 데이터 저장
- NotificationService Extension
- swift sms
- 안드로이드 앨범
- swift 문자
- 스위프트 푸시
- Flutter NativeView
- 스위프트 UserDefaults
- Flutter UIKitView MethodChannel
- 안드로이드 숏컷
- 노티피케이션 익스텐션
- swift autolayout
- 스위프트 웹뷰
- flutter rotate
- 플러터 뷰 컨트롤러
- 스위프트 카메라
- flutter 회전
- 스위프트
- 스위프트 앨범
- 앱 꺼졌을 때 푸시 데이터 저장
- 안드로이드 FCM
- 앱 백그라운드 푸시 데이터 저장
- silent push
- Today
- Total
Things take time
[SWIFT] 1일차 : 스위프트 기본 문법 본문
[SWIFT]
- swift online playground 검색 후 기본적인 스위프트 문법 테스트 가능
- 혹은 Xcode playground로 프로젝트 생성후 테스트 가능
- 도움말 혹은 용례를 살펴보려면 해당 함수 Alt키 누른 채로 클릭
- 1 ~ 6까지는 playground로 실습
1. 자료형
//: Playground - noun: a place where people can play // UIKit : ios의 네 개의 레이어(Core OS, Core Services, Media, Cocoa Touch)<p></p> // 코코아 터치라는 레이어을 포함하는 프레임워크를 import import UIKit // 변수 선언 및 할당, 할당 시 메모리 저장 및 타입 자동 설정, " 대신 ' 는 사용 불가 var str = "Hello, playground" // 출력 print(str + "~~") // 상수 선언 및 할당, 할당 시 이 후 변경 불가 let name = "겸님" // name = "겸" 불가 // :뒤에 오는 것은 타입, 타입을 따로 지정하지 않으면 컴파일러가 알아서 설정해 주게 됨 let name2: String = "겸" // 문자열 let lastName: Character = "김" // 문자 let name3 = "님" // 만약 타입을 따로 지정하지 않으면 컴파일러는 문자열로 인식, 즉 문자로 인식하고 싶다면 Character로 직접 할당해야 함 // 정수형, 최대 최소 값은 컴퓨터의 Cpu bit수에 따라 다르기에, 32bit사용시 64bit의 값보다 작게 나옴 // Int대신 Int32 Int64로 사용하는 것이 좋음, Int64로 선언 시 32bit Cput에서도 64bit수로 인식하게 됨 let age: Int = 38 let age2 = 38 let age3: Int64 = 38 print(Int.min) print(Int.max) // 실수형, 정확도를 위해 Float보다는 Double 권장 let pi = 3.141592 // Double, 타입을 따로 지정하지 않으면 컴파일러는 Double로 인식, 15자리 let pi2: Float = 3.141592 // Float, 6자리 // Boolean let isMan:Bool = true </p>
2. 사칙연산, 논리 연산
// 기본 사칙 연산 let num1 = 10 + 20 let num2 = 20 - 10 let num3 = 10 * 2 let num4 = 10 / 2 let num5 = 10 % 3 // 논리 연산자 : &&, ||, ! let b1: Bool = num4 > num5 let b2 = num1 >= num2 let b3 = num2 == num3 let b4 = num2 != num3 let b5 = b1 && b2 let b6 = b3 || b4 let b7 = !b3
3. 범위 연산
// 범위 연산자, 0부터 5까지 (0~5) for i in 0...5{ print(i) } // 0부터 5보다 작은 수까지 (0~4), in에 있는 값이 i로 대입이 되는 것 for i in 0..<5{ print(i) }4. 조건
// 조건문, 조건안에 ()은 생략 가능, 끝에 ;를 쓰면 한 라인에 여러 행을 출력하는 등의 작업을 할 수 있음 if num2 < num3 { //print안에 변수를 출력하려면 \(변수)로 사용함 print("num2값은 \(num2) num3값은 \(num3)"); print("그러므로") print("num2값이 num3값보다 작다") } else { print("num2값이 num3값보다 크다") }5. switch
5. 반복문// switch : break는 선택으로 필수가 아님, default 필수, fallthrough라는 문구를 삽입하면 case조건을 만족하지 않아도 다음 조건이 무조건 실행 됨 let score = 88 var grade = "" switch score { case 90...100: print("\(score)점") grade = "수" case 80...90: print("\(score)점") grade = "우" default: print("\(score)점") grade = "나머지" } switch grade { case "수", "우": print("수 혹은 우") default: print("나머지") }
var iii = 0 // for문의 _는 변수 혹은 상수가 들어가는 위치에 _를 넣고, 이 변수 부분을 무시하고 뒤의 조건 부분만 만족하면 돌게 되며, 변수 값을 in부분에서 변경할 수없음 for _ in 0..<10 { iii += 1 print(iii) } // 구구단, a를 3으로 선언하더라도 in에서 2부터 대입하므로 2단부터 출력 됨 var a = 3 for a in 2..<10 { for b in 1...9{ print("\(a) * \(b) = \(a*b)") } }6. print 줄바꿈
print("기본 줄 바꿈") print("줄 바꿈 없이 ", terminator:"") print("할 수 있음")
7. Array : Xcode 실행 후 macOS => command line tool, 아이폰용이 아니라 맥에서 돌아가는 프로그램 만들기로 실습
* Use Core Data : 폰 DB 사용 여부
// Foundation은 Core Service라는 레이어에 포함되어 있음(MacOS용) import Foundation print("Hello, World!") // 문자열 배열 var nameArray: Array= ["이종범", "선동렬", "김응룡", "양준혁", "박찬호"] nameArray.append("겸") // 마지막에 추가 nameArray.insert("용", at: 2) // 특정 위치에 있는 데이터 넣음(위치 뒤에 있는 데이터는 밀려남) nameArray.remove(at:0) // () 안은 Index nameArray.removeFirst() nameArray.removeLast() print(nameArray) print(nameArray[1]) nameArray[1] = "NEW" print(nameArray) print(nameArray.count) for name in nameArray{ print(name) } // 타입 상관 없는 배열 : Any var nameArray2: Array = ["이종범", "선동렬", "김응룡", "양준혁", "박찬호"] nameArray2[0] = 123 print(nameArray2) // 배열의 또 다른 선언 방법 : [] var iOSDeviceArray: [String] = ["아이폰", "아이패드"] // 2차원 배열 var iOSDeviceArray2: [[String]] = [["아이폰6", "아이폰7", "아이폰8"], ["아이패드3", "아이패드4"]] print(iOSDeviceArray2); print(iOSDeviceArray2.count) print(iOSDeviceArray2[0][1]) for arr in iOSDeviceArray2{ for innerArr in arr{ print(innerArr) } } // 할당되지 않은 배열 선언 var intArray: Array = [] print(intArray) print("빈 배열 여부 : \(intArray.isEmpty)") intArray.append(1) print(intArray) // 배열 합치기 : 앞 배열 뒤에 붙게 됨(append) var newArray = nameArray + iOSDeviceArray print(newArray) newArray.removeAll() print(newArray)
8. 집합
import Foundation print("Hello, World!") // 집합, set은 같은 항목이 중복된 값을 가지면 하나만 갖게 되며 들어가는 위치가 다름 var genres: Set= ["Classic", "Rock", "Balad"] genres.insert("Jazz") genres.insert("Jazz") genres.insert("Jazz") print(genres) genres.removeFirst() print(genres) var oddDigits: Set = [1, 3, 5, 7, 9] // 홀수 집합 var evenDigits: Set = [2, 4, 6, 8] // 짝수 집합 var primeDigits: Set = [2, 3, 5, 7] // 소수 집합 print(oddDigits.intersection(primeDigits)) // 교집합 print(oddDigits.intersection(primeDigits).sorted()) // 교집합 + 오름차순 정렬 print(oddDigits.union(evenDigits).sorted()) // 합집합 oddDigits.subtract(primeDigits) // 차집합, 리턴 값이 없음 print(oddDigits.sorted())
9. 튜플
import Foundation // return을 여러개 하기 위해 사용함 // 매개 변수 중 paramDescription은 생략가능하며, 이 때 호출은 usingParam: xx로 됨 func getTupleValue(paramDescription usingParam: Int) -> (String, Int, Bool, Array){ return ("겸", usingParam, true, ["겸", "님"]) } let (a, b, c, d) = getTupleValue(paramDescription: 88) print("\(a) & \(b)") // _로 된 것은 무시, 즉 값을 할당받지 않겠다는 의미 (88은 받지 않음) let (a2, _, c2, d2) = getTupleValue(paramDescription: 100)
10. 사전(Dictionary)
import Foundation print("Hello, World!") // key, value값으로 이루어지며 key값을 통해서만 접근이 가능함 var legDic: Dictionary= ["Human": 2, "Cat": 4] // dictionary 또 다른 선언 방법 var legDic2: [String: Int] = ["Human": 2, "Cat": 4] print(legDic["Human"]!) print(legDic2["Human"]!) // 추가 legDic["Tiger"] = 5 print(legDic) // 변경 legDic["Tiger"] = 7 print(legDic) // 특정 key 삭제 legDic.removeValue(forKey: "Tiger") // legDic["Tiger"] = nil /////// nil값을 넣으면 삭제와 마찬가지의 결과 print(legDic) // key, value 순회 for key in legDic.keys{ print(key) } for value in legDic.values{ print(value) } // 튜플 형식으로 받기 for (key,value) in legDic{ print("\(key) / \(value)") }
11. 열거형 : 상수로 이루어진 집합
import Foundation enum CompassPoint { case North case South case East case West } var direction = CompassPoint.South print(direction) // enum형 데이터로 선언한 direction은 한 번 선언 후 다시 사용할 때, .을 통해 enum안에 있는 데이터를 가져올 수 있음 direction = .East print(direction) // . == CompassPoint. switch direction{ case .North: print(direction) case CompassPoint.South: print(direction) case .East: print(direction) case .West: print(direction) } enum SomeItemType: Int{ case None = 10, Text = 20, String = 30, Bool } var type = SomeItemType.String print(type) print(type.rawValue) // 값이 지정되지 않은 Bool은 이전 값의 +1만큼 들어감 type = .Bool print(type) print(type.rawValue) enum DeviceType { case None case FeaturePhone(Bool) // true = 폴더, false = 슬라이드 case SmartPhone(String) // 장치 이름 문자열 case Tablet(String, Int) // 장치 이름, 버전 값 } var type1 = DeviceType.FeaturePhone(true) print(type1) var type2 = DeviceType.SmartPhone("아이폰") print(type2) var type3 = DeviceType.Tablet("아이패드", 10) print(type3) switch type3{ case .None: print("식별 불가") case .FeaturePhone(let isFolder): print("피쳐폰 : \(isFolder)") case .SmartPhone(let name): print("스마트폰 : \(name)") case .Tablet(let name, let version): print("태블릿 : \(name) / \(version)") }
12. Function, 함수
import Foundation // -> : Return value func sum(lhs: Int, rhs: Int) -> Int{ return lhs + rhs } print(sum(lhs:5, rhs:10)) // ... 개수에 제한을 두지 않음(,로 구분되는 배열) func sum2(param1: String, param2: Int...){ print(param1) for i in param2{ print(i) } } sum2(param1: "sum2", param2: 10,20,30)
13. Structure, 구조체 : Call by value (값 복사, 구조체 변수에서 구조체 내의 값을 변경해도 원래의 값은 변경 x(각 변수 당 다른 주소), 각 구조체 변수마다 메모리 별도 할당)
import Foundation struct MyInfo{ let name = "겸" var age = 30 func showInfo() -> String{ return "이름 : \(name), 나이 :\(age)" } } // 구조체 변수 var info = MyInfo()
var info2 = info // 복사 // 수정, let상수는 불가 info.age = 28 print(info.showInfo()) // 28 print(info2.showInfo()) // 30 (변경 안 됨)
14. Class, 클래스 : Call by reference (값 참조, 각 클래스 변수는 동일한 주소를 가리키며 각 변수 중 하나가 클래스안에 있는 값을 변경하면 실제 클래스 안의 값도 변경)
import Foundation class Animal{ init(){ print("Animal 생성자 호출") } init(n: String){ self.name = n print("Animal 생성자 호출, 이름 : \(self.name)") } func cry(){ print("빽빽") } var name: String = "동물" } var lion = Animal() var tiger = Animal(n: "호랑이") lion = tiger // 복사가 아닌 참조, 참조 후엔 각기 다른 메모리 할당이 아닌 동일한 주소를 가리키기때문에 값 자체가 변경 됨 print(tiger.name) // 호랑이 lion.name = "사자" print(tiger.name) // 호랑이가 아니라 사자가 나옴 (변경 됨) var etc = Animal() print(etc.name) // 동물 // 클래스 상속 class Bird: Animal{ override func cry(){ print("짹짹") } func superCry(){ super.cry() } } var bird = Bird() print(bird.name) // 동물 bird.cry() // 짹짹 bird.superCry() // 빽빽
15. Optional : 값이 있거나 혹은 없거나
import Foundation var optInt: Int? // 옵셔널 Int, 선언만하고 할당은 하지 않았지만 경고만 뜰 뿐, 에러는 아님(nil : 값을 알 수 없음) print(optInt) // print(optInt!) : 값 조차 할당되지 않았는데 !를 통해 확신했기 때문에 에러 발생 var optInt2: Int? = 7 print(optInt2) // 값이 없을 수도 있어서 Optional(7)로 리턴 print(optInt2!) // 개발자는 값이 있다고 확신한다면 !을 붙여서 값을 얻어냄 var optString: String? = "겸" print(optString) print(optString!) // optional 배열 var optArr: Array? // == optArr: [Double] // optional Dictionary var optDic: Dictionary ? // == optDic: [String: int] // ! 대신 값이 있으면 뽑고, 없으면 뽑지 않도록 하기 위해선 if let(var) = XXX로, unmapping var str = "10" if let j = Int(str){ print(j) } else{ print("형 변환 실패") } print(optString) // Optional("겸") 출력 if let s = optString{ print(s) // 겸 출력 }
16. Closure : 일회용 함수, Object-C에서는 Block, Java는 람다 함수, 함수 명이나 접근 제한자가 따로 없음
실습은 Single View 프로젝트로 실습, 버튼 하나를 만들고 Ctrl + 드래그로 해당 소스에 넣고 뷰 컨트롤러를 아래와 같이 수정하여 확인, 취소 버튼 생성
스위프트는 하나의 클래스에게만 상속이 가능하며, 다중상속은 불가, 대신 프로토콜이란 개념으로 여러 개를 상속받는 것처럼 할 수 있음 (프로토콜 = 인터페이스)
import UIKit class ViewController: UIViewController { // IBAction : 연결된 뷰가 가진 특정 컴포넌트와 연결되어 있다는 것 @IBAction func SendName(_ sender: UIButton) { print("버튼 누름") // 기본적인 다이얼로그 let alert = UIAlertController(title: "Closure", message: "버튼 클릭", preferredStyle: UIAlertControllerStyle.alert) // 다이얼로그에 버튼 추가 alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil)) // 취소 다이얼로그, handler에 들어가는 함수에 주의, Clousure양식 alert.addAction(UIAlertAction(title: "CANCEL", style: UIAlertActionStyle.cancel, handler: { (alert: UIAlertAction) -> Void in print("Cancel 버튼 클릭") })) self.show(alert, sender: nil) } }
17. 기본 앱 하나 만들기
- 레이블 하나와 버튼 연결, 버튼 연결 시 Action, 가운데의 TextField
- Outlet과 Action : Outlet은 옵셔널을 해제(!)하면서 해당 객체, 컴포넌트가 존재한다는 것, Action은 매개변수로 전달하는것이 있으며 특정 이벤트를 연결할 때 사용함
- 아래와 같은 디자인으로 제작
import UIKit class ViewController: UIViewController, UITextFieldDelegate { // TitleLabel이란 변수와 연결을해서, 코드에서 접근할 수 있게 함 @IBOutlet var TitleLabel: UILabel! @IBOutlet var userInputTextField: UITextField! // 클래스 객체, 뷰가 메모리로 로드되었을 때 override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. self.userInputTextField.delegate = self // 포커스 이동 및 키패드 올리기 self.userInputTextField.becomeFirstResponder() } @IBAction func SendName(_ sender: UIButton) { // Outlet으로 연결된 TitleLabel을 가져올 수 있음 self.TitleLabel.text = self.userInputTextField.text } // 텍스트필드에서 리턴(엔터)키 눌렀을 때 발동되는 함수ITextFieldDelegate의 프로토콜에서 이름만 명세된 함수를 구현화 하는 것(자바의 인터페이스처럼) func textFieldShouldReturn(_ textField: UITextField) -> Bool { // 키패드 내리기 self.userInputTextField.resignFirstResponder() return true } }
- 여기서 프로토콜의 개념(UITextFiledDelegate를 커맨드키 눌러서 확인해 볼 것)과 그 안에 명세된 textFieldShouldReturn을 구현하고, 텍스트 필드 자동 포커스 및 뷰 로드시 자동 키패드 올림, 그리고 엔터(리턴)키 입력 시 키패드 내리는 방법
- 선행으로 아울렛으로 보이는 컴포넌트들 연결 및 버튼 액션 연결
'iOS (교육)' 카테고리의 다른 글
[SWIFT] 6일차 : 스위프트 기본 앱 (0) | 2017.04.29 |
---|---|
[SWIFT] 5일차 : 스위프트 기본 앱 (0) | 2017.04.15 |
[SWIFT] 4일차 : 스위프트 기본 앱 (0) | 2017.04.08 |
[SWIFT] 3일차 : 스위프트 기본 앱 (3) | 2017.04.01 |
[SWIFT] 2일차 : 스위프트 기본 앱 (0) | 2017.03.25 |