Section 14/181 menit

14. Integrasi dengan UIKit

14. Integrasi dengan UIKit

SwiftData tidak bergantung pada SwiftUI — bisa digunakan dengan UIKit via ModelContext langsung.

UIViewController dengan SwiftData

swift
import UIKit
import SwiftData

class TaskListViewController: UIViewController {
    private var modelContext: ModelContext
    private var tasks: [Task] = []
    private var tableView: UITableView!
    
    // Inject ModelContext dari AppDelegate/SceneDelegate
    init(modelContext: ModelContext) {
        self.modelContext = modelContext
        super.init(nibName: nil, bundle: nil)
    }
    
    required init?(coder: NSCoder) { fatalError() }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setupTableView()
        loadTasks()
        observeChanges()
    }
    
    private func loadTasks() {
        let descriptor = FetchDescriptor<Task>(
            predicate: #Predicate { !$0.isCompleted },
            sortBy: [SortDescriptor(\Task.createdAt, order: .reverse)]
        )
        tasks = (try? modelContext.fetch(descriptor)) ?? []
        tableView.reloadData()
    }
    
    // Observe perubahan via NotificationCenter (mirip NSFetchedResultsController)
    private func observeChanges() {
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(contextDidSave),
            name: ModelContext.didSave,
            object: nil
        )
    }
    
    @objc private func contextDidSave(_ notification: Notification) {
        DispatchQueue.main.async {
            self.loadTasks()  // Re-fetch setelah save
        }
    }
    
    private func addTask(title: String) {
        let task = Task(title: title, priority: "medium")
        modelContext.insert(task)
        try? modelContext.save()
        // contextDidSave akan trigger reload otomatis
    }
    
    private func deleteTask(at indexPath: IndexPath) {
        let task = tasks[indexPath.row]
        modelContext.delete(task)
        try? modelContext.save()
    }
}

Setup ModelContainer di AppDelegate

swift
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?
    
    // Share container ke seluruh app
    static var sharedModelContainer: ModelContainer = {
        let schema = Schema([Task.self, User.self, Project.self])
        let config = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false)
        return try! ModelContainer(for: schema, configurations: config)
    }()
    
    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        let container = AppDelegate.sharedModelContainer
        let context = container.mainContext
        
        let rootVC = TaskListViewController(modelContext: context)
        let navController = UINavigationController(rootViewController: rootVC)
        
        window = UIWindow(frame: UIScreen.main.bounds)
        window?.rootViewController = navController
        window?.makeKeyAndVisible()
        
        return true
    }
}