[iOS] Firebase Realtime Database 에 데이터 넣어보기

이미지
[iOS] FirebaseDatabase 파이어 베이스를 이용해서 데이터 저장하고 읽어오기 앱을 만들다보니, 데이터를 저장하고 저장된 데이터를 읽어서 보여주어야 하는 상황에 놓이게 되었습니다. 처음에는 변수나 더미 데이터를 만들어서 저장하고 불러왔지만, 결국에는 서버를 셋팅 해야하나 라는 고민을하게 되었습니다. 그러다가 발견한 파이어 베이스의 기능 중 하나인 Database를 간단하게 사용한 방법에 대해 정리해 놓겠습니다. install 파이어 베이스를 사용하기 위해서는 패키지를 설치 해 줘야합니다. 공식 문서를 보고 설치하면 어렵지 않습니다. 귀찮으신 분들을 위해 간략히 적어놓자면, Xcode의 SwiftPackageManager를 사용해 https://github.com/firebase/firebase-ios-sdk.git 를 추가하면 됩니다. 그 중에서도 FirebaseDatabase 를 꼭 설치해주세요. Firebase에서 새 프로젝트를 만드신 후에 iOS프로젝트를 추가 해 줍니다. 설명을 따라 진행하면 어렵지 않게 완료할 수 있습니다. 핵심은 번들ID를 잘 입력 해주는 것과 GoogleService-Info.plist 파일을 잘 다운받아 내 프로젝트에 넣어주는 것 입니다. Data firebaseDatabase는 JSON 형식의 데이터를 지원합니다. 간단히 JSON을 설명 드리면, 키 - 밸류 로 이루어진 데이터 포맷입니다. 우리는 간단한 JSON형식의 데이터를 작성해 볼것 입니다. 예제 데이터는 아래와 같이 생겼습니다. { user { age : 31, married : false name : "hyunho" } } Data Write 데이터 베이스가 비어있으니 일단 쓰는 기능부터 구현해 보겠습니다. import Firebase let testItemsReference = Database.database().referen

[Xcode] 디버깅 입문

이미지
[Xcode] 디버깅 입문 Xcode 디버깅 입문 코딩을 하다가 버그를 발견하거나 내가 원하는 결과가 나오지 않을 때면, 프린트 문을 써서 문제를 해결하곤 했는데 디버깅 툴 이라는 것을 발견한 후로 잘 쓰면 생산성을 향상 시킬 수 있을 것 같아서 정리 해 놓습니다. Xcode에 있는 디버깅 도구를 활용해 버그를 잡아봅시다. BreakPoint 브레이크 포인트는 실행중인 앱을 일시정지 하는 포인트 입니다. 사용 법은 매우 간단합니다. Xcode 소스코드의 왼쪽에 있는 라인 넘버를 클릭하면 파란 화살표가 생깁니다. 브레이크 포인트가 생성된 것 입니다. 이제 앱을 실행시키면, 브레이크 포인트에서 앱이 일시정지 되는 것을 볼 수 있습니다. 다시 앱을 동작하게 하는 방법도 간단합니다. 디버깅 창 중간의 삼각형 모양의 화살표를 눌러주면 다시 실행됩니다. 만약 브레이크 포인투가 두개라면 다음 브레이크 포인트에서 일시정지합니다. 브레이크 포인트를 다시 한번 클릭하면, 비활성화됩니다. 토글 형태이기 때문에 활성화, 비 활성화 하면서 브레이크 포인트를 사용할 수 있습니다. 브레이크 포인트는 오른쪽으로 드래그 하면 제거됩니다. 위 아래 방향으로 드래그 해서 옮길 수 있습니다. 디버깅 창에서 브레이크 포인트와 같은 파란색 화실표 버튼을 누르면, 한번에 모든 브레이크 포인트를 활성화, 비활성화 시킬 수 있습니다. Xcode의 왼쪽 네비게이터에서 브레이크 포인트 모양의 아이콘을 누르면 현재 설정된 브레이크 포인트들을 한번에 볼 수 있습니다. 디버깅 중 일시 정지된 브레이크 포인트에서 현재 변수 상태를 확인할 수 있습니다. 가리키고 있는 브레이크 포인트에서 변수에 어떤 값이 할당되어있는지 확인 할 수 있습니다. 이 창을 통해 내가 기대하고 있는 값이 제대로 들어가 있는지 확인하면 문제를 해결하는데 큰 도움이 됩니다. Control flow 앱의 사용 흐름을 체크 하는데 모든 라인에 일일이 브레이크 포인트를 걸어주어

