본문 바로가기

IOS

(11)
[Swift] 클래스와 구조체 중 무엇을 선택해야할까? 공식문서에서 알려주는 가이드라인 구조체와 클래스 중에서 선택하기 구조체와 클래스는 데이터를 저장하고, 앱의 작동을 모델링하기에 좋은 선택입니다. 하지만 둘의 공통점들로 인해 둘 중 무엇을 선택해야할 지 정하는 것은 어렵습니다. 앱에 새로운 데이터 타입을 생성하기 전에 아래의 사항들을 고려하여 구조체와 클래스 중 무엇으로 구현할지 결정하세요. 기본적으로 구조체를 사용하세요. (Use structures by default) 오브젝티브-C와 상호작용해야 한다면 Class를 사용하세요. 모델링하는 데이터의 ID(identify)를 제어해야 하는 경우 클래스를 사용하세요. 프로토콜과 함께 구조체를 사용하세요. 구조체에 프로토콜을 채택하여 구현을 공유하세요. 기본적으로 구조체를 사용하세요. 스위프트의 구조체는 다른 언어라면 클래스 안에서만 가능..
@Published 변수를 재사용하는 문제와 해결 앱에서 발생했던 버그 중 하나가 어떤 게시물에 좋아요를 눌렀을 때 피드에 있는 모든 게시물이 다 함께 좋아요가 눌리는 현상이었습니다. 문제의 원인을 찾아보니 각각의 게시물마다 @Published 변수를 같이 사용하고 있는 것이 문제였습니다. 모든 게시물 뷰가 load(onAppear)될 때 매번 해당 게시물을 현재 사용자가 좋아요를 눌렀는지 서버로부터 받아오지만 그 값을 모두가 공유하는 Published 변수에 담다보니 결국 다른 게시물들과 좋아요 상태를 공유하는 버그가 발생했습니다. 문제 발생 class LikeStore: ObservableObject { // 좋아요를 저장하는 배열 @Published var likes: [Like] = [] // likes를 서버에서 받아서 likes에 넣어주는 기..
[Swift] 함수의 재사용성을 높이기 위한 Protocol 도입 및 모델 추상화 Market Model과 MyNote Model이 분리되면서 생겼던 문제와 해결들 기존에는 마켓에 올라가는 노트와 마이 노트를 같은 모델로 사용했지만 앱의 볼륨이 커지면서 각각의 컬렉션마다 필요한 필드들이 조금씩 더 추가되거나 달라지기 시작했습니다. 따라서 우리 앱은 마켓에 쓰이는 모델과 마이노트에 쓰이는 모델을 분리했고, 해당 과정에서 몇몇 메서드들의 재사용성이 좋지 않아지는 문제가 발생했습니다. 즉, 각각 모델에 맞는 함수를 따로따로 만들어줘야 하는 문제가 발생했습니다. 이를 해결하기 위해 마켓 모델과 마이 노트 모델이 공통으로 갖고 있는 속성들을 한 곳에 모아 NoteProtocol을 만들어주었고, 두 모델을 ‘추상화’ 시켰습니다. 결과적으로, 두 가지 모델 타입을 모두 받을 수 있는 메서드를 만들..
CoreData MultiThreading과 Delete Rule 코데 사용시 겪었던 문제 저희 앱은 MultiPlatform 환경의 사용자 또는 MultiDevice 사용자를 위한 Data Migration 작업이 필요했다. 예를 들어, 사용자가 A기기에서 B기기로 사용 기기를 바꾼다면 저희 앱은 서버에 백업용으로 저장해왔던 해당 유저의 암기장 데이터들을 사용해서 재로그인 시 동기화 작업을 수행했습니다. 이 과정에서 서버에 있는 많은 Note와 그에 포함되어 있는 Word들을 불러오고 거의 동시에 그 데이터들을 코데에 저장하는 과정에서 지속적으로 CoreData에 저장시키지 못하고 누락되는 버그들이 생겼습니다. 찾았던 문제점들 NoteEntity와 WordEntity의 Relationship 설정이 1 : N 관계였는데 이 데이터들을 삭제하는 규칙(Delete Rul..
SwiftUI Property Wrapper (@StateObject, @ObservedObject, @EnvironmentObject) 차이점 및 코드 예시 SwiftUI에서 property wrapper는 view의 상태를 관리하는 데 사용됩니다. SwiftUI에서 객체를 관리하는 데 사용되는 주요 property wrapper는 @StateObject, @ObservedObject 및 @EnvironmentObject입니다. @StateObject @StateObject는 뷰 전체에서 사용 될 새 객체를 생성하는 데 사용됩니다. 객체는 한 번만 생성되며 뷰의 전체 수명주기 동안 유지됩니다. 이것은 뷰의 다른 부분에서 사용할 새 객체를 만들고자 할 때 유용합니다. struct ContentView: View { @StateObject var viewModel = ViewModel() var body: some View { Text(viewModel.name..
ios 앱 심사 과정 경험 (리젝 사유와 대응) 메모라이징 앱의 첫 번째 심사에서 리젝을 받았다. 그 이유는 크게 3가지 였으며 다행히 엄청 큰 볼륨의 수정이 필요하지 않아서 빠르게 다시 수정할 수 있었다. 지금보면 예상 가능했던 리젝도 있었고, 덕분에 새롭게 알게된 사항들도 있다. 리젝 사유 3가지 ‘Apple ID로 시작하기’라는 워딩이 사용자들에게 ID만으로도 로그인이 가능하다는 오해를 불러일으킬 수 있기 때문에 (Guideline 4.0 - Design) 회원가입 후 한번더 사용자 이름 or ID를 묻는 것은 좋지 않다. 이미 apple로그인 시 해당 데이터들을 받아올 수 있기 때문에 (Guideline 4.0 - Design) 앱 내에서 포인트가 존재하기 때문에 ‘유저가 포인트를 획득할 수 있는 방식들에 대한 설명’을 요구 (Guideline..
[Swift] 코테를 위한 문자 타입(String, Character) 문법, 메서드 총정리🧙‍♀️ (지속 업로드 예정) - String.count : 문자열의 글자수를 리턴 let str = "안 녕 하 세 요" str.count // 9 띄어쓰기 포함 - Array(String) : 한 글자씩 배열의 요소로 변환하여 리턴 (주의: 각 요소의 타입은 Character로 바뀜) let str = "안녕하세요" Array(str) //["안", "녕", "하", "세", "요"] let strArray = Array(str) //["안", "녕", "하", "세", "요"] type(of: strArray) // Array.Type -String[num] : num번째 글자를 리턴 X (swift에서는 해당 방법 불가) -> Array(str)[num] let str = "안녕하세요" Array(str)[3]//"세" - S..
[Swift] 범위연산자 서브스크립트([ ])에 범위연산자를 활용해서 편리하게 인덱스 접근해보기 var numbers: [Int] = [1, 2, 3, 4, 5] numbers[1..3] // [2, 3, 4] 범위연산자로 ~이상, ~이하 표현해보기 var num = 10 switch num { case 0...: // 0 이상 true case ...0: // 0 이하 false default: break }