コンテンツにスキップ

Xcode Cheatsheet

Xcode - Apple's Integrated Development Environment

Xcode is Apple's integrated development environment (IDE) for macOS, used to develop software for macOS, iOS, iPadOS, watchOS, and tvOS. It includes a suite of software development tools including a source code editor, debugger, and graphical user interface builder.

Table of Contents

Installation

System Requirements

# macOS 12.5 or later
# At least 8GB of RAM (16GB recommended)
# At least 50GB of available disk space

# Check macOS version
sw_vers

# Check available disk space
df -h

Download and Install

# Download from Mac App Store
# Search for "Xcode" and click "Get"

# Or download from Apple Developer Portal
# https://developer.apple.com/xcode/

# Command Line Tools (if needed separately)
xcode-select --install

# Verify installation
xcode-select -p
xcodebuild -version

First Launch Setup

# Accept license agreement
sudo xcodebuild -license accept

# Install additional components when prompted
# iOS Simulator, watchOS Simulator, etc.

# Set up Apple ID for development
# Xcode > Preferences > Accounts > Add Apple ID

Getting Started

Create New Project

// File > New > Project
// Choose template:
// - iOS App
// - macOS App
// - watchOS App
// - tvOS App
// - Multiplatform App

// Project configuration:
// Product Name: MyApp
// Team: Your Development Team
// Organization Identifier: com.yourname.myapp
// Bundle Identifier: com.yourname.myapp
// Language: Swift
// Interface: SwiftUI or Storyboard
// Use Core Data: Optional
// Include Tests: Recommended

Project Templates

// iOS App with UIKit
class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        return true
    }
}

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    var window: UIWindow?

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        guard let windowScene = (scene as? UIWindowScene) else { return }
        window = UIWindow(windowScene: windowScene)
        window?.rootViewController = ViewController()
        window?.makeKeyAndVisible()
    }
}

// iOS App with SwiftUI
@main
struct MyApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

struct ContentView: View {
    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundColor(.accentColor)
            Text("Hello, world!")
        }
        .padding()
    }
}

Project Structure

MyApp.xcodeproj/
├── MyApp/
│   ├── AppDelegate.swift
│   ├── SceneDelegate.swift
│   ├── ViewController.swift
│   ├── Main.storyboard
│   ├── Assets.xcassets
│   ├── LaunchScreen.storyboard
│   ├── Info.plist
│   ├── Models/
│   ├── Views/
│   ├── Controllers/
│   └── Services/
├── MyAppTests/
│   └── MyAppTests.swift
├── MyAppUITests/
│   └── MyAppUITests.swift
└── Products/
    └── MyApp.app

Interface Builder

Storyboard Basics

// Creating outlets
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var submitButton: UIButton!
@IBOutlet weak var textField: UITextField!

// Creating actions
@IBAction func submitButtonTapped(_ sender: UIButton) {
    guard let text = textField.text, !text.isEmpty else {
        showAlert(message: "Please enter some text")
        return
    }

    titleLabel.text = text
    textField.text = ""
}

// Segues
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "showDetail" {
        if let detailVC = segue.destination as? DetailViewController {
            detailVC.data = selectedData
        }
    }
}

// Programmatic segue
performSegue(withIdentifier: "showDetail", sender: self)

Auto Layout

// Programmatic constraints
view.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
    view.topAnchor.constraint(equalTo: superview.safeAreaLayoutGuide.topAnchor, constant: 20),
    view.leadingAnchor.constraint(equalTo: superview.leadingAnchor, constant: 16),
    view.trailingAnchor.constraint(equalTo: superview.trailingAnchor, constant: -16),
    view.heightAnchor.constraint(equalToConstant: 50)
])

// Using NSLayoutAnchor
let constraints = [
    titleLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor),
    titleLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor),

    submitButton.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 20),
    submitButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
    submitButton.widthAnchor.constraint(equalToConstant: 200),
    submitButton.heightAnchor.constraint(equalToConstant: 44)
]
NSLayoutConstraint.activate(constraints)

// Stack Views
let stackView = UIStackView(arrangedSubviews: [titleLabel, submitButton])
stackView.axis = .vertical
stackView.spacing = 20
stackView.alignment = .center
stackView.distribution = .fill

