1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

iOS APPの作り方。(With App Store & AdMob & SwiftUI)

Last updated at Posted at 2025-06-22

✳︎自分用メモです。随時更新
admobはバナータイプです。
SwiftUIです。
シミュレーターはadmobがテストモードになります。
App Connectの審査の時はテストモードのスクショは却下になります。
App Connect登録時にワーニング2つ出るのは、無視。
App ConnectのマーケティングURLは登録の必要あり。(admobの審査で必要:このページのトップのapp-ads.txt ファイルをクローリングする。)
Privacy-policyの作成にはここを使いました。
https://app-privacy-policy-generator.nisrulz.com

手順

とりあえず名前をキープするため

1.Developerサイトで登録

2.App Connectでアプリの登録
とりあえずしないと名前が決定しない。名前は登録順らしい。名前が取れなきゃアイコンとかが決まらないので。

コード作成上必要なIDを取得するため

3.admobでアプリ登録(追加)

広告ユニット(形式)が決まっていればそれも
この記事はバナー

作成開始(X Code)

4.XCodeでアプリを新規作成

5.ProjectのSigning & Capabilities があっているか確認

6.言語設定をする。英語もあった方が良さそうなので残し、Japaneseを追加して、それをデフォルトにセットする。
スクリーンショット 2025-06-22 18.17.09.png

AdMob周りをしていきます。

copilot for Xcodeでお願いするのが便利です。
https://github.com/github/CopilotForXcode
Chat(Agent GPT-5 mini)で下記のようにお願いしたらできました。抜けている部分もあるので、その後info.plistを確認してください。

Content Viewの上部にadMobを追加したいです。アプリIDはca-app-pub-xxxxxxで、広告のフォーマットはバナーで、広告ユニットIDはca-app-pub-xxxx

7.Google Mobile Ads の Swift パッケージをインストール
File->Add Package Dependencities... で下記URL
https://github.com/googleads/swift-package-manager-google-mobile-ads.git

8.Info.plistの設定(admobのAPPID)
最初はファイルがないので、Infoの画面で登録 登録するとファイルができる。
適当なキーのマウスでロールオーバーすると右に+が表示されるのでクリック。
キーに GADApplicationIdentifier Valueにadmobのapp idを入力
Infoファイルができるので"Open as">"Source code"で開く
6行目(APP ID の書いてあるStringタグ)以降に下記の部分を追加。
https://developers.google.com/admob/ios/quick-start?hl=ja#import_the_mobile_ads_sdk

<key>GADApplicationIdentifier</key>
<!-- Sample AdMob app ID: ca-app-pub-3940256099942544~1458002511 -->
<string>SAMPLE_APP_ID</string>
<key>SKAdNetworkItems</key>
<array>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>cstr6suwn9.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>4fzdc2evr5.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>2fnua5tdw4.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>ydx93a7ass.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>p78axxw29g.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>v72qych5uu.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>ludvb6z3bs.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>cp8zw746q7.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>3sh42y64q3.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>c6k4g5qg8m.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>s39g8k73mm.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>3qy4746246.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>f38h382jlk.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>hs6bdukanm.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>mlmmfzh3r3.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>v4nxqhlyqp.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>wzmmz9fp6w.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>su67r6k2v3.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>yclnxrl5pm.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>t38b2kh725.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>7ug5zh24hu.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>gta9lk7p23.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>vutu7akeur.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>y5ghdn5j9k.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>v9wttpbfk9.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>n38lu8286q.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>47vhws6wlr.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>kbd757ywx3.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>9t245vhmpl.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>a2p9lx4jpn.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>22mmun2rn5.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>44jx6755aq.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>k674qkevps.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>4468km3ulz.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>2u9pt9hc89.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>8s468mfl3y.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>klf5c3l5u5.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>ppxm28t8ap.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>kbmxgpxpgc.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>uw77j35x4d.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>578prtvx9j.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>4dzt52r2t5.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>tl55sbb4fm.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>c3frkrj4fj.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>e5fvkxwrpn.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>8c4e2ghe7u.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>3rd42ekr43.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>97r2b46745.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>3qcr597p9d.skadnetwork</string>
  </dict>
</array>

多言語化の設定

9.New File From TemplateからResourceグループのString Catalogを選択(ファイル名はそのまま)
スクリーンショット 2025-06-22 17.42.57.png

10.New File From TemplateからResourceグループのString Catalogを選択ファイル名を"InfoPlist"で作成(大文字小文字を間違えないよう)
スクリーンショット 2025-06-22 17.45.31.png

Admobのための追加コード

11.GoogleMobileAdsConsentManager.swiftファイルの作成
https://developers.google.com/admob/ios/quick-start?hl=ja#import_the_mobile_ads_sdk
のGoogleMobileAdsConsentManager.swiftファイルをプロジェクトに取り込み
(テンプレートで新規Swiftファイルを作って、ペースト)ホームページでは一部しか表示されていないので注意

12.BannerContentView.swift ファイルの作成
https://developers.google.com/admob/ios/banner?hl=ja
のBannerContentView.swift を取り込む (テンプレートで新規Swiftファイルを作って、ペースト)ホームページでは一部しか表示されていないので注意
39行目のIDを変更。(シミュレータはデバッグしか表示されない)
28行目の Privateを削除

