2016년 6월 9일 목요일

XCode swift "Command failed due to signal: Segmentation fault: 11 해결 방법

XCode swfit 컴파일러가 컴파일중에 세그먼테이션 폴트가 발생하면 어떻게 해결 해야 하는가?



어떤 라인이 문제가 있는지 어떤 코드가 문제인지 찾아 주지도 못한다.

심지어 이런 상황에서 버그를 리포트 하라고 에디터 상단에 아래와 같은 화면이 표시 되기도 한다.




에디터는 신텍스 하이라이트가 실행 되지 못하고 모든 텍스트가 흑백으로 표시 될때도 있다.





XCode의 버젼은 7.3.1이다.


문제의 코드는 위에 주석처리 한 코드 아래의 코드가 문제를 일으키는 코드이다.

recentlAddr은 아래와 같이 선언 되어 있다.

var recentlAddr = [[String:AnyObject]]()

if 문으로 바로 비교를 들어가면 Xcode swift 컴파일러가 문제를 일으키는 것으로 보인다.

더많은 케이스가 있겟지만 내가 찾은 케이스는 이런 경우 이다.

위에 올바른 코드와 같이 

func bookmarkButtonClick(sender : UIButton) {
        let bookmark = self.recentlAddr[sender.tag]["bookmark"] as! String
        
        if bookmark == "1" {
            return
        }
        recnetTobookmark(sender.tag, bookMarkType: 3)
    }

이렇게 수정하면 아무런 문제 없이 컴파일이 잘되고 문제가 없다.

결론
 XCode 컴파일러의 Segmentation fault 11이 발생하면 그래도 코드를 유심히 찾아 봐라!

2016년 6월 2일 목요일

iOS app에서 GCM (Google Cloud Messaging 사용하기

APNS를 위한 애플 개발자 페이지에서 앱 설정을 해야 한다.

구글 클라우드 메세징 서비스 페이지
https://developers.google.com/cloud-messaging/

구글 페이지에서
좌측 iOS를 선택하고 언어를 swift로 선택을 하여 안내를 받을 수 있다.

Cocoapod 을 이용해서 Google GCM 라이브러리를 프로젝트에 추가 해야 한다.

https://developers.google.com/cloud-messaging/ios/start?ver=swift


아래에 훌륭한 문서를 참조 하면 쉽게 따라 할 수 있다.
http://devlecture.tistory.com/entry/팁02-APNS-쉽게-만들고-테스트하기


Appdelegate 에 구글에서 제공하는 코드 뼈대를 잘 넣어 줘서 푸시를 수신 받을 수 있다.


앱이 포그라운드 상태에서 푸시를 받으면 아래에 메서드가 호출 된다.
 func application( application: UIApplication,
    didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
      print("Notification received: \(userInfo)")
      // This works only if the app started the GCM service
      GCMService.sharedInstance().appDidReceiveMessage(userInfo);
      // Handle the received message
      // ...
  }
 
앱이 백그라운드 상태에서 푸시를 받으면 아래에 메서드가 호출 된다.  
  func application( application: UIApplication,
    didReceiveRemoteNotification userInfo: [NSObject : AnyObject],
    fetchCompletionHandler handler: (UIBackgroundFetchResult) -> Void) {
      print("Notification received: \(userInfo)")
      // This works only if the app started the GCM service
      GCMService.sharedInstance().appDidReceiveMessage(userInfo);
      // Handle the received message
      // Invoke the completion handler passing the appropriate UIBackgroundFetchResult value
      // ...
  }
 
아래에 메서드는 GCM 서버로 부터 registrationToken을 받는다. 
  func registrationHandler(registrationToken: String!, error: NSError!) {
  }
 
테스트는 구글  크롬 어플리케이션 중에 포스트 맨을 이용하여 테스트가 가능 하다.

  registrationToken과 구글 GCM 사이트에서 앱을 등록 하고 p12 키등을 입력 받아서 얻은 Server API Key가 있어야 테스트가 가능 하다.



중요
디버깅 모드에서 푸시가 잘되는데 adhoc (릴리즈 버젼에서 푸시가 오지 않는경우)

개발이 완료되어 배포 시점이 되면 다음 코드를 수정 해야 한다.
  func application( application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken
      deviceToken: NSData ) {
  // [END receive_apns_token]
        // [START get_gcm_reg_token]
        // Create a config and set a delegate that implements the GGLInstaceIDDelegate protocol.
        let instanceIDConfig = GGLInstanceIDConfig.defaultConfig()
        instanceIDConfig.delegate = self
        // Start the GGLInstanceID shared instance with that config and request a registration
        // token to enable reception of notifications
        GGLInstanceID.sharedInstance().startWithConfig(instanceIDConfig)
        registrationOptions = [kGGLInstanceIDRegisterAPNSOption:deviceToken,
          kGGLInstanceIDAPNSServerTypeSandboxOption:true]
        GGLInstanceID.sharedInstance().tokenWithAuthorizedEntity(gcmSenderID,
          scope: kGGLInstanceIDScopeGCM, options: registrationOptions, handler: registrationHandler)
        // [END get_gcm_reg_token]
  }

kGGLInstanceIDAPNSServerTypeSandboxOption:true --> kGGLInstanceIDAPNSServerTypeSandboxOption:false