Custom Views

@IBDesignable
class CustomButton: UIButton {

    @IBInspectable var cornerRadius: CGFloat = 0 {
        didSet {
            layer.cornerRadius = cornerRadius
        }
    }

    @IBInspectable var borderWidth: CGFloat = 0 {
        didSet {
            layer.borderWidth = borderWidth
        }
    }

    @IBInspectable var borderColor: UIColor = .clear {
        didSet {
            layer.borderColor = borderColor.cgColor
        }
    }

    override func prepareForInterfaceBuilder() {
        super.prepareForInterfaceBuilder()
        layer.cornerRadius = cornerRadius
        layer.borderWidth = borderWidth
        layer.borderColor = borderColor.cgColor
    }
}

Swift Programming

Basic Syntax

// Variables and Constants
var mutableVariable = "Hello"
let immutableConstant = "World"

// Data Types
let integer: Int = 42
let double: Double = 3.14159
let float: Float = 2.718
let boolean: Bool = true
let string: String = "Swift"

// Optionals
var optionalString: String? = "Optional"
var implicitlyUnwrappedOptional: String! = "Implicitly Unwrapped"

// Optional Binding
if let unwrappedString = optionalString {
    print("Value: \(unwrappedString)")
}

// Guard Statement
guard let unwrappedString = optionalString else {
    return
}

// Nil Coalescing
let result = optionalString ?? "Default Value"

Functions and Closures

// Functions
func greet(name: String, age: Int = 25) -> String {
    return "Hello, \(name)! You are \(age) years old."
}

// Function with multiple return values
func minMax(array: [Int]) -> (min: Int, max: Int)? {
    guard !array.isEmpty else { return nil }

    var currentMin = array[0]
    var currentMax = array[0]

    for value in array[1..<array.count] {
        if value < currentMin {
            currentMin = value
        } else if value > currentMax {
            currentMax = value
        }
    }

    return (currentMin, currentMax)
}

// Closures
let numbers = [1, 2, 3, 4, 5]
let doubled = numbers.map { $0 * 2 }
let filtered = numbers.filter { $0 > 2 }
let sum = numbers.reduce(0) { $0 + $1 }

// Trailing closure syntax
UIView.animate(withDuration: 0.3) {
    self.view.alpha = 0.5
}

Classes and Structures

// Structure
struct Person {
    var name: String
    var age: Int

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

    func greet() -> String {
        return "Hello, I'm \(name) and I'm \(age) years old."
    }

    mutating func haveBirthday() {
        age += 1
    }
}

// Class
class Vehicle {
    var brand: String
    var model: String
    var year: Int

    init(brand: String, model: String, year: Int) {
        self.brand = brand
        self.model = model
        self.year = year
    }

    func description() -> String {
        return "\(year) \(brand) \(model)"
    }
}

// Inheritance
class Car: Vehicle {
    var numberOfDoors: Int

    init(brand: String, model: String, year: Int, numberOfDoors: Int) {
        self.numberOfDoors = numberOfDoors
        super.init(brand: brand, model: model, year: year)
    }

    override func description() -> String {
        return "\(super.description()) with \(numberOfDoors) doors"
    }
}

// Protocols
protocol Drawable {
    func draw()
}

extension Car: Drawable {
    func draw() {
        print("Drawing a car: \(description())")
    }
}

Error Handling

// Define errors
enum NetworkError: Error {
    case invalidURL
    case noData
    case decodingError
}

// Throwing function
func fetchData(from urlString: String) throws -> Data {
    guard let url = URL(string: urlString) else {
        throw NetworkError.invalidURL
    }

    // Simulate network call
    guard let data = "Sample data".data(using: .utf8) else {
        throw NetworkError.noData
    }

    return data
}

// Error handling
do {
    let data = try fetchData(from: "https://api.example.com")
    print("Received data: \(data)")
} catch NetworkError.invalidURL {
    print("Invalid URL provided")
} catch NetworkError.noData {
    print("No data received")
} catch {
    print("Unknown error: \(error)")
}

// Try? and try!
let optionalData = try? fetchData(from: "https://api.example.com")
// let forcedData = try! fetchData(from: "https://api.example.com") // Use with caution

