DispatchQueue에서의 completion사용과 escaping을 쓰는 이유 + 쓰지 않는다면 어떻게 해야하는가?

|

개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.


DispatchQueue 에서는 completion

DispatchQueue 코드 안에서는 흔히 return을 해주지 못한다.
이에 대한 해결방안으로 completion을 사용해주면 된다.

예시는 아래와 같다.

func downloadJson(_ url: String, _ completion: @escaping(String?) -> Void) {
  DispatchQueue.global().async {
    let url = URL(string: url)!
    let data = try! Data(contentsOf: url)
    let json = String(data: data, encoding: .utf8)
    DispatchQueue.main.async {
      completion(json)
    }
  }
}

escaping이 없어도 에러가 나지 않으려면

func downloadJson(_ url: String, _ completion: ((String?) -> Void)?) { // code }

위와 같이 옵셔널이라면 에러가 나지 않는다. 그런데 escaping이 왜 필요한 걸까?

본 함수 downloadJson가 끝나고 실행되는 코드(: completion(json))이기에 escaping이라고 적어주는 것
본체 함수가 실행되고 나중에 실행되는 함수다. 라고 지정해주기 위해 적어주는 것!

그런데 옵셔널 함수인 경우에는 escaping이 디폴트다. 그래서 이때는 escaping을 안써줘도 되는 것!

git 사용하면서 발생한 에러 총정리 + 해결방안 및 저장소 복사하는 방법

|

개인적인 연습 내용을 정리한 글입니다.
더 좋은 방법이 있거나, 잘못된 부분이 있으면 편하게 의견 주세요. :)


Git 에러 그 시작….

그냥 개인적인 해결방법입니다. 참고를 하시되 전혀 스마트한 방법이 아님을 꼭 강조하겠습니다.

우선 나는 터미널에서 git만 사용했지 git-flow는 사용해보지 못했다.
사실 git을 쓰든 git-flow를 쓰든 큰 차이가 있는것도 아니고, git-flow도 조금만 찾아보면 사용방법이 무척 잘 정리되어있고 간단해서 그리 큰 어려움이 있지는 않았다. 다만 문제는 들어온 회사의 전 개발자가 git branch 정리를 제대로 해놓고 가지 않았던 것… 그것부터가 재앙의 시작이었다.

사실 문제를 해결한 지금 시점에서 그리 큰 문제는 아니었지만, 첫 개발회사를 다니게 된 나의 입장에서는 git fatal error가 뜰때마다 심장이 쪼그라드는 기분이었달까..?

사수로부터 전 개발자가 release 브래치를 finish하지 않았기 때문에 master, develop 브랜치에 병합을 해야한다고 말을 해주었다.
release 브랜치를 finish 하기만하면 자동으로 master, develop 브랜치에 병합된다는것을 알고 있었기에 자연스럽게 아래 코드를 작성하였다.

git flow release finish <해당 버전>

그러나 에러가 뚜둔

Branches 'release/0.4.0' and 'origin/release/0.4.0' have diverged.
And local branch 'release/0.4.0' is ahead of 'origin/release/0.4.0'.
Branches 'develop' and 'origin/develop' have diverged.
And local branch 'develop' is ahead of 'origin/develop'.
Fatal: Tag already exists and does not point to release branch 'release/0.4.0'

우선 첫 네줄은 간단하게 지금 release, develop 브랜치에 변동사항이 있었기에 git add와 commit 을 남겨주기만 하면 해결이 된다.
단 문제는 마지막 Fatal: Tag already exists and does not point to release branch 'release/0.4.0'
저 태그는 우선 내가 만들어준 태그는 아니었고, 이전에 만들어진 hotfix 0.4.1 을 의미하는데 이를 해결할 방법이 마땅치 않았다.

당시에 해결했던 방법으로는 태그를 업데이트 해보거나, 푸시해보거나 그런 방법이었는데 모든것은 다 무용지물!

git push --tags
git pull --tags
git push origin --tags
git push --tags -f
git fetch --tags

위 코드를 순서대로 진행하라는 의미는 아니고, 당시에 stackoverflow를 보며 찾아 실행했던 모든 명령어들을 그냥 적어놓은 것 뿐이당..
그러니 저 순서대로 참고하지는 말것!

여튼 그럼에도 불구하고 해결되지 않았고 머지를 하려해도 계속 충돌충돌
깃을 항상 혼자만 써와서 그런지(협업을 했다고 하더라도 히스토리 하나도 모른상태로 깃을 사용한적은 없기에..) 너무 어려웠다.
더군다나 개인 플젝도 아니고 회사 플젝이다보니 내가 잘못건들여서 망하면 어떡해! 하는 마음에..(쫄쫄보)

