ガイド変更履歴HERE SDK API references
ガイド

HERE SDKを統合する

このチュートリアルでは、地図を表示するiOSアプリケーションを開発します。

  • HERE SDKを既存のアプリケーションに統合する場合は、新しいプロジェクトを最初からセットアップする最初の手順は飛ばしてかまいません。
  • HERE SDK の一部の機能を紹介しているサンプル アプリの実行から始める場合は、こちらのチュートリアルをご覧ください。

前提条件

資格情報と HERE SDK フレームワークへのアクセス権があることを確認します。詳細については、「利用開始」を参照してください。

新しいプロジェクトを作成する

XcodeをIDEとして使用します。iOSの開発が初めての場合は、developer.android.comのガイドに従って最初のステップを進めてください。

結果として得られるコードはGitHubから入手可能です。

Xcodeを起動し (このガイドはバージョン16.4に基づきます)、[Create New Project...](新しいプロジェクトを作成...) をクリックします。または、[File](ファイル) > [New](新規) > [Project...](プロジェクト...) の順に選択します。

  1. テンプレートの場合は、プラットフォームとして[iOS]を選択し、[Application](アプリケーション) セクションで[App](アプリ) を選択します。
  2. [Next](次へ) をクリックします。
  3. [Product Name](製品名) を入力します ("HelloMap"など)。
  4. [Team](チーム) を選択します (該当する場合)。
  5. [Organization Identifier](組織ID) を入力します(com.your-companyなど)。
  6. 言語として[Swift]を選択します。
  7. インターフェースとして[SwiftUI]を選択します。
  8. [Next](次へ) をクリックして、プロジェクトを保存する適切なディレクトリを選択します。
  9. [Create](作成) をクリックして、プロジェクトの設定を完了します。

新しく作成したプロジェクトで、アプリケーションの実行先としてシミュレーターまたは実際のデバイス(推奨) を選択します。

以下の例では、デフォルトの設定のままにしています。既存のサンプルアプリを実行する場合は、デプロイターゲットがインストールしたバージョンに設定されていることを確認してください。今回はiOS 15.2を使用しています。

[Build](ビルド) および[Run the current scheme](現在のスキームを実行) をクリックし、まだ何も設定していないプロジェクトが期待どおりに実行されることを確認します。すべてが成功すると、コンテンツのない空白のビューが表示されます。

動作するアプリケーションができたら、アプリの機能を検討します。このチュートリアルでは、シンプルさを保ったまま、エミュレータまたはデバイスにマップ ビューを表示します。

次のステップの概要は以下のとおりです。

  1. HERE SDK を統合する。
  2. 必要な資格情報を設定します。
  3. マップビューを追加して最初のマップシーンを読み込みます。

HERE SDK のすべての機能にはシミュレーターからアクセスできますが、実際のデバイスを使用することを強くお勧めします。全体的なパフォーマンスが向上し、ジェスチャーなどの一部の機能はマルチタッチ対応のハードウェアの方が簡単に使用できます。マップ ビューのレンダリングはモバイル機器の GPU に合わせて最適化されています。

最初のステップから始めて、HERE SDK をプロジェクトに追加する方法を見てみましょう。

HERE SDK フレームワークを統合する

上記のように、アプリケーションに含める HERE SDK フレームワークを含む最新のリリース アーティファクト (xx.yy.zz.release_date という名前) を取得します。

CocoaPodsを使用したArtifactoryのサポートはまだ提供されておらず、SDK依存関係管理も利用できません。そのため、HERE SDKフレームワークフォルダー (XCFW) を手動でダウンロードして統合する必要があります。

アプリのルートフォルダーにheresdk.xcframeworkフォルダーをコピーします。XCFW フォルダーには、Info.plist ファイル や 2 つのフォルダー (ios-arm64ios-arm64_x86_64-simulator) など、多くのファイルが含まれています。