UIKit Development

View Controllers

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        setupUI()
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        // View is about to appear
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        // View has appeared
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        // View is about to disappear
    }

    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        // View has disappeared
    }

    private func setupUI() {
        view.backgroundColor = .systemBackground
        title = "My View Controller"

        // Add navigation bar button
        navigationItem.rightBarButtonItem = UIBarButtonItem(
            barButtonSystemItem: .add,
            target: self,
            action: #selector(addButtonTapped)
        )
    }

    @objc private func addButtonTapped() {
        // Handle add button tap
    }
}

Table Views

class TableViewController: UIViewController {
    @IBOutlet weak var tableView: UITableView!

    private var items = ["Item 1", "Item 2", "Item 3"]

    override func viewDidLoad() {
        super.viewDidLoad()
        setupTableView()
    }

    private func setupTableView() {
        tableView.dataSource = self
        tableView.delegate = self
        tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
    }
}

extension TableViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return items.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
        cell.textLabel?.text = items[indexPath.row]
        return cell
    }
}

extension TableViewController: UITableViewDelegate {
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
        print("Selected: \(items[indexPath.row])")
    }

    func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
        if editingStyle == .delete {
            items.remove(at: indexPath.row)
            tableView.deleteRows(at: [indexPath], with: .fade)
        }
    }
}

Collection Views

class CollectionViewController: UIViewController {
    @IBOutlet weak var collectionView: UICollectionView!

    private var items = Array(1...20)

    override func viewDidLoad() {
        super.viewDidLoad()
        setupCollectionView()
    }

    private func setupCollectionView() {
        collectionView.dataSource = self
        collectionView.delegate = self

        let layout = UICollectionViewFlowLayout()
        layout.itemSize = CGSize(width: 100, height: 100)
        layout.minimumInteritemSpacing = 10
        layout.minimumLineSpacing = 10
        collectionView.collectionViewLayout = layout

        collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "Cell")
    }
}

extension CollectionViewController: UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return items.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath)
        cell.backgroundColor = .systemBlue
        return cell
    }
}

extension CollectionViewController: UICollectionViewDelegate {
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        print("Selected item: \(items[indexPath.item])")
    }
}
// Push view controller
let detailVC = DetailViewController()
navigationController?.pushViewController(detailVC, animated: true)

// Present modally
let modalVC = ModalViewController()
let navController = UINavigationController(rootViewController: modalVC)
present(navController, animated: true)

// Dismiss modal
dismiss(animated: true)

// Pop view controller
navigationController?.popViewController(animated: true)

// Pop to root
navigationController?.popToRootViewController(animated: true)

// Tab Bar Controller
let firstVC = FirstViewController()
let secondVC = SecondViewController()

firstVC.tabBarItem = UITabBarItem(title: "First", image: UIImage(systemName: "1.circle"), tag: 0)
secondVC.tabBarItem = UITabBarItem(title: "Second", image: UIImage(systemName: "2.circle"), tag: 1)

let tabBarController = UITabBarController()
tabBarController.viewControllers = [firstVC, secondVC]

SwiftUI Development

Basic Views

import SwiftUI

struct ContentView: View {
    @State private var name = ""
    @State private var isToggled = false
    @State private var selectedOption = 0

    var body: some View {
        NavigationView {
            VStack(spacing: 20) {
                // Text
                Text("Hello, SwiftUI!")
                    .font(.largeTitle)
                    .foregroundColor(.blue)

                // Image
                Image(systemName: "star.fill")
                    .font(.system(size: 50))
                    .foregroundColor(.yellow)

                // TextField
                TextField("Enter your name", text: $name)
                    .textFieldStyle(RoundedBorderTextFieldStyle())
                    .padding(.horizontal)

                // Button
                Button("Tap Me") {
                    print("Button tapped!")
                }
                .buttonStyle(.borderedProminent)

                // Toggle
                Toggle("Enable notifications", isOn: $isToggled)
                    .padding(.horizontal)

                // Picker
                Picker("Options", selection: $selectedOption) {
                    Text("Option 1").tag(0)
                    Text("Option 2").tag(1)
                    Text("Option 3").tag(2)
                }
                .pickerStyle(SegmentedPickerStyle())
                .padding(.horizontal)

                Spacer()
            }
            .navigationTitle("SwiftUI Demo")
        }
    }
}