그래서 결국 내가 선택한 방법은 해당 프로젝트의 저장소를 내 저장소로 복사해와서 내 저장소 안에서 실행해보는것!

저장소 복사해보기

방식은 해당 블로그를 참고해서 보았다.. 제드님 정말 최고 » 참고블로그

  1. 터미널 내에서 폴더를 하나 만들어준다.
  2. 내가 만들어놓은 폴더에 해당 코드 작성 » git clone --mirror <복사할 저장소의 url>
  3. 복사된 저장소 파일로 들어가 내 저장소 주소 입력 » git remote set-url --push origin <내 저장소의 url>
  4. 그리고 push! » git push --mirror
  5. 제대로 내 저장소에 복사되었는 지 확인 » git remote -v

그런데 나는 저장소에 제대로 복사가 되었음에도 불구하고 git push --mirror를 하면 계속해서 에러가 발생했다.

요렇게..ㅠ 그래서 또 stackoverflow를 열심히 찾아보았다. » 참고한 stackoverflow
근데 사실 큰 방법을 얻어내지는 못했다. 그래서 일단..그래 저장소에 옮겨서 확인하는 것은 포기!
내 깃헙 저장소로 돌아와 conflict를 최대한으로 해결해보았지만, 너무 많은곳에서 conflict가 발생해서 웹상에서 해결하는것이 불가능하다고 하기에 깃헙에서 추천해준 방법을 사용해서 해결하려고 하였으나 이 방법 또한 터미널에서 거절당했다. 부들부들..

어떻게 해야할지 고민하다가 내린 결론은 그냥 다 merge를 시켜버리자.

깃 에러를 해결하는 과정에서 각각의 브랜치의 진행 상태를 어느정도 파악했었고, release에서 develop과 master에 병합을 하라고 했으니 현재 상태는 release가 가장 최신의 상태임을 확인할 수 있었다. (실제 코드상으로도 소스트리를 통해 본 결과에서도 master와 develop은 한참 뒤에 멈춰있었고, 이전 개발자는 release로 계속해서 개발을 진행했던 것으로 확인했다.)

더 나아가, 현재 git flow release finish 가 되지 않는 상황이니 수동으로 merge를 진행하는것이 가장 최선이라고 생각했다.
더 좋은 방법이 있다면 혹은 해결방법을 알고 있는 분이 계시다면 꼭 ! 알려주세요…. 정석적인 방법을 알고 싶습니다..

그래서 그냥 정말 수동으로 다 머지를 시켰다.
정말 다른 방법은 없고 release 브랜치로 들어가 pod install을 알맞게 맞춰서 한 다음 git add, commit을 진행하고
git checkout develop으로 develop 브랜치로 들어가 git merge release를 해주었다.

이후 develop브랜치에서 제대로 release버전이 병합된 것을 확인헀고, 여기서부터 다시 git flow feature를 통해 새로운 브랜치를 생성해 앞으로 개발을 해나갈 예정이다. 정석적인 방법도 아니고 아직 제대로 된 해결방법도 모르겠지만… 지금으로써는 이게 최선이었다. 초기 셋팅 너무나 빡쎄네용…

Remote push notification 시뮬레이터에서 실행해보기

|

개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.


Remote push notification

Xcode 11.4부터 시뮬레이터에서 Remote Push Notification의 시뮬레이션을 지원한다. 시뮬레이션을 하는 방법은 두가지가 있다.

  1. 시뮬레이터에 apns 파일을 직접 드래그
  2. CLI를 이용

시작

Remote Push Notification을 시뮬레이션 하기 위해서는 우선 사용자에게 푸시알림 사용 권한을 요청하고 허가를 받아야한다.
권한 요청을 위해 AppDelegate파일의 didFinishLaunchingWithOptions 델리게이트에 권한 요청 코드를 추가해줘야 한다.

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
   requestAuthorizationForRemotePushNotification()
   return true
}

// 사용자에게 푸시 권한을 요청
func requestAuthorizationForRemotePushNotification() {
    let current = UNUserNotificationCenter.current()
    current.requestAuthorization(options: [.alert, .sound, .badge]) { (granted, error) in
    	// granted가 true로 떨어지면 푸시를 받을 수 있다.
    }
}

위 코드 혹은 아래 코드를 작성해주면 된다. (둘 중 하나만)

let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound] UNUserNotificationCenter.current().requestAuthorization(options: authOptions) { (isAllowed, error) in
  if isAllowed { DispatchQueue.main.async(execute: { application.registerForRemoteNotifications() })
  }
}