Xcode でアプリに heresdk.xcframeworkを追加します。プロジェクト ナビゲーターでプロジェクトを強調表示し、[Targets](ターゲット) でアプリを選択します。[General」(全般) タブで、[Frameworks, Libraries, and Embedded Content](フレームワーク、ライブラリ、組み込みコンテンツ) まで下にスクロールします。セクションを展開し、[+] -> [Add other](その他を追加) -> [Add files](ファイルを追加) をクリックします。

このガイドはHERE SDKバージョン4.25.5.0に基づいています。フレームワークのバージョンがこのガイドで使用しているバージョンと異なる場合は、手順が異なる場合があり、サンプルのソースコードの調整が必要になる場合があります。

資格情報を設定する

HERE SDK を使用する際には、一連の資格情報を使用してアプリケーションを認証する必要があります。

資格情報を手元に用意したら、HERE SDKを初期化する際に、プログラムで一連の資格情報を追加します (次のステップを参照)。

資格情報はアプリの名前に関連付けられているのではなく、資格情報の取得に使用されるアカウントに関連付けられています。複数のアプリに同じ資格情報を使用する場合は、システム内のアプリを区別するためにスコープを設定する必要もあります。

HERE SDK を初期化する

HERE SDK は自動的に初期化されません。代わりに、HERE SDK を初期化するタイミングを自由に決定できます。初期化はメイン スレッド上で同期的に行われ、約 100 ミリ秒かかります。

資格情報が無効であっても、HERE SDK の初期化は成功します。資格情報が有効かどうかを確認する最良の方法は、機能エンジンを試すことです。資格情報が無効である場合は専用のエラー列挙型 (enum) 値になります。一部の機能では、他の機能よりも多くの権限が必要になる場合があります。たとえば、Explore用に取得した資格情報をExploreのサブセットの一部ではないOfflineSearchEngineで使用すると、エラーが発生します。

HERE SDKの機能を使用する前に、次のメソッドを実行してHERE SDKを初期化します。

private func initializeHERESDK() {
    // Set your credentials for the HERE SDK.
    let accessKeyID = "YOUR_ACCESS_KEY_ID"
    let accessKeySecret = "YOUR_ACCESS_KEY_SECRET"
    let authenticationMode = AuthenticationMode.withKeySecret(accessKeyId: accessKeyID,
                                                              accessKeySecret: accessKeySecret)
    let options = SDKOptions(authenticationMode: authenticationMode)
    do {
        try SDKNativeEngine.makeSharedInstance(options: options)
    } catch let engineInstantiationError {
        fatalError("Failed to initialize the HERE SDK. Cause: \(engineInstantiationError)")
    }
}

キーとシークレットの正しい資格情報を挿入してください。makeSharedInstance() を呼び出すことで、HERE SDK を使用するために必要なものをすべて初期化します。HERE SDK のコア クラスは SDKNativeEngine と呼ばれています。内部的には、HERE SDKによって提供される他のエンジンでこのインスタンスが使用されます。

以下は、AppクラスのコンストラクタでinitializeHERESDK()を呼び出す方法の例です。たとえば、プロジェクトの名前が"HelloMap"の場合、ファイルの名前はHelloMapApp.swiftです。以下のようにファイルを編集します。

import heresdk
import SwiftUI

// This class is the entry point to an application.
// In this example, the HERE SDK initialization is done at the start of the app.
// When app is terminated, the HERE SDK is disposed.
@main
struct HelloMapApp: App {

    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }

    init() {
        observeAppLifecycle()

        // Usually, you need to initialize the HERE SDK only once during the lifetime of an application.
        initializeHERESDK()
    }

    private func observeAppLifecycle() {
        NotificationCenter.default.addObserver(forName: UIApplication.willTerminateNotification,
                                               object: nil,
                                               queue: nil) { _ in
            // Perform cleanup or final tasks here.
            print("App is about to terminate.")
            disposeHERESDK()
        }
    }

    private func initializeHERESDK() {
        // Init the HERE SDK here ...
    }

    private func disposeHERESDK() {
        // Free HERE SDK resources before the application shuts down.
        // Usually, this should be called only on application termination.

        // After this call, the HERE SDK is no longer usable unless it is initialized again.
         SDKNativeEngine.sharedInstance = nil
    }
}

常にメインスレッドでinitializeHERESDK()を呼び出します。同様に、HERE SDKを配置してリソースを解放できます。この例では、NotificationCenterを使用してアプリが終了しそうなタイミングを検出します。このアプリケーションでは、解放するリソースがないため、単純にSDKNativeEngine.sharedInstancenilに設定します。