Lists and Navigation

struct Item: Identifiable {
    let id = UUID()
    let name: String
    let description: String
}

struct ListView: View {
    let items = [
        Item(name: "Item 1", description: "Description 1"),
        Item(name: "Item 2", description: "Description 2"),
        Item(name: "Item 3", description: "Description 3")
    ]

    var body: some View {
        NavigationView {
            List(items) { item in
                NavigationLink(destination: DetailView(item: item)) {
                    VStack(alignment: .leading) {
                        Text(item.name)
                            .font(.headline)
                        Text(item.description)
                            .font(.subheadline)
                            .foregroundColor(.secondary)
                    }
                }
            }
            .navigationTitle("Items")
        }
    }
}

struct DetailView: View {
    let item: Item

    var body: some View {
        VStack {
            Text(item.name)
                .font(.largeTitle)
                .padding()

            Text(item.description)
                .font(.body)
                .padding()

            Spacer()
        }
        .navigationTitle("Detail")
        .navigationBarTitleDisplayMode(.inline)
    }
}

State Management

// ObservableObject
class UserData: ObservableObject {
    @Published var username = ""
    @Published var isLoggedIn = false

    func login() {
        isLoggedIn = true
    }

    func logout() {
        isLoggedIn = false
        username = ""
    }
}

// Using ObservableObject
struct LoginView: View {
    @StateObject private var userData = UserData()

    var body: some View {
        VStack {
            if userData.isLoggedIn {
                Text("Welcome, \(userData.username)!")
                Button("Logout") {
                    userData.logout()
                }
            } else {
                TextField("Username", text: $userData.username)
                    .textFieldStyle(RoundedBorderTextFieldStyle())

                Button("Login") {
                    userData.login()
                }
                .disabled(userData.username.isEmpty)
            }
        }
        .padding()
    }
}

// Environment Objects
struct ParentView: View {
    @StateObject private var userData = UserData()

    var body: some View {
        ChildView()
            .environmentObject(userData)
    }
}

struct ChildView: View {
    @EnvironmentObject var userData: UserData

    var body: some View {
        Text("User: \(userData.username)")
    }
}

Custom Modifiers

struct CardModifier: ViewModifier {
    func body(content: Content) -> some View {
        content
            .padding()
            .background(Color.white)
            .cornerRadius(10)
            .shadow(radius: 5)
    }
}

extension View {
    func cardStyle() -> some View {
        modifier(CardModifier())
    }
}

// Usage
Text("Hello, World!")
    .cardStyle()

Core Data

Data Model

// Create .xcdatamodeld file
// Add Entity: Person
// Add Attributes: name (String), age (Int16), email (String)

import CoreData

// NSManagedObject subclass
@objc(Person)
public class Person: NSManagedObject {

}

extension Person {
    @nonobjc public class func fetchRequest() -> NSFetchRequest<Person> {
        return NSFetchRequest<Person>(entityName: "Person")
    }

    @NSManaged public var name: String?
    @NSManaged public var age: Int16
    @NSManaged public var email: String?
}

Core Data Stack

import CoreData

class CoreDataManager {
    static let shared = CoreDataManager()

    private init() {}

    lazy var persistentContainer: NSPersistentContainer = {
        let container = NSPersistentContainer(name: "DataModel")
        container.loadPersistentStores { _, error in
            if let error = error {
                fatalError("Core Data error: \(error)")
            }
        }
        return container
    }()

    var context: NSManagedObjectContext {
        return persistentContainer.viewContext
    }

    func saveContext() {
        if context.hasChanges {
            do {
                try context.save()
            } catch {
                print("Save error: \(error)")
            }
        }
    }
}

CRUD Operations

class PersonService {
    private let coreDataManager = CoreDataManager.shared

    // Create
    func createPerson(name: String, age: Int16, email: String) {
        let person = Person(context: coreDataManager.context)
        person.name = name
        person.age = age
        person.email = email

        coreDataManager.saveContext()
    }

    // Read
    func fetchAllPersons() -> [Person] {
        let request: NSFetchRequest<Person> = Person.fetchRequest()

        do {
            return try coreDataManager.context.fetch(request)
        } catch {
            print("Fetch error: \(error)")
            return []
        }
    }

