iOS 카카오 ADFit 연동해보기

|

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


너무나 오랜만에 블로그를 작성하네요. 반성합니다.
이번에 사이드 프로젝트를 진행하면서 앱 안에 광고를 넣으려면서 카카오에서 제공해주는 Adfit을 사용해보았는데..
생각만큼 참고할만한 자료가 많이 없어서 고생고생하다가 고생기를 정리해보려고 합니다.

우선 참고하며 진행했던 자료는 요것입니다 » adfit-ios-sdk

시작해보기

지원 환경

  1. 최신 버전의 Xcode (Xcode 12.0 / Swift 5.3)
  2. iOS Deployment Target: iOS 12.0 이상

AdFitSDK는 Swift로 개발되어있으며, swift 기반의 프로젝트에서 AdFitSDK를 사용하시려면 반드시 최신 버전의 Xcode를 사용해주어야 합니다.

1. 광고단위 ID(Client ID) 발급받기

실제 광고를 수신하고 수익을 창출하기 위해서는, 먼저 AdFit 플랫폼에서 자신의 앱을 매체로 등록하고 광고단위 ID(Client ID)를 발급받아야 합니다.<br. 아래의 웹 사이트에서 앱 등록 / 광고단위 ID 발급 단계를 진행할 수 있습니다.

광고단위 ID 발급받기

앱 등록과 광고단위 ID 발급이 완료된 후, 다음 단계의 안내에 따라 AdFit SDK를 설치한다.

2. SDK 설치하기

pod 'AdFitSDK' > pod install

3. 프로젝트 설정

ATS(App Transport Security)처리

iOS 9부터 ATS(App Transport Security) 기능이 기본적으로 활성화 되어 있기 때문에 암호화된 HTTPS 방식의 통신만 허용됩니다. AdFit SDK는 ATS 활성화 상태에서도 정상적으로 동작하도록 구현되어 있으나, 광고를 통해 노출되는 광고주 페이지는 HTTPS 방식을 지원하지 않을 수도 있기 때문 에 아래의 사항을 앱 프로젝트의 Info.plist 파일에 적용하여 주어야 한다.

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

ATT(App Tracking Transparency) framework 적용

iOS14 타겟팅된 앱이 IDFA 식별자를 얻기 위해서는 ATT Framework를 반드시 적용해야 한다.

<key> NSUserTrackingUsageDescription </key>
<string> 맞춤형 광고 제공을 위해 사용자의 데이터가 사용됩니다. </string>

이는 앱이 사용자 또는 장치를 추적하기 위해 데이터 권한을 요청하는 이유를 사용자에게 알리는 메세지입니다.

이후 ATT 아래 코드를 App delegate에 적용시켜줍니다.

이는 광고 요청하기 전에 사용자로 부터 개인정보 보호에 관한 권한을 요청하는 것으로
앱이 설치되고 한번만 호출하면 되며, 아래 코드는 사용자가 권한에 대한 응답 후에는 더 이상 사용자에게 권한을 묻지 않습니다.

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

extension AppDelegate {
    func adFit() {
        if #available(iOS 14, *) {
          ATTrackingManager.requestTrackingAuthorization(completionHandler: { status in
            // 권한 요청이 완료된 다음, 광고를 요청해 주세요.
//             loadAd()
          })
        }
    }
}

4. 광고 요청하기

import UIKit
import AdFitSDK

class MyViewController: UIViewController {
  override func viewDidLoad() {
      super.viewDidLoad()
      setAdfit()
  }

  func setAdfit() {
      let adView = AdFitBannerAdView(clientId: "", adUnitSize: "")
      adView.frame = CGRect(x: 0, y: 0, width: view.bounds.width, height: 100)
      adView.rootViewController = self
      adView.addSubview(adView)

      adView.loadAd()
      adView.delegate = self
  }
}

5. delegate 메서드 구현

func adViewDidClickAd(_ bannerAdView: AdFitBannerAdView) {
    print("adDidClicked")
}

func adViewDidReceiveAd(_ bannerAdView: AdFitBannerAdView) {
    print("adDidReceived")
}

func adViewDidFailToReceiveAd(_ bannerAdView: AdFitBannerAdView, error: Error) {
    print("adDidFailReceived - error :\(error.localizedDescription)")
}