코드 작성 후 앱을 실행하면 권한 요청 팝업이 뜨게 될텐데, 허용(Allow)을 선택해 Remote Push를 사용할 수 있도록 해준다.

1. 시뮬레이터에 apns 파일을 직접 드래그 하는 방법

apns 파일은 json 포맷의 확장자가 apns인 파일이다.
apns의 payload 형식을 따라 샘플 파일을 생성한다.

{
    "Simulator Target Bundle" : "App Bundle ID",
    "aps" : {  // Remote push notification 사용을 위해 지정된 payload
        "alert" : {
            "title" : "테스트입니다.",
            "body" : "테스트 푸시~",
        },
    },
}

해당 파일을 내 프로젝트 폴더 안에 test.apns로 저장하였다. 그리고 시뮬레이터에 직접 드래그를 해보면 된다!

2. CLI를 사용해보는 방법

터미널에서도 시뮬레이션을 할 수 있다.
시뮬레이션에는 xcrun 명령을 사용한다.

xcrun simctl push [사용 가능한 디바이스 identifier] [App Bundle ID] [APNS 파일명]
  1. 가능한 디바이스 확인하기

단순히 xcrun simctl list devices를 하게 되면 모든 시뮬레이터 기종이 나오게 되는데, 이때 시뮬레이터 상태가 Booted인 시뮬레이터 identifier를 골라주어야 한다. 아래 코드를 작성하면 현재 내가 실행중이고 사용가능한 시뮬레이터를 찾을 수 있다.

xcrun simctl list devices | grep Booted

그러고 아래의 코드를 작성해주자.

xcrun simctl push 169DEF1A-288A-46C8-846F-8EB6079FD00C [App Bundle ID] test.apns

그러면 정상적으로 작동하는 것을 볼 수 있을 것이다.

Build Success 했음에도 시뮬레이터가 돌아가지 않는 경우?

|

개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.


Build Success 했음에도 시뮬레이터가 돌아가지 않는 경우?

빌드가 성공적으로 되었음에도 불구하고(build success) 시뮬레이터가 작동하지 않는 경우가 있다.

해결 방법

  • [Product] > [Scheme] > [Edit Scheme] 혹은
  • [프로젝트] > [Edit Scheme]

위 방식으로 들어가서 [Run] > [Info] 에서 [Executable]에 none 이 되었는 지 확인
만약 none이라면 본인의 프로젝트를 선택해준다! 이후 close!

git reset --hard origin/master 한거 취소하기(git reflog)

|

개인적인 연습 내용을 정리한 글입니다.
더 좋은 방법이 있거나, 잘못된 부분이 있으면 편하게 의견 주세요. :)


문제상황

개발을 하던 중 대박 실수를 하나 했었다.

  • local에 있는 파일을 깃헙에 push하려고 하는데 reject가 되었다.
  • 이전에도 비슷한 충돌은 많아가지고 git conflict해결 요거 참고하며 진행하는순간
  • 초기 파일만 남은채 그냥 다 사라져버렸다. 아니지 초기파일도 아니고 그냥 텅빈 파일 이름들만 남아있었다….
  • 구글링하며 설명을 찾아보니
  • “만약, 로컬에 있는 모든 변경 내용과 확정본을 포기하려면 아래 명령으로 원격 저장소의 최신 이력을 가져오고, 로컬 master 브랜치가 저 이력을 가리키도록 할 수 있어요”
  • 즉, 내 로컬은 텅 비어있던 깃헙을 역 push 해버려 텅빈 파일들만 남아있게 되었다…

git reflog

ref는 reference를 의미한다 > reference log

  • 사진을 보면 우선 위에서부터 아래로 커밋이 진행된 것을 볼 수 있다.
  • 내가 뭐가 뭔지를 몰라서 reset이 좀 남발이 되어있는데
  • 여튼 53d8에 있어야 할 HEAD가 잘못사용한 reset으로 인해 1b31까지 갔던 것을 볼 수 있다

이때 git reset -hard HEAD@{몇번전의 행동} 명령어를 통해 각각의 커밋 id를 대체할 수 있다.

즉 나는 git reflog를 통해 본 HEAD{3}행동으로 돌아가야 하니까(현재 HEAD{1}에 있고)
git reset -hard HEAD@{3}이라는 명령어를 통해 커밋을 돌려놓았다.

즉 이 명령어를 통해 우리가 할 수 있는 일은 아래와 같다.

  1. 원하는 몇번째 전의 행동으로 해당 과정을 되돌려 놓거나
  2. reset으로 잘못 삭제한 커밋을 되살리기 위해 사용한다.