# 画面設計書 79-ArticleLocationCollection画面

## 概要

本ドキュメントは、Wikipedia iOSアプリの位置情報付き記事コレクション画面（ArticleLocationCollectionViewController）の設計を記述したものである。

### 本画面の処理概要

ArticleLocationCollectionViewController は、位置情報を持つWikipedia記事のリストを表示する画面である。各記事には現在地からの距離と方角が表示され、ユーザーは自分の周囲にある記事を視覚的に把握できる。Places機能の詳細表示や、位置情報に基づいた記事探索に使用される。

**業務上の目的・背景**：Wikipediaには位置情報（緯度・経度）が紐付けられた記事が多数存在する。例えば、名所、建造物、地域に関する記事などである。本画面は、これらの位置情報付き記事をユーザーの現在地との関係で表示し、周囲の興味深いスポットについての知識を提供する。LocationManagerと連携して、リアルタイムで距離と方角を更新する機能を持つ。

**画面へのアクセス方法**：Places画面からの詳細表示、またはExplore画面の近くの記事カードからの遷移で表示される。contentGroup経由でコンテキストが渡され、表示対象の記事URLリストが提供される。

**主要な操作・処理内容**：
1. ArticleLocationCollectionViewCellを使用した記事リスト表示
2. 各記事に現在地からの距離と方角をコンパス表示
3. LocationManagerによる位置情報と方位のリアルタイム監視
4. 記事セルタップで記事詳細画面への遷移
5. コンテキストメニュー（長押し）で記事プレビュー表示
6. フッターボタンで前画面への戻り

**画面遷移**：
- 遷移元：Places画面、Explore画面（近くの記事カード）
- 遷移先：Article画面（記事選択時）

**権限による表示制御**：位置情報の利用許可が必要。許可されている場合のみ距離・方角が表示される。未許可の場合は記事リストのみ表示。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 18 | 近くの記事（Places） | 補助機能 | 位置情報付き記事コレクションの共通基盤 |

## 画面種別

一覧

## URL/ルーティング

ネイティブ画面のため、URLベースのルーティングは存在しない。Places画面やExplore画面からナビゲーションコントローラ経由でプッシュ遷移される。

## 入出力項目

| 項目名 | 型 | 入力/出力 | 説明 |
|--------|-----|----------|------|
| articleURLs | [URL] | 入力 | 表示対象の記事URLリスト |
| dataStore | MWKDataStore | 入力 | データストアインスタンス |
| contentGroup | WMFContentGroup? | 入力 | コンテンツグループ（オプション） |
| theme | Theme | 入力 | 適用するテーマ |
| needsCloseButton | Bool | 入力 | 閉じるボタンの表示有無 |
| articleSource | ArticleSource | 入力 | 記事ソース識別 |

## 表示項目

| 項目名 | データソース | 説明 |
|--------|-------------|------|
| 記事セル | ArticleLocationCollectionViewCell | 位置情報付き記事表示用セル |
| サムネイル画像 | WMFArticle.imageURL | 記事のサムネイル |
| タイトル | WMFArticle.displayTitle | 記事のタイトル |
| 説明文 | WMFArticle.wikidataDescription | 記事の概要説明 |
| 距離 | 計算値 | 現在地からの距離（km/m） |
| 方角コンパス | CompassView | 記事の方角を示すコンパス |

## イベント仕様

### 1-画面表示（viewWillAppear）

LocationManagerのデリゲートを設定し、位置情報の利用が許可されている場合はstartMonitoringLocation()を呼び出して監視を開始する。

### 2-画面非表示（viewDidDisappear）

LocationManagerのデリゲートをnilに設定し、stopMonitoringLocation()を呼び出して監視を停止する。

### 3-位置情報更新（locationManager:didUpdate:）

新しい位置情報またはヘディング情報を受信すると、updateLocationOnVisibleCells()を呼び出して、表示中のすべてのセルの距離と方角を更新する。

### 4-セル選択（didSelectItemAt）

記事セルをタップすると、ArticleCoordinatorを生成してstart()を呼び出し、Article画面へ遷移する。

### 5-コンテキストメニュー

記事セルを長押しすると、ArticlePeekPreviewViewControllerによるプレビューを表示。

### 6-フッターボタン押下

collectionViewFooterButtonWasPressed()でnavigationController?.popViewController()を呼び出し、前画面へ戻る。

## データベース更新仕様

### 操作別データベース影響一覧

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| - | - | - | 本画面ではデータベース更新は発生しない（読み取りのみ） |

### テーブル別更新項目詳細

本画面は読み取り専用であり、データベース更新は発生しない。

## メッセージ仕様

本画面では直接的なメッセージ表示は行わない。

## 例外処理

| 例外ケース | 処理内容 |
|-----------|---------|
| 位置情報未許可 | 距離・方角は表示されない（記事リストのみ） |
| 記事データなし | 空のリスト表示 |
| CoreData取得失敗 | configureでセルが設定されない |

## 備考

- ColumnarCollectionViewControllerを継承
- WMFNavigationBarConfiguring, CollectionViewContextMenuShowing, LocationManagerDelegate, MEPEventsProvidingプロトコルを実装
- locationManagerプロパティでLocationManagerインスタンスを保持
- articleURLsプロパティはdidSetでcollectionView.reloadData()を呼び出す
- needsCloseButtonがtrueの場合、hidesBottomBarWhenPushedがtrueに設定
- イベントログはcategory: .places、label: nilで記録される
- needsConfigNavBarフラグでナビゲーションバーの設定を制御

---

## コードリーディングガイド

本クラスを理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