    func fetchPersons(with name: String) -> [Person] {
        let request: NSFetchRequest<Person> = Person.fetchRequest()
        request.predicate = NSPredicate(format: "name CONTAINS[cd] %@", name)
        request.sortDescriptors = [NSSortDescriptor(key: "name", ascending: true)]

        do {
            return try coreDataManager.context.fetch(request)
        } catch {
            print("Fetch error: \(error)")
            return []
        }
    }

    // Update
    func updatePerson(_ person: Person, name: String, age: Int16, email: String) {
        person.name = name
        person.age = age
        person.email = email

        coreDataManager.saveContext()
    }

    // Delete
    func deletePerson(_ person: Person) {
        coreDataManager.context.delete(person)
        coreDataManager.saveContext()
    }
}

Networking

URLSession

import Foundation

class NetworkManager {
    static let shared = NetworkManager()

    private init() {}

    func fetchData<T: Codable>(from url: URL, type: T.Type, completion: @escaping (Result<T, Error>) -> Void) {
        URLSession.shared.dataTask(with: url) { data, response, error in
            if let error = error {
                completion(.failure(error))
                return
            }

            guard let data = data else {
                completion(.failure(NetworkError.noData))
                return
            }

            do {
                let decodedData = try JSONDecoder().decode(type, from: data)
                completion(.success(decodedData))
            } catch {
                completion(.failure(error))
            }
        }.resume()
    }

    func postData<T: Codable>(to url: URL, body: Data, type: T.Type, completion: @escaping (Result<T, Error>) -> Void) {
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        request.httpBody = body

        URLSession.shared.dataTask(with: request) { data, response, error in
            if let error = error {
                completion(.failure(error))
                return
            }

            guard let data = data else {
                completion(.failure(NetworkError.noData))
                return
            }

            do {
                let decodedData = try JSONDecoder().decode(type, from: data)
                completion(.success(decodedData))
            } catch {
                completion(.failure(error))
            }
        }.resume()
    }
}

enum NetworkError: Error {
    case noData
    case invalidURL
    case decodingError
}

// Usage
struct Post: Codable {
    let id: Int
    let title: String
    let body: String
    let userId: Int
}

class PostService {
    func fetchPosts(completion: @escaping (Result<[Post], Error>) -> Void) {
        guard let url = URL(string: "https://jsonplaceholder.typicode.com/posts") else {
            completion(.failure(NetworkError.invalidURL))
            return
        }

        NetworkManager.shared.fetchData(from: url, type: [Post].self, completion: completion)
    }
}

Async/Await (iOS 15+)

class ModernNetworkManager {
    static let shared = ModernNetworkManager()

    private init() {}

    func fetchData<T: Codable>(from url: URL, type: T.Type) async throws -> T {
        let (data, _) = try await URLSession.shared.data(from: url)
        return try JSONDecoder().decode(type, from: data)
    }

    func postData<T: Codable>(to url: URL, body: Data, type: T.Type) async throws -> T {
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        request.httpBody = body

        let (data, _) = try await URLSession.shared.data(for: request)
        return try JSONDecoder().decode(type, from: data)
    }
}

// Usage with async/await
class ModernPostService {
    func fetchPosts() async throws -> [Post] {
        guard let url = URL(string: "https://jsonplaceholder.typicode.com/posts") else {
            throw NetworkError.invalidURL
        }

        return try await ModernNetworkManager.shared.fetchData(from: url, type: [Post].self)
    }
}

// In SwiftUI
struct PostsView: View {
    @State private var posts: [Post] = []
    @State private var isLoading = false

    var body: some View {
        NavigationView {
            List(posts, id: \.id) { post in
                VStack(alignment: .leading) {
                    Text(post.title)
                        .font(.headline)
                    Text(post.body)
                        .font(.caption)
                        .foregroundColor(.secondary)
                }
            }
            .navigationTitle("Posts")
            .task {
                await loadPosts()
            }
        }
    }

    private func loadPosts() async {
        isLoading = true
        do {
            posts = try await ModernPostService().fetchPosts()
        } catch {
            print("Error loading posts: \(error)")
        }
        isLoading = false
    }
}

