Pod install시 에러 발생 [ParserError – 767]

ParserError – 767: unexpected token at ‘ ‘ #10088

Pod 설치시 에러가 나면 곤란한 경우가 많다.
처음보는 에러가 하나 발생했다.
pod repos와 캐시를 클린해주면 해결이 된다.

해결방법은 다음과 같다.

rm -rf ~/.cocoapods/repos
pod cache clean --all
pod install
  • 참고 링크
  • https://github.com/CocoaPods/CocoaPods/issues/10088

[글 작성 중] Firebase 클라우드 메시지 시작하기

Firebase에서 제공하는 푸쉬를 적용해보자.
Pod을 사용할 것이며, 해당 가이드 링크는 참고링크(하단)에 적어놓았다.
https://firebase.google.com/docs/cloud-messaging/ios/client?authuser=0

Firebase에서 프로젝트를 설정하고, 푸쉬를 사용하기 위한 방법입니다.
프로젝트 설정등은 firebase 가이드를 따라 하는 방식을 권장합니다.
따라서 firebase를 XCode에 적용하고, 푸쉬가 오는것까지 확인하는 것을 목표로 작성된 문서입니다.

다음과 같이 Pod을 설정하고 설치한다.
Pod 설정은 가이드 문서를 참고하여 각자의 환경에 맞추어 설정한다.

# Uncomment the next line to define a global platform for your project
platform :ios, '9.0'


target 'SampleRxSwift' do
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks!


  # Pods for SampleRxSwift
  #pod 'RxSwift', '6.0.0-rc.1'
  #pod 'RxCocoa', '6.0.0-rc.1'
  # Add the Firebase pod for Google Analytics
  pod 'Firebase/Analytics'
  # Add the pod for Firebase Cloud Messaging
  pod 'Firebase/Messaging'




  target 'SampleRxSwiftTests' do
    inherit! :search_paths
    # Pods for testing


    # Add the Firebase pod for Google Analytics
    pod 'Firebase/Analytics'
    # Add the pod for Firebase Cloud Messaging
    pod 'Firebase/Messaging'


  end


  target 'SampleRxSwiftUITests' do
    # Pods for testing
    # Add the Firebase pod for Google Analytics
    pod 'Firebase/Analytics'
    # Add the pod for Firebase Cloud Messaging
    pod 'Firebase/Messaging'


  end


end

Pod 설치 및 사용법은 아래 링크를 참고. 또는 가이드 문서를 참고
http://magpiebros.com/wordpress/category/dev-story/ios-개발-이야기/cocoapods/

앱 실행부, AppDelegate 정당한 위치에 아래와 같은 같은 코드를 삽입한다.

class AppDelegate: UIResponder, UIApplicationDelegate, MessagingDelegate {
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        print("[AppDelegate] didFinishLaunchingWithOptions")
        FirebaseApp.configure()
        firebaseRegisterForRemoteNotifications(application)


        // 메시지 대리자 설정
        Messaging.messaging().delegate = self
        
        return true
    }

FCM관련 추가

// MARK:- FCM
extension AppDelegate {
    func getFCMToken() {
        print("[AppDelegate] getFCMToken")

        Messaging.messaging().token { token, error in
            if let error = error {
                print("Error fetching FCM registration token: \(error)")
            } else if let token = token {
                print("FCM registration token: \(token)")
                //            self.fcmRegTokenMessage.text  = "Remote FCM registration token: \(token)"
            }
        }
    }
    
    func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
        print("[AppDelegate] 파이어베이스 토큰: \(fcmToken)")
    }
    
    func firebaseRegisterForRemoteNotifications(_ application: UIApplication) {
        print("[AppDelegate] firebaseRegisterForRemoteNotifications")
        if #available(iOS 10.0, *) {
            // For iOS 10 display notification (sent via APNS)
            UNUserNotificationCenter.current().delegate = self
            
            let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
            UNUserNotificationCenter.current().requestAuthorization(
                options: authOptions,
                completionHandler: {_, _ in })
        } else {
            let settings: UIUserNotificationSettings =
                UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
            application.registerUserNotificationSettings(settings)
        }
        
        application.registerForRemoteNotifications()
    }
}