まず、位置情報関連のデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | LocationManager | `Wikipedia/Code/` | 位置情報管理クラス |
| 1-2 | CLLocation | `CoreLocation` | 位置情報データ |
| 1-3 | CLHeading | `CoreLocation` | 方位データ |

**読解のコツ**: LocationManagerはCLLocationManagerをラップし、位置と方位の監視を簡易化している。LocationManagerDelegateでコールバックを受け取る。

#### Step 2: エントリーポイントを理解する

処理の起点となるファイル・関数を特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ArticleLocationCollectionViewController.swift | `Wikipedia/Code/ArticleLocationCollectionViewController.swift` | 本クラスのメインファイル |

**主要処理フロー**:
1. **行19-44**: 初期化でarticleURLs、dataStore、contentGroup、theme、needsCloseButton、articleSourceを設定
2. **行46-49**: viewDidLoadでArticleLocationCollectionViewCellを登録
3. **行51-68**: viewWillAppearでLocationManager監視開始とナビゲーションバー設定
4. **行70-74**: viewDidDisappearでLocationManager監視停止

#### Step 3: 位置情報更新を理解する

LocationManagerDelegateの実装を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ArticleLocationCollectionViewController.swift | `Wikipedia/Code/ArticleLocationCollectionViewController.swift` | LocationManagerDelegate実装 |

**主要処理フロー**:
- **行172-186**: LocationManagerDelegate実装
- **行116-123**: updateLocationOnVisibleCells()で全セルの位置情報を更新

#### Step 4: セル表示を理解する

記事セルの設定処理を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | ArticleLocationCollectionViewController.swift | `Wikipedia/Code/ArticleLocationCollectionViewController.swift` | configure(cell:forItemAt:layoutOnly:)実装 |

**主要処理フロー**:
- **行140-162**: configure()でセルにarticleLocation、userLocation、userHeadingを設定
- **行161**: cell.configure(article:displayType:...)でセル表示を更新

### プログラム呼び出し階層図

```
ArticleLocationCollectionViewController
    │
    ├─ init(articleURLs:dataStore:contentGroup:theme:needsCloseButton:articleSource:) [行19-31]
    │
    ├─ viewDidLoad() [行46-49]
    │      └─ layoutManager.register(ArticleLocationCollectionViewCell)
    │
    ├─ viewWillAppear(_:) [行51-62]
    │      ├─ locationManager.delegate = self
    │      ├─ locationManager.startMonitoringLocation() (if authorized)
    │      └─ configureNavigationBar()
    │
    ├─ viewDidDisappear(_:) [行70-74]
    │      ├─ locationManager.delegate = nil
    │      └─ locationManager.stopMonitoringLocation()
    │
    ├─ configure(cell:forItemAt:layoutOnly:) [行140-162]
    │      ├─ dataStore.fetchArticle(with: url)
    │      ├─ cell.articleLocation = article.location
    │      ├─ cell.update(userLocation:heading:)
    │      └─ cell.configure(article:displayType:...)
    │
    ├─ updateLocationOnVisibleCells() [行116-123]
    │      └─ locationCell.update(userLocation:heading:)
    │
    ├─ LocationManagerDelegate [行172-186]
    │      ├─ didUpdate location → updateLocationOnVisibleCells()
    │      ├─ didUpdate heading → updateLocationOnVisibleCells()
    │      └─ didUpdateAuthorized → startMonitoringLocation()
    │
    └─ collectionView(_:didSelectItemAt:) [行190-199]
           └─ ArticleCoordinator.start()
```

### データフロー図

```
[入力]                    [処理]                           [出力]

articleURLs ─────────▶ numberOfItemsInSection()
    │                         │
    │                         ▼
    │                articleURL(at:)
    │                         │
    └─────────────────────▶  ▼
                     dataStore.fetchArticle()
                              │
                              ▼
                        WMFArticle
                              │
                   ┌──────────┼──────────┐
                   │          │          │
                   ▼          ▼          ▼
              タイトル    サムネイル   location
                   │          │          │
                   └──────────┴──────────┘
                              │
                              ▼
              ArticleLocationCollectionViewCell
                              │
LocationManager ────────▶ update(userLocation:heading:)
    │                              │
    │                              ▼
    └─▶ 距離計算 + 方角計算 ──▶ 距離/コンパス表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ArticleLocationCollectionViewController.swift | `Wikipedia/Code/ArticleLocationCollectionViewController.swift` | ソース | 本クラス |
| ColumnarCollectionViewController.swift | `Wikipedia/Code/ColumnarCollectionViewController.swift` | ソース | 親クラス |
| ArticleLocationCollectionViewCell.swift | `Wikipedia/Code/ArticleLocationCollectionViewCell.swift` | ソース | 位置情報付き記事セル |
| LocationManager.swift | `Wikipedia/Code/LocationManager.swift` | ソース | 位置情報管理 |
| LocationManagerDelegate.swift | `Wikipedia/Code/LocationManagerDelegate.swift` | プロトコル | 位置情報コールバック |
| CompassView.swift | `Wikipedia/Code/CompassView.swift` | ソース | コンパスビュー |
| ArticleCoordinator.swift | `Wikipedia/Code/ArticleCoordinator.swift` | ソース | 記事画面遷移コーディネーター |
| ArticlePeekPreviewViewController.swift | `Wikipedia/Code/ArticlePeekPreviewViewController.swift` | ソース | 記事プレビュー |
| MWKDataStore.swift | `Wikipedia/Code/MWKDataStore.swift` | ソース | データストア |
| WMFContentGroup | `WMF Framework/` | ソース | コンテンツグループ |