Testing

Unit Testing

import XCTest
@testable import MyApp

class CalculatorTests: XCTestCase {

    var calculator: Calculator!

    override func setUpWithError() throws {
        calculator = Calculator()
    }

    override func tearDownWithError() throws {
        calculator = nil
    }

    func testAddition() {
        let result = calculator.add(2, 3)
        XCTAssertEqual(result, 5)
    }

    func testDivisionByZero() {
        XCTAssertThrowsError(try calculator.divide(10, 0)) { error in
            XCTAssertEqual(error as? CalculatorError, CalculatorError.divisionByZero)
        }
    }

    func testAsyncOperation() async throws {
        let result = try await calculator.asyncCalculation()
        XCTAssertGreaterThan(result, 0)
    }

    func testPerformance() {
        measure {
            for _ in 0..<1000 {
                _ = calculator.complexCalculation()
            }
        }
    }
}

UI Testing

import XCTest

class MyAppUITests: XCTestCase {

    var app: XCUIApplication!

    override func setUpWithError() throws {
        continueAfterFailure = false
        app = XCUIApplication()
        app.launch()
    }

    func testLoginFlow() throws {
        let usernameTextField = app.textFields["Username"]
        let passwordSecureTextField = app.secureTextFields["Password"]
        let loginButton = app.buttons["Login"]

        XCTAssertTrue(usernameTextField.exists)
        XCTAssertTrue(passwordSecureTextField.exists)
        XCTAssertTrue(loginButton.exists)

        usernameTextField.tap()
        usernameTextField.typeText("testuser")

        passwordSecureTextField.tap()
        passwordSecureTextField.typeText("password123")

        loginButton.tap()

        let welcomeLabel = app.staticTexts["Welcome"]
        XCTAssertTrue(welcomeLabel.waitForExistence(timeout: 5))
    }

    func testTableViewNavigation() throws {
        let tableView = app.tables["ItemsTable"]
        XCTAssertTrue(tableView.exists)

        let firstCell = tableView.cells.element(boundBy: 0)
        firstCell.tap()

        let detailView = app.navigationBars["Detail"]
        XCTAssertTrue(detailView.waitForExistence(timeout: 5))

        let backButton = app.navigationBars.buttons.element(boundBy: 0)
        backButton.tap()

        XCTAssertTrue(tableView.waitForExistence(timeout: 5))
    }
}

Debugging

Breakpoints

// Set breakpoints by clicking on line numbers
// Conditional breakpoints: Right-click breakpoint > Edit Breakpoint

func processData(_ data: [String]) {
    for (index, item) in data.enumerated() {
        // Set conditional breakpoint: index == 5
        print("Processing: \(item)")

        // Symbolic breakpoint for specific method calls
        // Debug > Breakpoints > Create Symbolic Breakpoint
        // Symbol: -[UIViewController viewDidLoad]
    }
}
// Basic print
print("Debug message")

// Print with separator and terminator
print("Value 1", "Value 2", separator: " | ", terminator: "\n")

// Debug print (only in debug builds)
debugPrint("Debug information")

// Custom debug description
extension Person: CustomDebugStringConvertible {
    var debugDescription: String {
        return "Person(name: \(name ?? "nil"), age: \(age))"
    }
}

// Dump for detailed object inspection
dump(person)

// Assert for debugging
assert(age >= 0, "Age cannot be negative")

// Precondition for runtime checks
precondition(users.count > 0, "Users array cannot be empty")

Instruments

# Launch Instruments
# Product > Profile (Cmd+I)

# Common instruments:
# - Time Profiler: CPU usage analysis
# - Allocations: Memory usage tracking
# - Leaks: Memory leak detection
# - Energy Log: Battery usage analysis
# - Network: Network activity monitoring

Performance

Memory Management

// Weak references to avoid retain cycles
class Parent {
    var children: [Child] = []
}

class Child {
    weak var parent: Parent?
}

// Unowned references (use when reference will never be nil)
class Customer {
    let name: String
    var card: CreditCard?

    init(name: String) {
        self.name = name
    }
}

class CreditCard {
    let number: UInt64
    unowned let customer: Customer