하면 위 setAdfit함수에 적여있는 adView.delegate = self에 의해 광고가 잘 전달되었는지, 에러가 왜 발생하는지를 알 수 있게 됩니다.

발생했던 에러

The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated from this process.

xcrun simctl spawn booted log config –mode “level:off” –subsystem com.apple.CoreTelephony

터미널에 위와 같이 실행해서 처리하였다.

참고한 stackoverflow

iOS Firebase Push Notification(FCM)연동해보기

|

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


제 블로그에서는 단순히 파이어베이스에서 fcm 연동하는 부분만 정리하였습니다.
애플 개발자 홈페이지에서 인증서를 발급받는 부분은 정리되어있지 않습니다 :)

ios 파이어베이스 연동하기

파이어베이스 콘솔 > [settings] > [클라우드 메시징]

APNs 파일을 업로드 하기위해 애플에서 발급받은 p8 파일을 같이 업로드 해줍니다.
뿐만 아니라 애플에서 발급받은 키ID와 팀ID를 입력합니다.

그리고 이제 xcode로 돌아옵니다.

Xcode > target > Push Notifications 추가

xcode로 돌아와 프로젝트의 target으로 들어가 + 버튼을 누르고 Push Notifications을 추가해줍니다.
그리고 Podfile에 아래를 추가해줍니다.

pod 'Firebase/Core'
pod 'Firebase/Analytics'
pod 'Firebase/Messaging'

이후 pod install 하는 것은 잊지마시구용!

App Delegate

pod install이 끝나면 app delegate로 돌아옵니다.
그리고 아래 코드를 추가해줍니다.

(import Firebase와 import UserNotifications 꼭 해주세요!)

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // Override point for customization after application launch.
    FirebaseApp.configure()
    UNUserNotificationCenter.current().delegate = self
    Messaging.messaging().delegate = self

    let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
    UNUserNotificationCenter
      .current()
      .requestAuthorization(
        options: authOptions,completionHandler: { (_, _) in }
      )
    application.registerForRemoteNotifications()
    return true

위 코드는 푸시 권한과 파이어베이스 기타 셋팅입니다.

extension AppDelegate : MessagingDelegate {
    func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
        print("파이어베이스 토큰: \(String(describing: fcmToken))")
    }
}

extension AppDelegate : UNUserNotificationCenterDelegate {
    func userNotificationCenter(_ center: UNUserNotificationCenter,willPresent notification: UNNotification,withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        completionHandler([.alert, .badge, .sound])
    }

    func userNotificationCenter(_ center: UNUserNotificationCenter,didReceive response: UNNotificationResponse,withCompletionHandler completionHandler: @escaping () -> Void) {
        completionHandler()
    }
}

그리고 파이어베이스 메시지 전송의 토큰을 받을 수 있는 MessagingDelegate를 extension으로 분리해줍니다.
뿐만 아니라, UNUserNotificationCenterDelegate를 통해 파이어베이스 노티를 수신받습니다.

파이어베이스 토큰값은 하나의 기기 특정 상대에게만 보낼 수 있는 기기의 고유한 값입니다.

GoogleServiceInfo-plist 추가하기

그리고 한가지 더 추가할 점! > xcode에 GoogleServiceInfo.plist 파일을 넣어주어야 합니다.
위 파일은 파이어베이스에서 처음 앱을 등록했을 때 받았을 수도 있고, 그렇지 않다면 아래 경로로 들어가 저장해주면 된다.

파이어베이스 콘솔창에서 [프로젝트 설정] > [일반]에 들어가 아래로 스크롤 하면 plist를 저장받을 수 있습니다.
저장한 파일은 xcode내 supporting files안에 넣어주면 됩니다.

그럼 이제 백그라운드 및 포어그라운드에서 알람메시지가 잘 작동하는지 다시 파이어베이스 홈페이지로 고고합시당.

push 확인해보기

파이어베이스 콘솔창을 한참 내리다 보면 Cloud Messaging이 있습니다.

클릭 후 들어가 새 알림 을 클릭해주고, 푸시할 내용을 적어주면 테스트 메시지 전송 버튼이 활성화될 것입니다.

