1 典型的なiOSのMVC (Model-View-Controller) アーキテクチャにおいて、UIViewControllerはどのような責務を持つべきですか?
従来のiOSのMVC(Model-View-Controller)において、UIViewControllerはViewコンポーネントとModelデータの橋渡しをするControllerとして機能します。主な責務には、Viewのライフサイクル管理(`viewDidLoad` や `viewWillAppear` など)、UI要素の初期設定と更新、直接的なユーザー操作のハンドリング(ボタンタップ、デリゲート、ターゲット・アクションなど)、および画面遷移やプレゼンテーションの制御が含まれます。
直接的なネットワーク通信、データの永続化、重いビジネスロジックなどのUI以外の責務は、専用のサービスオブジェクトやモデルオブジェクトに委譲すべきです。これにより、View Controllerが肥大化してMassive View Controllerになるのを防ぐことができます。
class UserProfileViewController: UIViewController {
private let userService: UserServiceProtocol
private let profileView = UserProfileView()
init(userService: UserServiceProtocol) {
self.userService = userService
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
override func loadView() {
view = profileView
}
override func viewDidLoad() {
super.viewDidLoad()
profileView.editButton.addTarget(self, action: #selector(didTapEdit), for: .touchUpInside)
fetchProfile()
}
private func fetchProfile() {
userService.fetchCurrentUser { [weak self] result in
DispatchQueue.main.async {
if case .success(let user) = result {
self?.profileView.configure(with: user)
}
}
}
}
@objc private func didTapEdit() {
// Handle user action or trigger navigation
}
}
AI コーチを使ってこの質問に答えてみる
2 iOSアプリのリリースにおいて、プロビジョニングプロファイルはどのような役割を果たしますか?
iOSのリリースにおいて、プロビジョニングプロファイルはAppleのセキュリティ要件とアプリのバイナリおよび対象デバイスを橋渡しする、暗号署名されたパッケージとして機能します。その主な役割は、アプリケーションが特定の配信ルールに基づいて実行を許可されていることを、iOSオペレーティングシステムおよびApp Store Connectに伝えることです。
プロビジョニングプロファイルは、以下の重要な要素をひとまとめにバンドルしています。
- App ID(Bundle Identifier)
- アプリのビルド元を確認する承認済みの署名証明書
- アプリに付与されたエンタイトルメントと機能(プッシュ通知、Sign in with Apple、iCloudなど)
- App Store以外のプロファイル(DevelopmentやAd-Hocなど)の場合、許可されたデバイスのUDIDリスト
App Storeリリース用プロファイルでは、App Storeを通じて任意の一般ユーザーのデバイスへ配信することがAppleによって許可されているため、個々のデバイスUDIDは省略されます。
Provisioning Profile (.mobileprovision)
├── App ID / Bundle Identifier (e.g., com.example.app)
├── Certificates (Public key / Distribution Certificate)
├── Entitlements (e.g., Push Notifications, Associated Domains)
└── Device UDIDs (Present for Development/Ad-Hoc; omitted for App Store distribution)
AI コーチを使ってこの質問に答えてみる
3 iOSアプリがバックグラウンドで処理を実行するとはどういう意味ですか?また、システムはその処理に対してどのような基本的な制限を設けていますか?
iOSにおけるバックグラウンドでの処理実行とは、アプリが画面上でアクティブになっていない、またはユーザーから見えていない状態のときにコードを実行することを指します。ユーザーがアプリを離れると、アプリはアクティブなフォアグラウンド状態からバックグラウンド状態へと遷移し、その後間もなくサスペンド状態へと移行します。サスペンド状態ではメモリ(RAM)上に展開されたまま実行のみが一時停止されます。
バッテリー駆動時間、システムの応答性、およびデバイスリソースを保護するため、iOSはバックグラウンド実行を厳格に制御しています。システムはバックグラウンド移行後にコードを実行できる時間(特定のバックグラウンドモードやスケジュールタスクを使用しない限り、通常は約30秒程度の短い有限なウィンドウ)を制限し、CPUやネットワークの優先度を抑制(スロットリング)するほか、デバイスのメモリ逼迫時にはサスペンド状態のアプリを終了させることがあります。
import UIKit
NotificationCenter.default.addObserver(
forName: UIApplication.didEnterBackgroundNotification,
object: nil,
queue: .main
) { _ in
print("App entered background. Code execution will pause soon unless extended.")
}
AI コーチを使ってこの質問に答えてみる
4 Combineにおけるパブリッシャー(Publisher)とは何ですか。また、一般的なiOSのデータフローにおいてサブスクライバー(Subscriber)とはどのように異なりますか?
Combineにおいて、Publisherは時間の経過に伴って一連の値(ストリーム)を発行し、完了イベント(正常終了またはエラーによる失敗)で終了できます。Publisherは2つの関連型を宣言します。生成するデータの型である`Output`と、発行する可能性があるエラーの型である`Failure`です。Subscriberは、パブリッシャーから値とライフサイクルイベントを受け取ります。典型的なiOSのデータフローでは、パブリッシャーは非同期イベント(ネットワークレスポンス、通知、ユーザー入力など)の発行元(プロデューサー)として機能し、サブスクライバーは発行された値への対応、エラー処理、完了への対応を行うコンシューマーとして機能します(UI状態の更新やデータベースへの書き込みなど)。サブスクライバーはパブリッシャーにアタッチ(接続)し、サブスクリプショントークンを受け取り、要素の要求(demand)を行います。
import Combine
// Publisher: emits a sequence of integers
let numberPublisher = [1, 2, 3].publisher
// Subscriber: consumes the emitted integers
let cancellable = numberPublisher.sink(
receiveCompletion: { completion in
switch completion {
case .finished:
print("Finished")
case .failure(let error):
print("Error: \(error)")
}
},
receiveValue: { value in
print("Received: \(value)")
}
)
AI コーチを使ってこの質問に答えてみる
5 Swiftにおける `async/await` にはどのような意味があり、iOSアプリから非同期APIを呼び出すにはどのように使用しますか?
`async/await` は、ネストされたクロージャや完了ハンドラ(completion handler)を使用する代わりに、非同期コードを直線的かつ可読性の高いシーケンシャルな形式で記述するためのSwift組み込み構文です。関数に `async` を指定すると、時間のかかる処理(ネットワークリクエストやファイルI/Oなど)の完了を待つ間、その関数の実行を中断(サスペンド)できることをコンパイラに伝えます。`await` キーワードは中断ポイントを示します。現在の関数の実行が一時停止し、基礎となるスレッドが解放されて他の処理を実行できるようになり、待機していた結果やエラーの準備が整うと実行が再開されます。iOSアプリから非同期APIを呼び出すには、別の `async` 関数の内部や `Task` ブロックなどの非同期コンテキスト内から、呼び出す `async` メソッドの前に `await`(エラーをスローする関数の場合は `try await`)を付与して呼び出します。
func fetchUserData(from url: URL) async throws -> User {
let (data, response) = try await URLSession.shared.data(from: url)
guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else {
throw URLError(.badServerResponse)
}
return try JSONDecoder().decode(User.self, from: data)
}
AI コーチを使ってこの質問に答えてみる
6 iOSアプリでUserDefaultsはどのような場合に使用すべきですか?また、どのようなデータをそこに保存すべきではありませんか?
UserDefaultsは、アプリの起動を跨いで保持する小規模で軽量なユーザー設定やフラグ(テーマ設定、音量レベル、`hasSeenOnboarding` のようなブール値フラグなど)を保存するために設計されています。String、Int、Double、Bool、Date、Data、Array、Dictionary などのプロパティリスト型をサポートしています。
保存すべきではないデータは以下の通りです:
1. 機密情報(ユーザーパスワード、秘密鍵、認証トークンなど): UserDefaultsはデータを暗号化せず、プレーンテキストのplistファイルに保存するためです。
2. 大規模なデータセット、ドキュメント、またはメディアファイル(画像、音声、サイズの大きいJSONペイロードなど): アクセス時にplist全体がメモリにロードされるため、メモリのオーバーヘッドが大きくなり、アプリの起動時間が遅延する原因になります。
// Saving simple preference values
UserDefaults.standard.set(true, forKey: "hasCompletedOnboarding")
UserDefaults.standard.set("dark", forKey: "preferredTheme")
// Reading values back
let hasCompletedOnboarding = UserDefaults.standard.bool(forKey: "hasCompletedOnboarding")
let theme = UserDefaults.standard.string(forKey: "preferredTheme") ?? "system"
AI コーチを使ってこの質問に答えてみる
これらの回答を声に出して練習する準備はできていますか?
声で回答し、技術の深さ、構成、英語でのコミュニケーションについてフィードバックを受け取れます。
7 SwiftにおけるARC(Automatic Reference Counting)とは何ですか?また、iOSアプリ内でクラスインスタンスの寿命をどのように管理しますか?
ARC(Automatic Reference Counting)は、クラスインスタンス(参照型)の寿命を追跡・管理するためのSwiftのコンパイル時メモリ管理機構です。クラスの新しいインスタンスが生成されて強参照(strong reference)に代入されるたびに、ARCはそのインスタンスの内部参照カウントを追跡します。インスタンスへの強参照が少なくとも1つ存在する限り、ARCはそのインスタンスをメモリ上に保持します。すべての強参照が解除されて参照カウントがゼロになると、ARCは即座にインスタンスを破棄してメモリを解放し、解放の直前にインスタンスの`deinit`メソッドを自動的に呼び出します。Javaや.NETのような環境における実行時ガベージコレクション(GC)とは異なり、ARCは定期的なスイープサイクルを実行しません。Swiftコンパイラがコンパイル時にバイナリへ適切なretain呼び出しとrelease呼び出しを挿入します。
class User {
let name: String
init(name: String) {
self.name = name
print("\(name) initialized")
}
deinit {
print("\(name) deallocated")
}
}
var ref1: User? = User(name: "Alice") // count = 1
var ref2: User? = ref1 // count = 2
ref1 = nil // count = 1
ref2 = nil // count = 0 -> deinit called
AI コーチを使ってこの質問に答えてみる
8 iOSアプリにおいて、URLSession を使用してシンプルな HTTP (Hypertext Transfer Protocol) GET リクエストを実行するにはどうすればよいですか?
iOSアプリでシンプルな HTTP GET リクエストを実行するには、URL オブジェクトを作成し、URLSession.shared などの URLSession インスタンスに渡します。リクエストの実行には、データタスクの完了ハンドラ(URLSession.shared.dataTask(with: url) { data, response, error in ... })を使用する方法と、モダンな Swift の並行処理(let (data, response) = try await URLSession.shared.data(from: url))を使用する方法があります。従来のデータタスクによる手法を使用する場合は、タスクを開始するために .resume() を呼び出し、トランスポートエラーを処理し、HTTPURLResponse のステータスコードを確認した上で、UIの更新処理が必ずメインスレッドにディスパッチされるようにする必要があります。
guard let url = URL(string: "https://api.example.com/items") else { return }
let task = URLSession.shared.dataTask(with: url) { data, response, error in
if let error = error {
print("Network error: \(error.localizedDescription)")
return
}
guard let httpResponse = response as? HTTPURLResponse, (200...299).contains(httpResponse.statusCode) else {
print("Server error or invalid status code")
return
}
if let data = data {
DispatchQueue.main.async {
// Update UI on main thread
}
}
}
task.resume()
AI コーチを使ってこの質問に答えてみる
9 XcodeのInstrumentsとは何ですか?また、iOSアプリにおける単純なパフォーマンス問題を調査するためにどのように使用しますか?
Instrumentsは、Xcodeに同梱されているAppleのパフォーマンスプロファイリングおよび分析ツールです。ランタイムの動作、CPU使用率、メモリ割り当て、メモリリーク、UIレンダリングのパフォーマンスなどを監視できます。UIのカクつきや高いCPU使用率といった単純なパフォーマンス問題を調査する場合、XcodeからInstrumentsを起動し(Product -> Profile)、適切なテンプレート(CPUボトルネックにはTime Profiler、メモリ問題にはAllocationsやLeaksなど)を選択して、実機上で問題となるユーザーフローを再現しながらトレースを記録します。記録完了後、コールツリー(call tree)や最も負荷の高いスタックトレースを分析することで、遅延や過度なリソース消費を引き起こしている具体的なメソッドを特定できます。これにより、コード変更を行う前にボトルネックを正確に測定・特定できます。
1. In Xcode, select Product -> Profile (Builds with Release optimizations).
2. Select the 'Time Profiler' template.
3. Click Record and perform the sluggish action in the app.
4. Stop recording.
5. Inspect the Call Tree tab:
- Enable 'Separate by Thread' and 'Hide System Libraries'.
- Trace the heaviest call stack on the Main Thread to identify the blocking function.
AI コーチを使ってこの質問に答えてみる
10 APNs (Apple Push Notification service) とは何ですか。また、iOSアプリにプッシュ通知を配信するうえでどのような役割を果たしますか?
APNs(Apple Push Notification service)は、バックエンドサーバー(プロバイダサーバー)からApple製デバイスへプッシュ通知を安全にルーティングする、Appleのクラウドベースの仲介サービスです。モバイルデバイスが各アプリのバックエンドと個別に常時ソケット接続を維持すると、バッテリーの急激な消耗や過度なネットワーク帯域消費が発生するため、Appleは各デバイスとAPNsの間に低消費電力の持続的接続を1本だけ維持しています。アプリがリモート通知に登録すると、APNsはそのデバイス上の特定のアプリインストールを一意に識別する不透明なデバイストークンを生成します。アプリはこのトークンをバックエンドのプロバイダサーバーに送信します。プロバイダがユーザーに通知を送りたい場合、ペイロードを構築し、HTTP/2経由でデバイストークンとともにAPNsへ送信します。APNsはそのデバイスのアクティブな接続を特定し、プッシュ通知のペイロードをiOSへ直接配信します。その後、iOSが設定に応じてアラートを表示したりアプリを起床させたりします。
[Provider Server] ---> (HTTP/2 Request + Device Token + Payload) ---> [APNs]
|
(Persistent APNs Connection)
v
[iOS Device / App]
AI コーチを使ってこの質問に答えてみる