일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- Value Type Reference Type
- CarouselCollectionview
- 자료구조
- Reference Cycle
- Input Output
- 테이블뷰 나누기
- UIKit
- coremotion
- 롤케이크 자르기
- TableView Section
- 강한 참조 순환
- 면접을 위한 CS 전공 지식 노트 Tree
- NavigationSearchBar
- til
- tableview section별 다른 cell적용
- @escaping
- 면접을 위한 CS전공 지식 노트
- class struct
- 프로그래머스
- Carousel CollectionView
- CoreData
- Array vs Linked List
- TableView
- wil
- retain cycle
- ReferceCycle
- 양궁대회
- UserDefaults
- firebase
- SWIFT
- Today
- Total
목록SWIFT (31)
개발하는 동글 :]

지금 까지 MVVM을 사용하면서 Data Binding을 Observable Pattern을 이용해 왔었다 그리고 최근 공부를 시작한 RxSwift를 적용하며 이 RxSwift를 이용한 Data Binding의 방법 중 하나인 Input Output구조를 적용해 보자! 1. Input Output 구조를 사용할 뷰 모델의 protocol 만들기 Input과 Output구조를 거의 모든 Viewmodel에서 사용해 줄 것이니 이 구조를 프로토콜로 만들어 준다 이 구조를 통해 컨트롤러에서 transform 메서드를 이용하여 Output을 이용해 바인딩을 하자! 2. ViewModel에서 Input과 Output의 요소를 만들고 어떻게 Input을 변환하여 Output으로 전달할 것인지를 정의 ViewMode..