[swift] Type Method (class func vs static func)

이미지
[swift] Type Method instance vs class vs static 클래스를 사용할 때에 static이 붙은 메소드를 사용하지 못해서 문득 아 얘를 언제 쓰는지 모르고 있구나 라는 생각에 정리해 두겠습니다. func 라는 키워드는 함수를 만들 때 많이 들 보셨을 것이라고 생각합니다. 오늘은 이 앞에 붙는 키워드들의 종류와 그 이유에 대해 알아보고 정리하겠습니다. 아무것도 붙지 않음 func instanceFunc() {} class가 붙음 class func classFunc() {} static이 붙음 static func staticFunc() {} How to make Func 아무것도 붙지 않은 함수는 평범하게 아래와 같이 사용이 가능합니다. class Student { func instanceFunc(){ print("instance func leeo") } class func classFunc() { print("class func leeo") } static func staticFunc() { print("static func leeo") } } let student = Student() student.instanceFunc() Student.classFunc() Student.staticFunc() // instance func from Parents // class func from Parents // static func from Parents 그렇다면 다른 두 키워드 class , static 은 언제 쓰는 것이고 어떤 장점이 있는 걸까요? 이 두 키워드는 클래스가 만든 인스턴스에서 사용하는것이 아닌 클래스 자체에서 사용하는 메소드입니다. 이 두개를 타입 메소드라고 부르는데 어떤 의미냐 하면, 인스턴

[swift] if 문에서 콤마와 && 연산자의 차이점

이미지
[swift] if 문에서 콤마와 && 연산자의 차이점 코딩을 하다가 Bool? 타입의 변수에 true값이 왔는지를 체크하다가 우연히 찾게된 코드를 보고 이해하기 위해서 정리 해놓습니다. 원래 사용했던 코드는 아래와 같았습니다. let result: Bool? if let result = result { if result { print("result is true") } else { print("result is false") } } else { print("result is nil") } 옵셔널일 때 값이 있는지 없는지를 검증하고 나서 그 안의 값을 사용하는 코드를 짰었습니다. 하지만 실제로 false일 때의 경우에는 아무런 행동을 하지 않았기 때문에 else라인은 비어있었습니다. 논리 적으로 아래 코드와 같이 써서 사용할 수 있을 줄 알았는데 동작하지 않았습니다. if let result = result && result { print("result is true") } if let으로 옵셔널을 제거 해 준 후에 사용할 수 있기 때문입니다. 검색을 통해 찾아보니 이럴 때 comma를 이용해 코드를 명확하게 짤 수 있었습니다. let result: Bool? = false if let result = result , result { print("result is true") } else { print("result is nil or false") } 막상 짜 놓고 보니 &&와 comma가 왜 다른지 이 구문이 어떻게 동작하는지에 대해 잘 모르고 있었기에 정리 해 놓겠습니다. 공식 문서 의 if Statement 부분을 참고해보니 이런 내용이 있었습니다. if Stat

[git] git의 마지막 커밋 메시지 수정하기