그러면 아래와 같이 FCM 등록 토큰 추가 라는 화면이 보일 것이다.

이 토큰은 어디서 구할 수 있냐!? 다시 xcode로 들어가보자.
위 과정을 모두 처리한 다음 시뮬레이터를 돌려보면 xcode 로그창에 이상한 메시지가 떠있을것이다.

이때 받은 토큰을 파이어베이스 FCM 등록 토큰 추가에 넣어주면 됩니다.

이후 테스트 버튼을 눌러서 제대로 푸시가 오는지 확인해보세요!

Xcode에서 remove reference한 파일 직접 삭제하는 방법

|

개인 공부 내용을 정리한 글입니다.
잘못된 내용이 있다면 편하게 댓글 남겨주세요!


문제 상황

실수로 xcode내 파일 중 하나를 삭제할 때 move to trash 를 하지 못하고 remove reference 를 클릭했다.
동일한 이름의 파일을 올리려고 하니 이미 해당 파일이 폴더 내에 있어서 삭제가 안된다고 한다.

“GoogleService-Info (1).plist” couldn’t be moved to “SupportingFiles” because an item with the same name already exists.

Xcode내에는 이미 내가 파일을 삭제했으니 파일은 보이지않고, 근데 이미 파일은 존재한다고 하는데 어떻게 해야할까?

해결 방법

나 같은 경우는 해당 파일이 Supporting files라는 폴더안에 있었다. 따라서..

  1. Supporting files 마우스커서 오른쪽 클릭
  2. Show in finder 클릭
  3. Supporting files 폴더를 들어가면 삭제되지 않은 파일들이 있음을 발견할 수 있다.

원하는 파일을 직접 삭제하면 더이상 해당 에러는 발생하지 않는다!

UILable의 자동 줄바꿈하는 방법?

|

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


UILable 자동 줄바꿈?

기본적으로 UILable을 사용하면 아래 사진처럼 자동 줄바꿈이 안된다.

틀이 정해져있는 텍스트라면 스토리보드에서 line의 수를 정해주면 되지만, 우리가 만약 채팅방을 만든다고 생각해보자.
채팅을 주고받을때 주고받는 텍스트의 길이는 유동적일 것이다.

이 유동적인 텍스트(데이터)에 대한 줄바꿈이 자동으로 되도록 하기 위해서는 아래처럼 진행하면 된다.

@IBOutlet weak var chatLbl: UILabel!

self.chatLbl.numberOfLines = 0

그러면 아래처럼 적용이 된다.

tableview 혹은 scrollview에서 화면 터치이벤트 받는 방법?

|

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


touchesbegan이 안된다!?

보통 키보드가 올라온 상태에서 화면을 누르면 키보드가 내려가게 하고 싶다면 touchesbegan으로 처리를 했을 것이다.

override func touchesbegan(_ touches: Set(UITouch), with event: UIEvent?) {
  // todo...
}

지금 내가 하고 있는 프로젝트는 테이블뷰로 이루어지고 있는데, 이 테이블뷰의 셀에 터치를 시도하게 되면 키보드가 내려가질 않는 현상이 발생한다.
이 touchesbegan이 먹히지 않는 이유는 찾아보니 생각보다 간단했다.

테이블뷰나 스크롤뷰 같은 경우는 일반적으로 스크롤을 하기위해 기본적인 1터치 가 발생한다.
그렇기 때문에 한번의 터치같은 경우는 그냥 무시가 되는 것 같다. 따라서 touchesbegan & touchedMoved 모두 호출이 되지 않는 것이다.

따라서 이러한 경우 직접 GestureRecognizer 를 추가하여 핸들러를 캐치하도록 만들어주어야 한다.

override func viewDidLoad() {
    super.viewDidLoad()

    // 핸들러 등록
    view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleTap(sender:))))
}

// 터치가 발생할때 핸들러 캐치
@objc func handleTap(sender: UITapGestureRecognizer) {
    if sender.state == .ended {
        view.endEditing(true) // todo...
    }
    sender.cancelsTouchesInView = false
}

이렇게 핸들러를 등록해주면 tableview 혹은 scrollview에서 터치이벤트를 작동할 수 있게된다.