APNS 설정

// MARK:- APNS
extension AppDelegate {
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        print("[AppDelegate] 토큰 받음", deviceToken.description)
        Messaging.messaging().apnsToken = deviceToken
    }
    
    
    // 호출되지 않음. iOS 10 미만?
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
        print("[AppDelegate] didReceiveRemoteNotification - 알람 옴")
        // If you are receiving a notification message while your app is in the background,
        // this callback will not be fired till the user taps on the notification launching the application.
        // TODO: Handle data of notification
        
        // With swizzling disabled you must let Messaging know about the message, for Analytics
        // Messaging.messaging().appDidReceiveMessage(userInfo)
        
        // Print message ID.
        //      if let messageID = userInfo[gcmMessageIDKey] {
        //        print("Message ID: \(messageID)")
        //      }
        
        // Print full message.
        print(userInfo)
    }
    
    // 호출되지 않음. iOS 10 미만?
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
                     fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        print("[AppDelegate] didReceiveRemoteNotification - fetchCompletionHandler - 알람 옴")
        // If you are receiving a notification message while your app is in the background,
        // this callback will not be fired till the user taps on the notification launching the application.
        // TODO: Handle data of notification
        
        // With swizzling disabled you must let Messaging know about the message, for Analytics
        // Messaging.messaging().appDidReceiveMessage(userInfo)
        
        // Print message ID.
        //      if let messageID = userInfo[gcmMessageIDKey] {
        //        print("Message ID: \(messageID)")
        //      }
        
        // Print full message.
        print(userInfo)
        
        completionHandler(UIBackgroundFetchResult.newData)
    }
}


//
@available(iOS 10, *) 
extension AppDelegate : UNUserNotificationCenterDelegate {
    
    // Receive displayed notifications for iOS 10 devices.
    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                willPresent notification: UNNotification,
                                withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        print("[AppDelegate] UNUserNotificationCenterDelegate")

        let userInfo = notification.request.content.userInfo
        
        // With swizzling disabled you must let Messaging know about the message, for Analytics
        // Messaging.messaging().appDidReceiveMessage(userInfo)
        
        // Print message ID.
        //    if let messageID = userInfo[gcmMessageIDKey] {
        //      print("Message ID: \(messageID)")
        //    }
        
        // Print full message.
        print(userInfo)
        
        // Change this to your preferred presentation option
        completionHandler([[.alert, .sound]])
    }
    
    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                didReceive response: UNNotificationResponse,
                                withCompletionHandler completionHandler: @escaping () -> Void) {
        print("[AppDelegate] UNUserNotificationCenterDelegate")

        let userInfo = response.notification.request.content.userInfo
        // Print message ID.
        //    if let messageID = userInfo[gcmMessageIDKey] {
        //      print("Message ID: \(messageID)")
        //    }
        
        // With swizzling disabled you must let Messaging know about the message, for Analytics
        // Messaging.messaging().appDidReceiveMessage(userInfo)
        
        // Print full message.
        print(userInfo)
        
        completionHandler()
    }
}

이렇게 코드만 적어놓는것은 역시 도움이 되지 않는 글을 작성해 놓은것 같아 씁쓸한 마음이 남는다. 이것보다 좀더 도움도 되고 발전도 할 수 있는 글을 작성할 수 있도록 고민해보아야 겠다.

  • 참고 링크
  • https://firebase.google.com/docs/cloud-messaging/ios/client?authuser=0

[CocoaPods] 01. 기본 사용법

요즘(요즘이라기 보단.. 오래되었지만.. 쿨럭) 뭔가를 대충 쓰기 보다는 제대로 알고 써보고 싶다는 생각이 많아진다.
그래서 공부도 하고 레퍼런스도 남길겸, 글들을 정리해서 써보기로 마음먹었다.