import GoogleMobileAds
import SwiftUI

struct BannerContentView: View {
  let navigationTitle: String

  // [START add_banner_to_view]
  var body: some View {
    Spacer()
    // Request an anchored adaptive banner with a width of 375.
    let adSize = currentOrientationAnchoredAdaptiveBanner(width: 375)
    BannerViewContainer(adSize)
      .frame(width: adSize.size.width, height: adSize.size.height)
      // [START_EXCLUDE silent]
      .navigationTitle(navigationTitle)
    // [END_EXCLUDE]
  }
  // [END add_banner_to_view]
}

struct BannerContentView_Previews: PreviewProvider {
  static var previews: some View {
    BannerContentView(navigationTitle: "Banner")
  }
}

// [START create_banner_view]
struct BannerViewContainer: UIViewRepresentable {
  typealias UIViewType = BannerView
  let adSize: AdSize

  init(_ adSize: AdSize) {
    self.adSize = adSize
  }

  func makeUIView(context: Context) -> BannerView {
    let banner = BannerView(adSize: adSize)
    // [START load_ad]
    banner.adUnitID = "ca-app-pub-8132641067593791/2804805858"
    banner.load(Request())
    // [END load_ad]
    // [START set_delegate]
    banner.delegate = context.coordinator
    // [END set_delegate]
    return banner
  }

  func updateUIView(_ uiView: BannerView, context: Context) {}

  func makeCoordinator() -> BannerCoordinator {
    return BannerCoordinator(self)
  }
  // [END create_banner_view]

  class BannerCoordinator: NSObject, BannerViewDelegate {

    let parent: BannerViewContainer

    init(_ parent: BannerViewContainer) {
      self.parent = parent
    }

    // MARK: - GADBannerViewDelegate methods

    func bannerViewDidReceiveAd(_ bannerView: BannerView) {
      print("DID RECEIVE AD.")
    }

    func bannerView(_ bannerView: BannerView, didFailToReceiveAdWithError error: Error) {
      print("FAILED TO RECEIVE AD: \(error.localizedDescription)")
    }
  }
}

13.IDFAの設定
https://developers.google.com/admob/ios/privacy/idfa?hl=ja

Infoでキー ”NSUserTrackingUsageDescription” Valueは日本がデフォルトなら”「許可」するとお客様に最適化された広告が表示されます。"を登録する。(NSUserTrackingUsageDescription は ”Privacy -Tracking Usage Description”になります。嫌な場合は右クリックでRaw key and Valueにすれば良い)
スクリーンショット 2025-06-22 18.14.57.png

14.一旦ビルドする。
ローカリゼーションファイルに反映するため。反映されていればビルド不要

15.InfoPlistのローカリゼーションファイルを開く
IDFA Messageを英語は”This identifier will be used to deliver personalized ads to you.”日本は”「許可」するとお客様に最適化された広告が表示されます。”にします。Defaultの言語は設定できないかも。。。。(できるプロジェクトとできないプロジェクトがある???ので不明)
スクリーンショット 2025-06-22 18.19.09.png

16.Admobのホームページの左のプライバシーとメッセージのIDFAメッセージを登録

17.メインとなるコードに追加

import SwiftUI
import SwiftData
//以下の5件のインポート追加
import UserMessagingPlatform
import AppTrackingTransparency
import AdSupport
import GoogleMobileAds
import Foundation


//以下のクラスを追加
class AppDelegate: UIResponder, UIApplicationDelegate {
    let shared = GoogleMobileAdsConsentManager()
    
    func application(_ application: UIApplication,
                     didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        debugPrint("lunch option \(launchOptions)")
        shared.gatherConsent { status in
            debugPrint("status \(status)")
        }
        shared.startGoogleMobileAdsSDK()
        return true
    }
}

@main
struct EasyCSVApp: App {
//以下の1行を追加
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate  
    var body: some Scene {
        
        WindowGroup {
            ContentView()
        }
        .modelContainer(for: CSVData.self)
    }
    init(){
        debugPrint("Program Started")
    }
}

この時点で実行するとIDFAの画面が表示されると思います。
シミュレータや実機で一旦動かしてAppがある場合は一旦削除しないと出ない時もあります。

18.あとはコードを書きます。
バナーを表示したいところで
import GoogleMobileAds 行と

  let adSize = currentOrientationAnchoredAdaptiveBanner(width: 375)
            BannerViewContainer(adSize)
                .frame(width: adSize.size.width, height: adSize.size.height)

App Storeの登録は色々記事に書いてあるので省略プライバシーポリシーに注意

参考

多言語化したい文字列は

String(localized: "文字列") と書けばLocalizableファイルに自動で上がる。(Textの文字列とかは何もしなくても上がります)
Localizableファイルに反映するのに1回ビルドする必要がある時もあります。

AdMobの審査

設定をきちんとして、チェックボタンを押しても無駄です。1日待ちましょう(クローリングが終わるまではチェックできません。チェックボタン(確認ボタン)を押さなくても正常なら、問題なく登録されてメールが届きます。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?