    init(number: UInt64, customer: Customer) {
        self.number = number
        self.customer = customer
    }
}

// Capture lists in closures
class ViewController: UIViewController {
    var completion: (() -> Void)?

    func setupCompletion() {
        // Strong reference cycle
        completion = {
            self.dismiss(animated: true)
        }

        // Weak reference to avoid cycle
        completion = { [weak self] in
            self?.dismiss(animated: true)
        }

        // Unowned reference (use when self will never be nil)
        completion = { [unowned self] in
            self.dismiss(animated: true)
        }
    }
}

Optimization Techniques

// Lazy properties
class DataManager {
    lazy var expensiveResource: ExpensiveResource = {
        return ExpensiveResource()
    }()
}

// Computed properties with caching
class Calculator {
    private var _cachedResult: Double?
    private var _lastInput: Double?

    func expensiveCalculation(input: Double) -> Double {
        if let cached = _cachedResult, _lastInput == input {
            return cached
        }

        let result = performExpensiveCalculation(input)
        _cachedResult = result
        _lastInput = input
        return result
    }

    private func performExpensiveCalculation(_ input: Double) -> Double {
        // Expensive calculation here
        return input * input
    }
}

// Efficient collection operations
let numbers = Array(1...1000000)

// Use lazy evaluation for chained operations
let result = numbers
    .lazy
    .filter { $0 % 2 == 0 }
    .map { $0 * 2 }
    .prefix(10)
    .reduce(0, +)

// Use appropriate collection types
var uniqueItems = Set<String>() // O(1) lookup
var orderedItems = [String]() // O(1) append, O(n) search
var keyValuePairs = [String: Any]() // O(1) lookup by key

App Store Connect

App Configuration

// Info.plist configuration
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>CFBundleDisplayName</key>
    <string>My App</string>
    <key>CFBundleIdentifier</key>
    <string>com.yourcompany.myapp</string>
    <key>CFBundleVersion</key>
    <string>1</string>
    <key>CFBundleShortVersionString</key>
    <string>1.0</string>
    <key>LSRequiresIPhoneOS</key>
    <true/>
    <key>UIRequiredDeviceCapabilities</key>
    <array>
        <string>armv7</string>
    </array>
    <key>UISupportedInterfaceOrientations</key>
    <array>
        <string>UIInterfaceOrientationPortrait</string>
        <string>UIInterfaceOrientationLandscapeLeft</string>
        <string>UIInterfaceOrientationLandscapeRight</string>
    </array>
</dict>
</plist>

Build and Archive

# Archive for distribution
# Product > Archive

# Validate archive
# Window > Organizer > Archives > Validate App

# Distribute archive
# Window > Organizer > Archives > Distribute App
# Choose distribution method:
# - App Store Connect
# - Ad Hoc
# - Enterprise
# - Development

App Store Submission

# Upload to App Store Connect
# Use Xcode Organizer or Application Loader

# App Store Connect configuration:
# - App Information
# - Pricing and Availability
# - App Store Information
# - Screenshots and Previews
# - App Review Information
# - Version Information
# - Build selection

# Submit for Review
# App Store Connect > My Apps > Your App > Submit for Review

Keyboard Shortcuts

# File Navigation
Cmd+Shift+O         # Open Quickly
Cmd+Shift+J         # Reveal in Navigator
Cmd+Ctrl+Up         # Switch between .h and .m files
Cmd+Ctrl+Left/Right # Navigate back/forward

# Code Navigation
Ctrl+6              # Jump to method/function
Cmd+L               # Go to line
Cmd+Shift+F         # Find in project
Cmd+Shift+G         # Find next

Editing

# Code Editing
Cmd+/               # Comment/uncomment
Cmd+[               # Shift left
Cmd+]               # Shift right
Cmd+Ctrl+E          # Edit all in scope
Cmd+Shift+A         # Add documentation

# Refactoring
Cmd+Ctrl+E          # Rename
Cmd+Shift+A         # Add documentation

Building and Running

# Build and Run
Cmd+R               # Run
Cmd+B               # Build
Cmd+Shift+K         # Clean
Cmd+U               # Test
Cmd+I               # Profile
Cmd+.               # Stop

Debugging