エンジン」セクションにはHERE SDKを初期化する方法が他にも記載されています。

マップビューを追加する

HERE SDKがプロジェクトに統合され、必要な資格情報が追加されたため、新しいMapViewインスタンスを追加できます。

以下ではSwiftUIを使用しています。ストーリーボードを使用してXcodeのInterface Builderを使用する場合は、「HelloMapWithStoryboard」サンプルアプリを参照してください。

HERE SDKが提供するMapViewUIViewサブクラスであるため、UIViewRepresentableプロトコルを使用するSwiftUIビューに準拠するようにラップする必要があります。前の手順で示したように、HERE SDKが事前に初期化されていることを確認してください。

Xcodeで、MapViewUIRepresentable.swiftと呼ばれる新しいSwiftクラスを作成し、次のようになっていることを確認します。

import heresdk
import SwiftUI

struct MapViewUIRepresentable: UIViewRepresentable {

    // Conform to UIViewRepresentable protocol.
    func makeUIView(context: Context) -> MapView {
        // Create an instance of the map view.
        return MapView()
    }

    // Conform to UIViewRepresentable protocol.
    func updateUIView(_ mapView: MapView, context: Context) {
        // Load a map scene here.
    }
}

UIViewRepresentableプロトコルはビューのインスタンスが必要なときに呼び出されるmakeUIView(context:)関数を定義します。ここで行う必要があるのは、マップビューの新しいインスタンスを返すことです。

作成後、ホスティングビューが表示され、updateUIView(_ mapView:context:)が呼び出されます。このタイミングでマップシーンを読み込むのが適切です。マップシーンを読み込まないと、地図は表示されません。

マップシーンを読み込む

MapViewUIRepresentableupdateUIView(_ mapView:context:)メソッドで次のコードを追加して、normalDayマップレンダリングスタイルを表すマップスキームを使用してシーンを読み込みます。

// Conform to UIViewRepresentable protocol.
func updateUIView(_ mapView: MapView, context: Context) {
    // Load the map scene using a map scheme to render the map with.
    mapView.mapScene.loadScene(mapScheme: MapScheme.normalDay, completion: onLoadScene)

    // Inlined completion handler for onLoadScene().
    func onLoadScene(mapError: MapError?) {
        guard mapError == nil else {
            print("Error: Map scene not loaded, \(String(describing: mapError))")
            return
        }

        // Use the camera to specify where to look at the map.
        // For this example, we show Berlin in Germany.
        let camera = mapView.camera
        let distanceInMeters = MapMeasure(kind: .distanceInMeters, value: 1000)
        camera.lookAt(point: GeoCoordinates(latitude: 52.517543, longitude: 13.408991),
                      zoom: distanceInMeters)
    }
}

シーンの読み込みが成功したかどうかを通知するために、オプションで完了ハンドラーを実装できます。シーンの読み込みが完了すると、メインスレッドで完了ハンドラーが呼び出されることに注意してください。nil以外のMapError値は、読み込み中に発生した問題を示します。

MapViewからCameraにアクセスして、地図の中央に配置する場所やズームレベル (カメラの地球までの距離で指定) などのカスタムマップパラメーターを設定できます。

let camera = mapView.camera
let distanceInMeters = MapMeasure(kind: .distanceInMeters, value: 1000)
camera.lookAt(point: GeoCoordinates(latitude: 52.517543, longitude: 13.408991),
              zoom: distanceInMeters)

MapView インスタンスが使用可能になるとすぐに Camera を設定できます。ただし、変更が有効になるのは、シーンの読み込みの完了ハンドラーが終了した後です。

演習として、上記の .normalDay スタイルを .satellite に置き換えてみます。どのような結果になりましたか?通常の夜間スキームなど、他のマップスキームも試してみてください。

または、利用可能ないずれかのマップレイヤー (Navigateでのみ使用可能) を試してみてください。たとえば、目立つランドマークのテクスチャ付き3Dモデルを有効にするには、次のコードラインをonLoadScene()完了ハンドラーに追加します。

mapView.mapScene.enableFeatures([MapFeatures.landmarks : MapFeatureModes.landmarksTextured])