이미지
[git] git의 마지막 커밋 메시지 수정하기 git을 쓰다가 보면 한참 커밋을 하고나서 푸쉬를 하고나니 의미없는 커밋 메시지가 많아서 커밋메시지를 위한 커밋 메시지를 커밋 하게되었습니다. 아무 의미 없는 커밋을 하나 늘리기는 싫어서 방법을 찾아보니 rebase를 쓰면 가능한 것을 찾았지만, 원래 기능이 아니기 때문에 다른 방법을 소개하려고 합니다. 아래와 같은 명령어를 입력합니다. git commit --amend 마지막 커밋 메시지가 뜨면서, 수정 후 저장할 수 있습니다. -m옵션을 주어 새로운 커밋 메시지를 바로 입력할 수 있습니다. git commit --amend -m "new message" push 하면 되지 않습니다. 왜냐하면 origin의 HEAD 보다 브랜치의 최신 커밋이 아니기 때문에 거절됩니다. 그러므로 우리는 강제로 push 해주어야 합니다. git push --force 하지만 이 때 주의해야 할 점이 있습니다. 누군가 이미 push 한 브랜치를 force push 하게 된다면, 같은 브랜치에 다른 이력이 쌓여 추후에 문제가 발생할 수 있습니다. force push 를 한다면 이렇게 꼬일 수 있는 상황에 대해서도 염두해 두어야 합니다.

[git] git의 upstream과 origin 헷갈리는 사람 손!

이미지
[git] git의 upstream과 origin git의 upstream과 origin upstream과 downstream 사전적인 의미를 파악해보면, upstream 이 상류, downstream 이 하류입니다. 물이 상류에서 하류로 흐르듯이 pull 하는 주최가 downstream 당하는 쪽이 upstream 입니다. 내 레포에서 다른 레포를 풀 해서 작업하고 있다면 다른 레포가 업스트림이 되겠군요! otherRepository(upstream) -> (git pull) myRepository(downstream) 이미지 출처 : https://aktiasolutions.com/upstream-kanban-business-agility/ upstream과 origin 그렇다면 업스트림과 오리진은 어떤 차이가 있는지 정리 하겠습니다. 보통은 다른 레포를 포크해서 내 레포를 만들어 놓고 내 레포를 클론, 풀 해서 작업합니다. 이때 가장 근본이 되는 레포를 upstream 이라고 부릅니다. 내가 fork해서 가져온 레포를 origin이라고 부릅니다. 그러므로 내가 로컬에 클론 해 놓고 작업할 때, origin/master에서 가져올지, upstream/master에서 가져와야 할지 생각해서 가져와야겠죠? otherRepository(upstream) -> (fork) myRepository(origin) otherRepository(upstream) -> (git pull) myRepository(local) myRepository(origin) -> (git pull) myRepository(local)

[swift] 클로져 개념 잡고 가기

이미지
[swift] 클로져(closures)_v2 함수라고 알고 있던 클로져를 공부하면서 기록합니다. 어느 순간 이해가 안되는 코드들이 클로져로 이루어져있다는 것을 알게된다음 정리와 적용과정이 필요하다는 것을 알고 정리해 놓습니다. 클로저란? 클로저 는 코드에 전달되어 사용할 수있는 독립적인 기능 블록입니다. Swift의 클로저는 C 및 Objective-C의 블록 및 다른 프로그래밍 언어의 람다와 유사합니다. 라는 정의가 공식문서에 적혀있습니다. 하지만 이 개념은 이해가 가지 않았고, 개인적으로는 이름이 없는 함수이고 축약을 위한 다른 규칙들이 있다라고 이해하고 있습니다. 클로저의 문법 함수의 생김새와 사용방법 let name = "hyunho" func printName() { print(name) } printName() // hyunho 클로져의 생김새 let name = "hyunho" let printName = { print(name) } printName() // hyunho 함수같이 생겨서 구조를 뜯어보았습니다. // 함수 func 함수이름(파라미터) -> 리턴타입 { (코드 블럭) } // 클로저 { (파라미터) -> 리턴타입 in (코드 블럭) } 클로져 축약과정 아래의 예시를 들어 함수를 사용하는 방법과 클로져의 사용을 정리해 보겠습니다. 기본설정 func squared(i: Int) -> Int{ i * i } squared(i: 5) // 25 let array = [1,2,3,4,5] squared 함수를 만들어 놓고, 5를 입력하면 25를 반환합니다. 리스트를 만들어서 하나씩 입력 해보겠습니다. 함수와 클로저 사용 // 함수를 매개변수로 전달 let arrayFunctionUsed = array.map(squared) print(arrayFunctionUsed) // [1