# Debugging
F6                  # Step over
F7                  # Step into
F8                  # Step out
Cmd+Ctrl+Y          # Continue
Cmd+Y               # Activate/deactivate breakpoints

Best Practices

Code Organization

// MARK: - Use MARK comments for organization
class ViewController: UIViewController {

    // MARK: - Properties
    @IBOutlet weak var tableView: UITableView!
    private var dataSource: [String] = []

    // MARK: - Lifecycle
    override func viewDidLoad() {
        super.viewDidLoad()
        setupUI()
    }

    // MARK: - Setup
    private func setupUI() {
        // UI setup code
    }

    // MARK: - Actions
    @IBAction func buttonTapped(_ sender: UIButton) {
        // Action handling
    }

    // MARK: - Private Methods
    private func updateData() {
        // Private method implementation
    }
}

// MARK: - Extensions for protocol conformance
extension ViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return dataSource.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        // Cell configuration
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
        cell.textLabel?.text = dataSource[indexPath.row]
        return cell
    }
}

Error Handling

// Use Result type for better error handling
enum APIError: Error {
    case networkError
    case decodingError
    case serverError(Int)
}

func fetchData(completion: @escaping (Result<[Item], APIError>) -> Void) {
    // Implementation
}

// Use do-catch for throwing functions
do {
    let data = try JSONSerialization.data(withJSONObject: dictionary)
    // Process data
} catch {
    print("JSON serialization failed: \(error)")
}

// Use guard for early returns
func processUser(_ user: User?) {
    guard let user = user else {
        print("User is nil")
        return
    }

    guard user.isActive else {
        print("User is not active")
        return
    }

    // Process active user
}

Performance

// Use appropriate data structures
// Array for ordered collections
// Set for unique items with fast lookup
// Dictionary for key-value pairs

// Avoid force unwrapping
// Use optional binding or nil coalescing instead
if let value = optionalValue {
    // Use value
}

let finalValue = optionalValue ?? defaultValue

// Use weak references in delegates
protocol MyDelegate: AnyObject {
    func didComplete()
}

class MyClass {
    weak var delegate: MyDelegate?
}

Troubleshooting

Common Build Errors

# Clean build folder
Product > Clean Build Folder (Cmd+Shift+K)

# Reset simulator
Device > Erase All Content and Settings

# Clear derived data
~/Library/Developer/Xcode/DerivedData
# Delete the folder for your project

# Update provisioning profiles
Xcode > Preferences > Accounts > Download Manual Profiles

# Fix code signing issues
Project Settings > Signing & Capabilities
# Ensure correct team and bundle identifier

Runtime Issues

// Debug memory issues
// Enable Address Sanitizer in scheme settings
// Edit Scheme > Run > Diagnostics > Address Sanitizer

// Debug UI issues on main thread
// Edit Scheme > Run > Diagnostics > Main Thread Checker

// Debug view hierarchy
// Debug > View Debugging > Capture View Hierarchy

// Check for retain cycles
// Debug Memory Graph (Debug navigator)

Simulator Issues

# Reset simulator
Device > Erase All Content and Settings

# Restart simulator
Device > Restart

# Reset simulator to factory settings
xcrun simctl erase all

# List available simulators
xcrun simctl list devices

# Boot specific simulator
xcrun simctl boot "iPhone 14 Pro"

Summary

Xcode is Apple's comprehensive IDE for developing applications across all Apple platforms. Key features include:

  • Integrated Development Environment: Complete toolchain for iOS, macOS, watchOS, and tvOS development
  • Interface Builder: Visual design tool for creating user interfaces
  • Swift and Objective-C Support: Full language support with syntax highlighting and code completion
  • Simulator: Test apps on various device configurations without physical hardware
  • Debugging Tools: Powerful debugger with breakpoints, memory analysis, and performance profiling
  • Testing Framework: Built-in unit testing and UI testing capabilities
  • Instruments: Performance analysis tools for memory, CPU, and energy usage
  • App Store Integration: Seamless app submission and distribution workflow
  • Version Control: Built-in Git support with visual diff and merge tools
  • Documentation: Integrated documentation browser and code documentation generation

Xcode provides everything needed to create, test, debug, and distribute high-quality applications for Apple's ecosystem, making it the essential tool for Apple platform development.