MENU

【Xcode便利機能】コメントアウトのMARK・TODO・FIXMEとは?使い方を徹底解説

Xcodeでコードを書いていると、ファイルが長くなって「あの関数どこだっけ?」と探すのに時間がかかることはありませんか?また、「後で実装しよう」と思ったことを忘れてしまった経験はないでしょうか。

実は、Xcodeには特殊なコメントマークを使って、コードを整理したりタスクを管理したりする便利な機能があります。この記事では、MARK、TODO、FIXMEをはじめとする、Xcodeで使える全てのコメントマークを初心者の方にもわかりやすく解説します。

目次

Xcodeのコメントマークとは?

Xcodeのコメントマークは、特定のキーワードを含むコメントを書くことで、コードの整理やタスク管理を助けてくれる機能です。

通常のコメントと同じように//で書きますが、特定のキーワード(MARK、TODO、FIXMEなど)を使うことで、Xcodeのジャンプバーに表示されたり、検索しやすくなったりします。

ジャンプバーとは?

ジャンプバーは、Xcodeのエディタ上部にある「現在編集している関数名やクラス名」が表示される部分です。この部分をクリックすると、ファイル内の構造やコメントマークが一覧表示され、すぐにジャンプできます。

Xcodeで使える6つのコメントマーク

それでは、Xcodeで使える主要なコメントマークを1つずつ見ていきましょう。

1. MARK: – コードのセクション分け

MARK:は、コードをセクションに分けて整理するためのマークです。大きなファイルを論理的なブロックに分割できます。

// MARK: - Properties

private var userName: String = ""
private var userAge: Int = 0

// MARK: - Initializer

init(name: String, age: Int) {
    self.userName = name
    self.userAge = age
}

// MARK: - Public Methods

func greet() {
    print("Hello, \(userName)!")
}

// MARK: - Private Methods

private func calculateAge() {
    // 処理
}

ポイント:

  • MARK:の後にハイフン-を付けると、ジャンプバーで区切り線が表示される
  • セクション名は自由に決められる
  • よく使われるセクション名:Properties、Initializer、Lifecycle、Setup、Actions、Public Methods、Private Methods

ジャンプバーでの表示:

MyClass
├─ Properties
├─ Initializer
├─ Public Methods
└─ Private Methods

2. TODO: – やるべきタスクの記録

TODO:は、後で実装する予定の機能や、やり残しているタスクを記録するマークです。

func loginUser(email: String, password: String) {
    // TODO: バリデーション処理を追加
    // TODO: パスワードの暗号化を実装
    // TODO: エラーハンドリングを追加
    
    // 仮の実装
    print("Login attempt")
}

使用場面:

  • 機能の未実装部分
  • 後回しにする改善点
  • まだ書いていないテストケース

具体例:

class ShoppingCartViewController: UIViewController {
    
    // TODO: Core Dataとの連携を実装
    private var cartItems: [Item] = []
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // TODO: 空のカート時のUIを実装
        setupTableView()
    }
    
    @IBAction func checkoutButtonTapped(_ sender: UIButton) {
        // TODO: 決済処理を実装
        showAlert(message: "準備中です")
    }
}

3. FIXME: – 修正が必要なバグ

FIXME:は、既知のバグや修正が必要な問題箇所を示すマークです。TODOよりも緊急度が高い問題に使います。

func calculateTotal(items: [Item]) -> Double {
    var total = 0.0
    
    for item in items {
        // FIXME: 消費税の計算が間違っている
        total += item.price * 1.08
    }
    
    return total
}

func formatDate(_ date: Date) -> String {
    let formatter = DateFormatter()
    // FIXME: タイムゾーンが考慮されていない
    formatter.dateFormat = "yyyy/MM/dd"
    return formatter.string(from: date)
}

TODOとFIXMEの使い分け:

  • TODO: 新しい機能の追加や改善(緊急度:低〜中)
  • FIXME: 既存のコードのバグや問題(緊急度:高)

4. WARNING: / !!!: – 重要な警告