“CocoaPods은 Swift와 Objective-C 코코아 프로젝트를 관리하는데 의존적으로 사용된다. 7만8천개 이상의 라이브러리가 존재하며, 이를 통해 만들어진 앱은 3백만개 이상이다. 코코아팟(CocoaPods)는 당신의 프로젝트를 우아하게 만드는데 도움이 될것이다.”라고 코코아팟 사이트에서는 알려주고 있다.

뭘 먼저 해봐야 할가? 설치 아니겠는가?
설치를 해보자.

sudo gem install cocoapods

뭐 명령어 한줄만 치면 자연스럽게 설치가 이루어진다.

이제 iOS 프로젝트 위치로 이동을 해주고 pod을 install해준다.
(‘당신의 프로젝트명’.xcodeproj 파일이 존재하는 위치여야 한다.)

cd /Users/magpiebros/Documents/dev/iOS/SampleRxSwift/SampleRxSwift
pod init

pod을 init하고 나면, Podfile이 생성된다.
아래와 같은 모양의 파일이 생성되었을 것이다.

# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'

target 'SampleRxSwift' do
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks!

  # Pods for SampleRxSwift

  target 'SampleRxSwiftTests' do
    inherit! :search_paths
    # Pods for testing
  end

  target 'SampleRxSwiftUITests' do
    # Pods for testing
  end

end

이제 # Pods for SampleRxSwift 등의 위치에 원하는 Pod을 설정해주고 install만 해주면 모든 준비가 끝이난다.

난 RxSwift를 설치할것이기 때문에 https://cocoapods.org/pods/RxSwift 에서 가이드 문서를 한번 읽어보고 진행할것이다.
다음과 같이 설정하면, 샘플앱에서 동작하는것이 모두 동작한다고 하니, 다음과 같이 설정해놓고 진행해보겠다.
(각 라이브러리마다 사용법은 다를수 있으니, 가이드 문서를 참고해야 한다.)

# Podfile
use_frameworks!

target 'YOUR_TARGET_NAME' do
    pod 'RxSwift', '6.0.0-rc.1'
    pod 'RxCocoa', '6.0.0-rc.1'
end

# RxTest and RxBlocking make the most sense in the context of unit/integration tests
target 'YOUR_TESTING_TARGET' do
    pod 'RxBlocking', '6.0.0-rc.1'
    pod 'RxTest', '6.0.0-rc.1'
end

이제 내 프로젝트에 있는 Podfile을 변경해보자.

# Uncomment the next line to define a global platform for your project
platform :ios, '9.0'

target 'SampleRxSwift' do
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks!

  # Pods for SampleRxSwift
  pod 'RxSwift', '6.0.0-rc.1'
  pod 'RxCocoa', '6.0.0-rc.1'

  target 'SampleRxSwiftTests' do
    inherit! :search_paths
    # Pods for testing
    pod 'RxBlocking', '6.0.0-rc.1'
    pod 'RxTest', '6.0.0-rc.1'
  end

  target 'SampleRxSwiftUITests' do
    # Pods for testing
    pod 'RxBlocking', '6.0.0-rc.1'
    pod 'RxTest', '6.0.0-rc.1'
  end

end

그리고 pod install을 하면 모든 준비는 끝이난다.
몇가지 경고들이 나타나는데, ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES 관련 에러등이 생긴다.

하지만 사용에는 무리가 없으니, 차차 더 깊은 Pod사용법을 정리해보겠다.
아.. 아직 RxSwift는 뭘 써야 좋을지를 정하지 못한 상태다.
한번 길을 잘못가면 되돌아 오기도 쉽지 않으니, 자세히 알아보고 시작하겠다.

  • 참고 사이트
  • https://cocoapods.org
  • https://cocoapods.org/pods/RxSwift