1. 왜 dismiss후 present 가 필요 할까? 지금 구현한 LockScreen ViewController는 비밀번호가 일치 할 때 TargetViewController를 띄워주는 기능을 하고 있다. 이렇게 작동하게 될 때 NavigationController에 쌓이는 컨트롤러는 아래와 같다 여기서 문제가 발생하였다. LockScreen ViewController는 메모리에 올라와있어 불필요한 메모리와 이 후 뷰에서 접근이 가능한 상태가 되는 문제가 발생한다 그렇기에 비밀번호가 일치해서 다음 화면으로 넘어갈 때 LockScreenViewController를 dismiss한 후 targetViewController를 present하는 방법이 필요하다. 2. 어떠한 방법으로 해결할 수 있을까? 2.1..
1. 함수명으로 정확히 기능을 구별하여 구현하기 먼저 로그인 및 회원가입에 대한 정보를 전달해 주는 LoginResult 구조체를 만들어 주자. struct LoginResult { var isSuccess: Bool let email: String var errorMessage: String? } 그 후 Firebase에서 제공하는 메서드를 통해 각각 로그인과 회원가입에 대한 메서드를 만들어 준다. import Foundation import FirebaseCore import FirebaseAuth struct LoginManager { func trySignUp(email:String, password: String, completion: @escaping (LoginResult) -> Void) ..

1. FireBase 연결하기 1.1 Firebase 프로젝트 생성하기 1.2 iOS 버튼을 눌러서 App 등록하기 1.3 app등록하기 1.4 SPM에서 FireBase 패키지 추가 1.5 GoogleService - Info 파일 추가 1.6 초기화 코드 추가 import UIKit import FirebaseCore @main class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { FirebaseApp.c..

1. 프로토콜 제약 func testFunc(num1:T, num2:T) -> Bool{ return num1 == num2 } testFunc(num1: 1, num2: 1) 이러한 제네릭 함수가 있다고 가정해 보자. 이 함수는 컴파일러에서 "Binary operator '==' cannot be applied to two 'T' operands"라는 에러를 알려준다 즉 이진 연산자 == 은 T라는 것에 적용할 수 없다는 것이다. 왜 이런 일이 발생할까? T는 Equatable 프로토콜을 채택하고 있지 않기 때문에 == 연산자를 사용할 수 없다. 그렇다면 문제를 해결하는 방법은 무엇일까? func testFunc(num1:T, num2:T) -> Bool{ return num1 == num2 } tes..

1. 문제 상황 개인과제를 진행하던 중 viewController가 deinit이 되지 않는 문제가 발생하였다. 무엇인가가 강한 참조순환이 되고 있어서 메모리에서 해제되지 않는 것이라고 판단하였다 그렇기에 처음으로 한 시도는 viewController을 사용하는 클로저에 모두 [weak self]를 붙이기 시작하였다. 그럼에도 viewController은 메모리에서 해제되지 않았기에 어떤 부분에서 강한 참조순환이 생기는지 찾기 시작하였다 2. 그래서 어디서 발생하는가? class ToDoListCell: UITableViewCell { var cellDelegate: ButtonTappedDelegate? } extension ToDoListViewController: UITableViewDelegate..
1. Generics(제네릭)이 해결하는 문제! 먼저 간단한 예시를 통해 알아보자! var num1 = 1 var num2 = 2 위와 같이 두 개의 변수가 있고 두 변수를 교환하는 함수를 작성해 보자. var doubleNum1 = 1.1 var doubleNum2 = 1.2 func swapTwoInts(_ a: inout Int, _ b: inout Int) { let tempA = a a = b b = tempA } swapTwoInts(&num1, &num2) func swapTwoDoubles(_ a: inout Double, _ b: inout Double) { let tempA = a a = b b = tempA } swapTwoInts(&num1, &num2) swapTwoDoubles(..

1. MVVM 양식에 맞게 코드를 적어보자! 아직은 아키텍처 패턴은 잘 모르겠지만 MVVM에 맞게 한 번 코드를 짜보자! 그럼 MVVM은 뭘까? MVVM 패턴을 사용하는 경우 앱은 다음 계층으로 나뉩니다. 모델 계층은 비즈니스 데이터를 나타내는 형식을 정의합니다. 여기에는 코어 앱 도메인을 모델링하는 데 필요한 모든 항목이 포함되며, 종종 코어 앱 논리가 포함됩니다. 이 계층은 뷰 및 뷰 모델 계층과는 완전히 별개이며, 클라우드에 부분적으로 상주하는 경우가 많습니다. 뷰 계층은 UI를 정의합니다. 태그에는 특정 UI 구성 요소와 다양한 뷰 모델 및 모델 멤버 간의 연결을 정의하는 데이터 바인딩이 포함되어 있습니다. 경우에 따라 코드 숨김 파일은 UI를 사용자 지정하거나 조작하는 데 필요한 추가 코드를 포..

1. 목표? 일단 구현한 후 코드를 이해하는 것을 목표로 CoreData를 사용해보자. 2. 구현 2.1 CoreData의 Model 만들기 먼저 새롭게 CoreData의 Data Model 파일을 만들어준 뒤 Entities를 새롭게 하나 만들어서 원하는 속성들을 만들어준다. 2.2 AppDelegate파일 수정 //AppDelegate // MARK: - Core Data stack lazy var persistentContainer: NSPersistentContainer = { let container = NSPersistentContainer(name: "MyToDoApp_3") container.loadPersistentStores(completionHandler: { (storeDescrip..

1. 왜 UIButton을 커스텀하게 되었는가? 위의 이미지처럼 버튼을 3번 사용하게 되는데 중복되는 코드들을 줄일 수 없을까?라는 고민에서 시작하게 되었다. 그 고민의 결과로 UIButton을 커스텀해보자는 생각을 하게 되었다. 2. 사용 전과 후 비교 func setUpCheckListButton(){ view.addSubview(checkListButton) checkListButton.setTitle("title", for: .normal) // 중복 checkListButton.setTitleColor(.link, for: .normal) // 중복 checkListButton.snp.makeConstraints { make in make.centerX.equalTo(view.snp.center..

1. 구현 영상 2. 구현 1. 사용할 이미지 배열, imageView, collectionView 생성 var imageDatas = [ UIImage(named: "image1"), UIImage(named: "image2"), UIImage(named: "image3"), UIImage(named: "image4"), UIImage(named: "image5"), UIImage(named: "image6"), UIImage(named: "image7") ] var imageView = UIImageView() let myCollectionView: UICollectionView = { let flowLayout = UICollectionViewFlowLayout() let collectionView..

1. DispatchQueue?공식문서의 내용을 살펴보면 DispatchQueue는 앱의 기본 스레드 또는 백그라운드 스레드에서 작업의 동기 또는 비동기 실행을 관리하는 Class이다. 이 것을 확인해 보기 위해 아래의 두 개의 메서드를 만들어서 확인해 보자.func shortWork(_ num:Int){ DispatchQueue.global().async { print("shortWork[\(num)]Start") print("1") print("2") print("3") print("4") print("5") print("shortWork[\(num)]End") } } func longWork(_ num:Int){ DispatchQueue.global().async { print("longWork[\..

1. 클로저의 강한 참조 순환은 왜 발생할까? class HTMLElement { let name: String let text: String? lazy var asHTML: () -> String = { if let text = self.text { return "\(text)" } else { return "" } } init(name: String, text: String? = nil) { self.name = name self.text = text } deinit { print("\(name) is being deinitialized") } } 해당 클래스는 name과 text, lazy asHTML 속성을 가지고 있다. 그리고 asHTML속성을 살펴보면 text에 따라 값을 반환하는 함수이다. ..

1. ScrollView 만들기 private let contentScrollView = UIScrollView() 1. 먼저 ScrollView 컴포넌트를 생성해 준다. private func setUpContentScrollView(){ view.addSubview(contentScrollView) contentScrollView.snp.makeConstraints{ make in make.edges.equalTo(view.safeAreaLayoutGuide) } } 2. 뷰에 addSubView를 해준 다음 스크롤 뷰의 상, 하, 좌, 우 제약을 잡아준다. 2. ContentView 만들기 private let contentView = UIView() 1. ContentView를 UIView로 생성..
import Foundation func solution(_ topping:[Int]) -> Int { var array1:[Int:Int] = [:] var array2:[Int:Int] = [:] var count = 0 for i in topping{ if array1[i] == nil{ array1[i] = 1 } else { array1[i]! += 1 } } for i in topping{ if array1[i]! == 1{ array1[i] = nil } else { array1[i]! -= 1 } if array2[i] == nil{ array2[i] = 1 } else { array2[i]! += 1 } if array1.keys.count == array2.keys.count{ coun..
TIL Result 타입의 내부 @frozen public enum Result { case success(Success) case failure(Failure) @inlinable public func map( _ transform: (Success) -> NewSuccess ) -> Result { switch self { case let .success(success): return .success(transform(success)) case let .failure(failure): return .failure(failure) } } @inlinable public func mapError( _ transform: (Failure) -> NewFailure ) -> Result { switch se..
1. Closure? Unnamed Closure와 Named Closure를 둘 다 포함 1.1 Named Closure, Unnamed Closure Named Closure : 평소와 같이 선언해 왔던 함수 func doSomething() { print("Somaker") } Unnamed Closure : 이름을 붙이지 않고 사용하는 함수 let closure = { print("Somaker") } 1.2 스위프트는 함수를 일급객체로 취급한다. 일급객체로 취급한다면? 함수를 변수에 할당할 수 있음 함수를 호출할 때 함수를 파라미터로 전달할 수 있음 함수에서 함수를 반환할 수 있음 2. Closure의 형태 {(Parameters) -> (Return Type) in 실행구문 return (Re..

Why? api사용을 연습해 보던 중 튜터님이 retain cycle이 생길 것 같다는 조언을 해주셔서 retain cycle이 뭔지 공부시작 TIL 1. Swift는 어떻게 메모리를 관리할까? Swift의 메모리는 대부분 ARC(automatic reference counting)가 관리해 준다. 기본적으로 클래스의 객체를 가리키는 각각의 reference(참조)는 강한 참조이다. 강한 참조가 있는 한 이 객체의 메모리는 해제되지 않을 것이다. 만일 객체에 대한 강한 참조가 존재하지 않는다면 이는 메모리에서 해제될 것이다. ARC - Swift의 메모리 사용량 추적 및 관리 시스템. - ARC는 더 이상 필요하지 않은 클래스 인스턴스를 자동으로 메모리에서 해제한다. import UIKit class T..
Why? api를 사용하여 데이터를 받아오는 과정 중 잘 이해가 되지 않는 문법을 발견함 TIL @escaping ? 클로저의 실행이 본래 함수를 벗어나서도 실행되도록 하는 키워드 Non-Escaping Closure func nonEscaping(closure: () -> () ){ closure() } 클로저가 실행되는 순서 클로저가 함수의 인자로 전달됨 함수 안에서 closure 가 실행됨 함수가 값을 반환하고 종료됨 메모리 함수내에서 단순하게 실행하고 종료하기 때문에 클로저를 힙영역이 아닌 일반 스택영역에 저장 Escaping Closure class ViewModel { var completionhandler: (() -> Void)? = nil func fetchData(completion:..

Why? memo app을 따라 만들어 보며 메모를 삭제하였을 때 하단의 메모 개수가 변경되지 않는 문제가 발생한 적이 있다 이러한 문제를 해결하는 과정으로는 해당 뷰의 viewWillAppear 메서드에 tableview와 collectionview, toolbar를 업데이트 및 다시 할당을 하니 문제를 해결 할 수 있었다. 그렇기에 viewWillAppear 메서드는 무엇이며 UIViewController에 어떠한 메서드와 프로퍼티가 있는지 확인해 봐야겠다는 생각이 들었다. override func viewWillAppear(_ animated: Bool) { // 화면이 새롭게 그려질 때마다 호출됨 myTableView.reloadData() myCollectionView.reloadData() s..