WARNING:または!!!:は、コードを使う際の注意事項や警告を示すマークです。

class NetworkManager {
    
    // WARNING: このクラスはシングルトンとして使用すること
    static let shared = NetworkManager()
    
    private init() {}
    
    func fetchData(completion: @escaping (Data?) -> Void) {
        // !!!: この処理は時間がかかる可能性があります
        // メインスレッドで呼び出さないこと
        URLSession.shared.dataTask(with: url) { data, _, _ in
            completion(data)
        }.resume()
    }
}

// WARNING: 非推奨のAPIです。NewAPIを使用してください
@available(*, deprecated, message: "Use NewAPI instead")
func oldFunction() {
    // 処理
}

使用場面:

  • パフォーマンスに影響する処理
  • スレッドセーフティの注意
  • 非推奨のコードや関数
  • セキュリティ上の注意点

5. NOTE: – 重要な補足情報

NOTE:は、コードの動作に関する重要な補足情報を記載するマークです。

class ImageProcessor {
    
    func processImage(_ image: UIImage) -> UIImage {
        // NOTE: この処理はメモリを多く消費するため、
        // バックグラウンドスレッドで実行することを推奨
        let processedImage = applyFilters(to: image)
        return processedImage
    }
    
    private func saveToCache(_ image: UIImage, key: String) {
        // NOTE: キャッシュは24時間で自動削除されます
        cache.setObject(image, forKey: key as NSString)
    }
}

// NOTE: このViewControllerはStoryboardからのみ初期化可能
class ProfileViewController: UIViewController {
    @IBOutlet weak var nameLabel: UILabel!
}

使用場面:

  • 前提条件や制約
  • 仕様に関する重要な情報
  • 他の開発者への引き継ぎ事項

6. HACK: – 一時的な回避策

HACK:は、理想的ではないが動作する一時的な解決策を示すマークです。技術的負債として後で改善が必要なコードに使います。

func loadUserData() {
    // HACK: APIのバグのため、2回リクエストを送る必要がある
    // 本来は1回で取得できるべき
    fetchUserProfile { profile in
        self.fetchUserSettings { settings in
            self.updateUI(profile: profile, settings: settings)
        }
    }
}

class CustomButton: UIButton {
    override func layoutSubviews() {
        super.layoutSubviews()
        
        // HACK: Auto Layoutの不具合の回避策
        // iOS 15.0以降では不要になる予定
        DispatchQueue.main.async {
            self.layer.cornerRadius = self.bounds.height / 2
        }
    }
}

使用場面:

  • サードパーティライブラリのバグ回避
  • OSのバグの一時的な対応
  • パフォーマンスのための妥協案
  • リファクタリング予定のコード

実践的な使用例:ViewControllerの整理

実際のプロジェクトでこれらのマークをどう使うか、具体例を見てみましょう。

import UIKit

// MARK: - LoginViewController

class LoginViewController: UIViewController {
    
    // MARK: - Properties
    
    // NOTE: これらのOutletはStoryboardから接続されています
    @IBOutlet weak var emailTextField: UITextField!
    @IBOutlet weak var passwordTextField: UITextField!
    @IBOutlet weak var loginButton: UIButton!
    
    private var isLoading = false {
        didSet {
            updateLoadingState()
        }
    }
    
    // TODO: ログイン状態を保持する仕組みを実装
    
