강의 - www.fastcampus.co.kr/dev_online_iosapp
깃허브 - github.com/FreeDeveloper97/iOS-Study-FastCompus
07. 스위프트 structure
" structure "
struct : 구조체 : 의미적으로 관계가 있는 것들을 묶어서 표현하는 방식
※ 구조체 사용전 구조 ※
// 문제: 가장 가까운 편의점 찾기
/*----------------------- struct 사용전 -------------------------*/
// 주어진 편의점 정보
let store1 = (x: 3, y: 5, name: "gs")
let store2 = (x: 4, y: 6, name: "seven")
let store3 = (x: 1, y: 7, name: "cu")
// 거리 구하는 함수
func distance(current: (x: Int, y: Int), target: (x: Int, y: Int)) -> Double {
// 피타고라스..
let distanceX = Double(target.x - current.x)
let distanceY = Double(target.y - current.y)
let distance = sqrt(distanceX * distanceX + distanceY * distanceY)
return distance
}
// 가장 가까운 편의점 프린트하는 함수
func printClosestStore(currentLocation:(x: Int, y: Int), stores:[(x: Int, y: Int, name: String)]) {
var closestStoreName = ""
var closestStoreDistance = Double.infinity
for store in stores {
let distanceToStore = distance(current: currentLocation, target: (x: store.x, y: store.y))
closestStoreDistance = min(distanceToStore, closestStoreDistance)
if closestStoreDistance == distanceToStore {
closestStoreName = store.name
}
}
print("Closest store: \(closestStoreName)")
}
// Stores Array 세팅, 현재 내 위치 세팅
let myLocation = (x: 2, y: 2)
let stores = [store1, store2, store3]
// printClosestStore 함수이용해서 현재 가장 가까운 스토어 출력하기
printClosestStore(currentLocation: myLocation, stores: stores)
※ 구조체 사용후 구조 ※
/*----------------------- struct 사용후 -------------------------*/
// Improve Code
// - make Location struct
struct Location {
let x: Int
let y: Int
}
// - make Store struct
struct Store {
let loc: Location
let name: String
}
// 주어진 편의점 정보
let store1_after = Store(loc: Location(x: 3, y: 5), name: "gs")
let store2_after = Store(loc: Location(x: 4, y: 6), name: "seven")
let store3_after = Store(loc: Location(x: 1, y: 7), name: "cu")
// 거리 구하는 함수
func distance_after(current: Location, target: Location) -> Double {
// 피타고라스..
let distanceX = Double(target.x - current.x)
let distanceY = Double(target.y - current.y)
let distance = sqrt(distanceX * distanceX + distanceY * distanceY)
return distance
}
// 가장 가까운 편의점 프린트하는 함수
func printClosestStore_after(currentLocation: Location, stores:[Store]) {
var closestStoreName = ""
var closestStoreDistance = Double.infinity
for store in stores {
let distanceToStore = distance_after(current: currentLocation, target: store.loc)
closestStoreDistance = min(distanceToStore, closestStoreDistance)
if closestStoreDistance == distanceToStore {
closestStoreName = store.name
}
}
print("Closest store: \(closestStoreName)")
}
// Stores Array 세팅, 현재 내 위치 세팅
let myLocation_after = Location(x: 2, y: 5)
let stores_after = [store1_after, store2_after, store3_after]
// printClosestStore 함수이용해서 현재 가장 가까운 스토어 출력하기
printClosestStore_after(currentLocation: myLocation_after, stores: stores_after)
- 의미있는 좌표들을 Location으로 묶었다
- 의미있는 좌표와 이름을 Store로 묶었다
※ 구조체 메소드 추가 구조 ※
/*----------------------- struct 메소드 추가 -------------------------*/
struct Store2 {
let loc: Location
let name: String
let deliveryRange = 2.0
func isDeliverable(userLoc: Location) -> Bool {
let distanceToStore = distance_after(current: userLoc, target: loc)
return distanceToStore <= deliveryRange
}
}
// 가장 가까운 편의점 프린트하는 함수
func printClosestStore_after2(currentLocation: Location, stores:[Store2]) {
var closestStoreName = ""
var closestStoreDistance = Double.infinity
//배송여부 추가
var isDeliverable = false
for store in stores {
let distanceToStore = distance_after(current: currentLocation, target: store.loc)
closestStoreDistance = min(distanceToStore, closestStoreDistance)
if closestStoreDistance == distanceToStore {
closestStoreName = store.name
//배송여부 확인
isDeliverable = store.isDeliverable(userLoc: currentLocation)
}
}
print("Closest store: \(closestStoreName), isDeliverable: \(isDeliverable)")
}
// 주어진 편의점 정보
let store1_after2 = Store2(loc: Location(x: 3, y: 5), name: "gs")
let store2_after2 = Store2(loc: Location(x: 4, y: 6), name: "seven")
let store3_after2 = Store2(loc: Location(x: 1, y: 7), name: "cu")
// Stores Array 세팅
let stores_after2 = [store1_after2, store2_after2, store3_after2]
// printClosestStore 함수이용해서 현재 가장 가까운 스토어 출력하기
printClosestStore_after2(currentLocation: myLocation_after, stores: stores_after2)
구조체와 연관이 있는 행동은 구조체 안에 method로 추가한다
" structure vs class "
structure : value 타입 / 값이 복사되어 할당된다 / Stack에 저장된다
class : reference 타입 / 값이 참조되는 형태이다 / Heap에 저장된다
/*----------------------- struct vs class -------------------------*/
struct PersonStruct {
var name: String
var age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
}
class PersonClass {
var name: String
var age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
}
var pStruct1 = PersonStruct(name: "Jason", age: 5)
var pStruct2 = pStruct1
pStruct2.name = "Hey"
let pClass1 = PersonClass(name: "Jason", age: 5)
let pClass2 = pClass1
pClass2.name = "Hey"
/* Struct는 값이 복사되었기 때문에 기존값에 변화가 없다 */
pStruct1.name //Jason
pStruct2.name //Hey
/* Class는 값을 참조하기 때문에 기존값과 동일하다 */
pClass1.name //Hey
pClass2.name //Hey
struct의 경우 값을 복사하기 때문에 해당 struct값만 변경되지만
class의 경우 참조하기 때문에 기존 class값 또한 변경된다
" structure - protocol "
※ protocol : 프로토콜 - 지켜야할 약속, 해야할 일들의 목록을 뜻 ※
description : Struct를 출력시 반환하는 내용을 정의
/* 도전과제 */
//1. 강의 이름, 강사 이름, 학생수를 가지는 struct 만들기 (Lecture)
/* protocol 프로토콜 사용 */
/* 지켜야할 약속, 해야할 일들의 목록 */
// CustomStringConvertible : print시 원하는 형태로 출력되게 설정
struct Lecture: CustomStringConvertible {
var description: String {
return "Title: \(name), Instructor: \(instructor)"
}
let name: String
let instructor: String
let studentsNumber: Int
}
let Lecture1 = Lecture(name: "iOSStudy", instructor: "FastCampus", studentsNumber: 500)
// 프로토콜 내용 출력
print(Lecture1)
" structure - parameter "
Struct를 parameter로 받는 func 예제
//2. 강의 array와 강사 이름을 받아서 해당 강사의 강의 이름을 출력하는 함수 만들기
func printLectureName(lects: [Lecture], instructor: String) {
//1. 일반적인 for문을 통한 방법
var result = ""
for lecture in lects {
if lecture.instructor == instructor {
result = lecture.name
}
}
print("--> Lecture Name : \(result)")
//2. closure, optional 사용한 방법
let lectureName = lects.first { lec in
return lec.instructor == instructor
}?.name ?? ""
print("--> Lecture Name : \(lectureName)")
}
//함수 실행
//3. 강의 3개를 만들고 강사 이름으로 강의 찾기
let Lecture1 = Lecture(name: "iOSStudy", instructor: "FastCampus", studentsNumber: 500)
let Lecture2 = Lecture(name: "iOS", instructor: "FC", studentsNumber: 500)
let Lecture3 = Lecture(name: "ios", instructor: "fc", studentsNumber: 500)
let Lectures = [Lecture1, Lecture2, Lecture3]
printLectureName(lects: Lectures, instructor: "FC")
" structure - property "
※ property : 프로퍼티 - 사용되는 data 값들을 의미 (일종의 변수) ※
1. Instance property 인스턴스 프로퍼티 : struct 내의 property에 해당되는 내용
stored property
- 변수에 저장되어 있는 값들
computed property
- stored property를 사용하여 계산된 새로운 값
/* properties 프로퍼티 : data들 */
/* stored property : 변수에 저장되어 있는 값 */
/* computed property : 직접 저장하지 않고, 저장된 정보를 이용해서 가공, 혹은 계산된 값을 제공할 때 사용 */
/* type property : 생성된 instance에 상관없이 struct의 타입 자체의 속성을 정하고 싶을 때 사용 */
struct Lecture: CustomStringConvertible {
//stored property : 값을 저장
let name: String
let instructor: String
let studentsNumber: Int
//computed property : 아래 정보들을 통해 계산된 값을 제공
var description: String {
return "Title: \(name), Instructor: \(instructor)"
}
}
※ get, set 함수를 통해 property의 반환, 수정 연산을 지정할 수 있다 ※
struct Person {
var firstName: String
var lastName: String
//computed property
var fullName: String {
get {
return "\(firstName) \(lastName)"
}
set {
if let firstName = newValue.components(separatedBy: " ").first {
self.firstName = firstName
}
if let lastName = newValue.components(separatedBy: " ").last {
self.lastName = lastName
}
}
}
}
lazy property
- stored property 처럼 struct가 생성될시에 생성되지 않고 변수에 접근시에 생성되는 property
- 최적화 관점에서 사용된다
- cost가 큰 변수의 경우 필요할때만 생성되겠금 할 때 사용된다
struct Person {
//stored property
var firstName: String
var lastName: String
//lazy property : 인스턴스값 사용시 실행된다
lazy var isPopular: Bool = {
if fullName == "Jay Park" {
return true
} else {
return false
}
}()
}
//struct 사용
var person = Person(firstName: "Jason", lastName: "Lee")
//lazy 프로퍼티 사용시에 생성
person.isPopular
2. type property 타입 프로퍼티 : struct 타입이름의 property에 해당되는 내용
type property
- static 키워드로 property를 만든다
struct Person {
//type property
static let isAlien: Bool = false
}
//Person 타입에 관한 프로퍼티값 사용
Person.isAlien
" structure - property observation "
observation을 통해 property가 사용되는 시점을 알 수 있다
/* observation : property가 바뀐 시점을 알 수 있다 */
struct Person {
//stored property : observation
var firstName: String {
//인스턴스값 접근 이전 실행된다
willSet {
print("willSet: \(firstName) --> \(newValue)")
}
//인스턴스값 접근 이후 실행된다
didSet {
print("didSet: \(oldValue) --> \(firstName)")
}
}
var lastName: String
}
※ willSet : newValue, 기존 property 값을 통해 새로운 값을 저장 전 수행된다
※ didSet : oldValue, 기존 property 값을 통해 새로운 값을 저장 후 수행된다
" structure - property vs method "
property로도, method로도 동일하게 수행할 수 있는 경우가 있다. 이런경우 아래와 같이 정리가 된다
간단한 경우 - property 사용 (간단하게 값을 접근, 반환하는 경우)
복잡한 경우 - method 사용 (좀더 복잡하게 값을 통해 연산처리과정 후 반환하는 경우)
/* property vs function*/
struct Person {
var firstName: String
var lastName: String
// property
var fullName: String {
return "\(firstName) \(lastName)"
}
//function
func fullName_f() -> String {
return "\(firstName) \(lastName)"
}
}
var person = Person(firstName: "Jason", lastName: "Lee")
// property 사용
person.fullName
// method 사용
person.fullName_f()
이런 간단한 값을 반환하는 경우는 property가 더 좋은 방법이 되겠다!
" structure - method "
method : 특정 연산을 수행하는 역할 (property 값들을 통해 연산)
mutating method : stored property 값을 변경하는 메소드
static func : struct 타입에 관한 메소드 (property 값들과 무관)
struct Lecture {
//stored property
var title: String
var maxStudents: Int = 10
var numOfRegistered: Int = 0
//method
func remainSeats() -> Int {
let remainSeats = maxStudents - numOfRegistered
return remainSeats
}
//struct 내에서 변수를 수정하는 메소드의 경우 mutating 키워드 필요
mutating func register() {
//등록된 학생수 증가시키기
numOfRegistered += 1
}
//type property
static let target: String = "Anybody want to learn something"
//type method
static func 소속학원이름() -> String {
return "패캠"
}
}
//method 사용
var lec = Lecture(title: "iOS Basic")
lec.remainSeats()
lec.register()
//type property, method 사용
Lecture.target
Lecture.소속학원이름()
" structure - extention "
기존에 만들어진 struct에 추가적인 property, 또는 method가 필요할 시에 사용된다
/* extension을 활용하여 만들어진 struct에 메소드를 추가할 수 있다 */
struct Math {
static func abs(value: Int) -> Int {
if value > 0 {
return value
} else {
return -value
}
}
}
Math.abs(value: -20)
위의 Math struct에 추가기능을 더할때 extention을 사용하면 된다
//만들어져있는 Math struct 에 새로운 함수 추가하기
extension Math {
static func square(value: Int) -> Int {
return value * value
}
static func half(value: Int) -> Int {
return value / 2
}
}
Math.square(value: 5)
Math.half(value: 20)
※ 애플이 기존에 만들어 놓은 struct의 경우도 역시 extension으로 기능을 추가할 수 있다 ※
//애플이 만들어 놓은 struct에 추가해서 사용할수도 있다
extension Int {
func square() -> Int {
return self * self
}
func half() -> Int {
return self / 2
}
}
var value: Int = 5
value.square()
value.half()
'iOS 개발자 > swift 기초' 카테고리의 다른 글
스위프트 기초7 (class, struct, override, upercast, downcast, init, convenience init) (0) | 2021.02.21 |
---|---|
스위프트 기초5 (collection, closure, first class type) (0) | 2021.02.15 |
스위프트 기초4 (collection, array, dictionary, set) (0) | 2021.02.15 |
스위프트 기초3 (function, parameter, overload, optional, binding, coalescing) (0) | 2021.02.13 |
스위프트 기초2 (while, repeat, for, switch) (0) | 2021.02.09 |