有効期間を処理する

SDKNativeEngineの共有インスタンスをnilに設定することをお勧めします。これにより、上記のHelloMapAppクラスに示すように、共有インスタンスは保持されなくなります。いずれにしてもアプリをシャットダウンする場合、SDKNativeEngineの破棄は必須ではありません。ただし、破棄してもデメリットはなく、進行中のリクエストをキャンセルして進行中のHERE SDKサービスをシャットダウンすることが推奨事項であると考えられています。一方で、1画面のみを破棄し、アプリの他の部分ではHERE SDKが引き続き必要な場合は、HERE SDKを早い段階で廃棄しないように注意してください。一般的に、画面ごとにHERE SDKを初期化/廃棄することも可能です。

複数のMapViewインスタンスを同じ画面で作成してレンダリングできます。

MapViewはライフサイクルイベントを独自にリッスンするため、通常、アプリケーションはクリーンアップやライフサイクル処理を単独で行う必要はありません。

ビルドして実行する

次に、アプリを構築して実行します。すべてがうまくいけば、画面全体に HERE マップが表示されます。お疲れ様でした。これで HERE SDK for iOS を使用する最初のステップが完了しました。

Screenshot: Showing main map scheme.

Screenshot: Showing 3D landmarks (only available for Navigate).

Screenshot: Showing satellite map scheme.

次のステップ

  • HERE SDKの機能の詳細については、「機能一覧」トピックを参照してください。
  • HERE SDKを使用してCarPlay用に開発する方法を確認します。「CarPlayとの統合」を参照してください。

EN 日本語

HERE documentation

Find answers to your product and technical questions

Documentation

What's new

Videos

EN 日本語

HERE ドキュメント

製品や技術に関する質問の答えを見つけましょう。より多くの内容と最新の情報については、英語版をご覧ください。

ドキュメント

ダイナミックマップ

動的コンテンツ関連のAPIをアプリやサービスに活用して、ドライバーが安全・快適かつ予定どおりに目的地へ到着できるよう支援します。

地図とデータ

世界中を走行する多数のマッピング車両から得られる最新の位置情報データを活用し、精度の高い地図やカスタムレイヤーを構築できます。

最新情報

動画

(function () { const input = document.querySelector('input[data-typeahead]'); if (!input) return; // Prevent the form from submitting/navigating input.closest('form')?.addEventListener('submit', e => e.preventDefault()); input.addEventListener('input', function () { const q = this.value.trim().toLowerCase(); document.querySelectorAll('.nav-group-name').forEach(group => { let anyVisible = false; group.querySelectorAll('.nav-group-task').forEach(task => { const text = task.textContent.trim().toLowerCase(); const show = !q || text.includes(q); task.style.display = show ? '' : 'none'; if (show) anyVisible = true; }); // Hide the whole group header if nothing matches group.style.display = anyVisible || !q ? '' : 'none'; }); }); })(); (function () { function onTokenClick(event) { var link = event.target.closest('.sdk-for-ios .item .token'); if (!link) return; event.preventDefault(); console.log('token clicked', link.textContent.trim()); var item = link.closest('.item'); if (!item) return; var content = item.querySelector('.height-container'); if (!content) { console.log('no .height-container found for item', item); return; } var isHidden = window.getComputedStyle(content).display === 'none'; content.style.display = isHidden ? 'block' : 'none'; link.classList.toggle('token-open', isHidden); var href = link.getAttribute('href'); if (href) { if (history.pushState) history.pushState({}, '', href); else location.hash = href; } } function openHashTarget() { var hash = window.location.hash.slice(1); if (!hash) return; var anchor = document.querySelector('.sdk-for-ios a[name="' + hash + '"]'); if (!anchor) return; var item = anchor.closest('.item'); if (!item) return; var link = item.querySelector('.token'); var content = item.querySelector('.height-container'); if (!link || !content) return; content.style.display = 'block'; link.classList.add('token-open'); } function init() { console.log('HERE SDK accordion init'); openHashTarget(); } document.removeEventListener('click', onTokenClick); document.addEventListener('click', onTokenClick); if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } window.addEventListener('hashchange', openHashTarget); window.addEventListener('pageLoad', init); })();