    // MARK: - Lifecycle
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setupUI()
        setupKeyboardHandling()
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        // FIXME: キーボードが表示されたままになる問題を修正
        emailTextField.becomeFirstResponder()
    }
    
    // MARK: - Setup
    
    private func setupUI() {
        loginButton.layer.cornerRadius = 8
        loginButton.backgroundColor = .systemBlue
    }
    
    private func setupKeyboardHandling() {
        // WARNING: キーボード通知の登録を忘れずに解除すること
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(keyboardWillShow),
            name: UIResponder.keyboardWillShowNotification,
            object: nil
        )
    }
    
    // MARK: - Actions
    
    @IBAction func loginButtonTapped(_ sender: UIButton) {
        guard validateInputs() else {
            showValidationError()
            return
        }
        
        performLogin()
    }
    
    @IBAction func forgotPasswordTapped(_ sender: UIButton) {
        // TODO: パスワードリセット画面への遷移を実装
        print("パスワードをお忘れですか?")
    }
    
    // MARK: - Validation
    
    private func validateInputs() -> Bool {
        // TODO: より厳密なバリデーションを追加
        // - メールアドレスの形式チェック
        // - パスワードの最小文字数チェック
        
        guard let email = emailTextField.text, !email.isEmpty else {
            return false
        }
        
        guard let password = passwordTextField.text, !password.isEmpty else {
            return false
        }
        
        return true
    }
    
    // MARK: - Network
    
    private func performLogin() {
        isLoading = true
        
        let email = emailTextField.text ?? ""
        let password = passwordTextField.text ?? ""
        
        // HACK: 本来はAPIクライアントを経由すべきだが、
        // 現状は直接URLSessionを使用
        let url = URL(string: "https://api.example.com/login")!
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        
        // !!!: パスワードは暗号化してから送信すること
        let body = ["email": email, "password": password]
        request.httpBody = try? JSONSerialization.data(withJSONObject: body)
        
        URLSession.shared.dataTask(with: request) { [weak self] data, response, error in
            DispatchQueue.main.async {
                self?.isLoading = false
                
                if let error = error {
                    // FIXME: エラーハンドリングが不十分
                    print("Error: \(error)")
                    return
                }
                
                self?.handleLoginSuccess()
            }
        }.resume()
    }
    
    // MARK: - UI Updates
    
    private func updateLoadingState() {
        loginButton.isEnabled = !isLoading
        loginButton.setTitle(isLoading ? "ログイン中..." : "ログイン", for: .normal)
    }
    
    private func handleLoginSuccess() {
        // TODO: ホーム画面への遷移を実装
        print("ログイン成功")
    }
    
    private func showValidationError() {
        let alert = UIAlertController(
            title: "エラー",
            message: "メールアドレスとパスワードを入力してください",
            preferredStyle: .alert
        )
        alert.addAction(UIAlertAction(title: "OK", style: .default))
        present(alert, animated: true)
    }
    
    // MARK: - Keyboard Handling
    
    @objc private func keyboardWillShow(_ notification: Notification) {
        // NOTE: キーボードの高さに応じてビューを調整
        guard let keyboardFrame = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect else {
            return
        }
        
        let keyboardHeight = keyboardFrame.height
        // 処理
    }
    
    // MARK: - Deinit
    
    deinit {
        // NOTE: 通知の登録を解除
        NotificationCenter.default.removeObserver(self)
    }
}

この例では、6つのコメントマークを適切に使い分けることで、コードの構造が明確になり、タスクや問題点も一目でわかるようになっています。

ジャンプバーでの活用方法

コメントマークを設定したら、ジャンプバーから素早くアクセスできます。

ジャンプバーの使い方

  1. エディタ上部のジャンプバー(現在のクラス名・関数名が表示されている部分)をクリック
  2. ファイルの構造とコメントマークが階層的に表示される
  3. 移動したい項目をクリックすると、その場所にジャンプ

ジャンプバーでの表示例

LoginViewController
├─ Properties
│  └─ emailTextField
│  └─ passwordTextField
│  └─ isLoading
├─ Lifecycle
│  └─ viewDidLoad()
│  └─ viewWillAppear(_:)
├─ Setup
│  └─ setupUI()
│  └─ setupKeyboardHandling()
├─ Actions
│  └─ loginButtonTapped(_:)
│  └─ forgotPasswordTapped(_:)
├─ Validation
├─ Network
├─ UI Updates
├─ Keyboard Handling
└─ Deinit

コメントマークを検索する方法

プロジェクト全体のTODOやFIXMEを一覧表示する方法を紹介します。

方法1: Xcodeの検索機能を使う

  1. ⌘ + Shift + F(プロジェクト内検索)を開く
  2. 検索ボックスに「TODO」「FIXME」などと入力
  3. プロジェクト全体のマークが一覧表示される

方法2: Show Document Items(推奨)

  1. エディタでファイルを開く
  2. Control + 6を押す
  3. ファイル内の全てのマークと関数が表示される
  4. 検索ボックスでフィルタリング可能

方法3: Find Navigatorを使う

  1. 左サイドバーの虫眼鏡アイコンをクリック
  2. 「Text」を選択して「TODO」「FIXME」で検索
  3. プロジェクト全体の該当箇所が表示される

コメントマークのベストプラクティス

効果的にコメントマークを使うためのポイントをまとめます。

1. 一貫性を保つ

チーム内で統一されたルールを決めましょう。

// ✅ 良い例:チーム全体で統一された書き方
// MARK: - Properties
// TODO: 認証機能を追加
// FIXME: メモリリークを修正

// ❌ 悪い例:バラバラな書き方
//MARK:Properties
// Todo: 認証機能を追加
//fixme メモリリークを修正

2. 具体的に書く

何をすべきか明確にしましょう。

// ✅ 良い例:具体的な内容
// TODO: UserDefaultsにログイン状態を保存する処理を追加
// FIXME: iOS 14以降で発生するクラッシュを修正(Issue #123参照)

// ❌ 悪い例:曖昧な内容
// TODO: 修正
// FIXME: バグ

3. 優先順位を明確にする

緊急度に応じて使い分けます。

緊急度 高: FIXME(バグや重大な問題)
緊急度 中: TODO(必要な機能追加)
緊急度 低: NOTE、HACK(情報共有や将来的な改善)

4. 期限や担当者を書く

チーム開発では特に有効です。

// TODO: [田中] v2.0リリースまでにプッシュ通知機能を実装
// FIXME: [佐藤] 2024/12/31までに修正(本番環境で発生中)

5. 解決したら削除する

コメントマークは一時的なものです。問題が解決したら削除しましょう。

6. MARKは大きな単位で使う

細かすぎる分割は逆に見づらくなります。

// ✅ 良い例:適切な粒度
// MARK: - Properties
// MARK: - Lifecycle
// MARK: - Public Methods
// MARK: - Private Methods

// ❌ 悪い例:細かすぎる
// MARK: - プロパティ1
// MARK: - プロパティ2
// MARK: - プロパティ3

チーム開発での活用テクニック

コードレビューでの活用

// TODO: [レビュー待ち] この実装で問題ないか確認してください
func complexCalculation() -> Double {
    // 複雑な計算処理
}

イシュー番号との連携

// FIXME: Issue #456 - ログイン後にクラッシュする問題
// TODO: Issue #789 - ダークモード対応

バージョン情報の記載

// TODO: v2.0で実装予定
// FIXME: v1.5で削除予定(非推奨API使用中)

まとめ

この記事では、Xcodeで使える6つのコメントマークを解説しました。

コメントマークの使い分け:

  • MARK: コードのセクション分け
  • TODO: 未実装の機能や改善点
  • FIXME: 既知のバグや修正箇所
  • WARNING/!!!: 重要な警告や注意事項
  • NOTE: 補足情報や仕様の説明
  • HACK: 一時的な回避策

活用のポイント:

  • ジャンプバーで素早くナビゲーション
  • 検索機能でタスク管理
  • チーム内で統一したルールを決める
  • 具体的で明確な内容を書く
  • 解決したら削除する

これらのコメントマークを効果的に使うことで、コードの可読性が向上し、タスク管理もスムーズになります。特に大規模なプロジェクトやチーム開発では、威力を発揮する機能です。

プログラミングの独学におすすめ
プログラミング言語の人気オンラインコース
独学でプログラミングを学習している方で、エラーなどが発生して効率よく勉強ができないと悩む方は多いはず。Udemyは、プロの講師が動画で実際のプログラムを動かしながら教えてくれるオンライン講座です。講座の価格は、セール期間中には専門書籍を1冊買うよりも安く済むことが多いです。新しく学びたいプログラミング言語がある方は、ぜひUdemyでオンライン講座を探してみてください。
目次