Core Application Architecture & Objective-C/SwiftUI Bridging Foundation #1

Closed
opened 2026-09-08 10:18:10 +01:00 by gronod · 2 comments
Owner

Purpose

Establish the core macOS application architecture combining a SwiftUI presentation layer with an Objective-C low-level telemetry subsystem. This foundation serves as the backbone for all hardware, kernel, and process monitoring features on Intel Mac platforms running macOS 14 Sonoma or higher.

Priority

Critical (Foundation for all telemetry modules and UI)

Dependencies

  • None (Root architecture)

Scope

  • macOS app bundle targeting x86_64 architecture with a minimum deployment target of macOS 14.0 (Sonoma).
  • Objective-C bridging layer (MacMonitor-Bridging-Header.h) to encapsulate direct interactions with Mach kernel, IOKit, BSD sysctl, and CoreFoundation C APIs.
  • Background telemetry dispatch coordinator managing recurring sampling cycles with configurable polling frequencies (e.g. 1s, 2s, 5s) and minimal CPU footprint.
  • Thread-safe data repositories exposing published observable models for SwiftUI reactive updates.
  • Centralized error-handling and sensor availability probing for graceful degradation on unsupported hardware.

Implementation Suggestions

  • Structure telemetry providers around an Objective-C base protocol or class returning structured metrics snapshots to Swift ObservableObject / @Observable view models.
  • Utilize low-overhead Grand Central Dispatch (dispatch_source_create timer) running on dedicated quality-of-service queues (QOS_CLASS_UTILITY) to prevent UI hitching.
  • Implement strict memory safety and buffer management when bridging C Mach structs into Objective-C/Swift objects.
### Purpose Establish the core macOS application architecture combining a SwiftUI presentation layer with an Objective-C low-level telemetry subsystem. This foundation serves as the backbone for all hardware, kernel, and process monitoring features on Intel Mac platforms running macOS 14 Sonoma or higher. ### Priority **Critical** (Foundation for all telemetry modules and UI) ### Dependencies - None (Root architecture) ### Scope - macOS app bundle targeting `x86_64` architecture with a minimum deployment target of macOS 14.0 (Sonoma). - Objective-C bridging layer (`MacMonitor-Bridging-Header.h`) to encapsulate direct interactions with Mach kernel, IOKit, BSD sysctl, and CoreFoundation C APIs. - Background telemetry dispatch coordinator managing recurring sampling cycles with configurable polling frequencies (e.g. 1s, 2s, 5s) and minimal CPU footprint. - Thread-safe data repositories exposing published observable models for SwiftUI reactive updates. - Centralized error-handling and sensor availability probing for graceful degradation on unsupported hardware. ### Implementation Suggestions - Structure telemetry providers around an Objective-C base protocol or class returning structured metrics snapshots to Swift `ObservableObject` / `@Observable` view models. - Utilize low-overhead Grand Central Dispatch (`dispatch_source_create` timer) running on dedicated quality-of-service queues (`QOS_CLASS_UTILITY`) to prevent UI hitching. - Implement strict memory safety and buffer management when bridging C Mach structs into Objective-C/Swift objects.
gronod added the Kind/Feature
Priority
Critical
1
labels 2026-09-08 10:18:10 +01:00
gronod added the Feature/ArchitectureProject/AntigravityFeature/Backend labels 2026-09-08 10:28:16 +01:00
Author
Owner

Technical Implementation Plan & Code Solution

1. Architecture Overview

The application follows a decoupled Unidirectional Data Flow (UDF) pattern:

  1. Low-Level Telemetry Layer (Objective-C/C): Implements providers adhering to MMTelemetryProvider protocol. Each provider interacts with Mach, IOKit, or BSD APIs, returning thread-safe immutable snapshot dictionaries or structs.
  2. Dispatch & Polling Coordinator (MMTelemetryCoordinator): A central engine running a dispatch_source_t timer on QOS_CLASS_UTILITY. Gathers snapshots asynchronously and broadcasts to Swift.
  3. Reactive Presentation Layer (Swift/SwiftUI): A Swift @Observable / @MainActor state store (SystemTelemetryStore) receiving snapshots, triggering 60 FPS SwiftUI updates without blocking the main thread.
flowchart TD
    HW["Hardware / Mach Kernel / IOKit"]
    PROV["Objective-C Providers<br/>(MMAppleSMC, MMMachHost, MMProcessCollector, etc.)"]
    COORD["MMTelemetryCoordinator<br/>(GCD Serial Queue · QOS_CLASS_UTILITY)"]
    STORE["SystemTelemetryStore<br/>(@Observable · @MainActor)"]
    VIEWS["SwiftUI Presentation Layer<br/>(Dashboard, MenuBarExtra, Popover, Charts)"]

    HW <-->|"C / Objective-C Low-Level APIs"| PROV
    PROV -->|"Immutable Snapshot DTOs / Structs"| COORD
    COORD -->|"Async @MainActor Dispatch"| STORE
    STORE -->|"Declarative State Binding (60 FPS)"| VIEWS

2. Objective-C / Swift Bridging Contracts

MacMonitor-Bridging-Header.h

#import <Foundation/Foundation.h>
#import <mach/mach.h>
#import <mach/mach_host.h>
#import <mach/processor_info.h>
#import <IOKit/IOKitLib.h>
#import <IOKit/ps/IOPowerSources.h>
#import <IOKit/ps/IOPSKeys.h>
#import <sys/sysctl.h>
#import <sys/mount.h>
#import <libproc.h>

#import "MMTelemetryProvider.h"
#import "MMTelemetryCoordinator.h"

MMTelemetryProvider.h

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

typedef NS_ENUM(NSInteger, MMTelemetryDomain) {
    MMTelemetryDomainCPU,
    MMTelemetryDomainMemory,
    MMTelemetryDomainThermals,
    MMTelemetryDomainFans,
    MMTelemetryDomainDisks,
    MMTelemetryDomainNetwork,
    MMTelemetryDomainGPU,
    MMTelemetryDomainBattery,
    MMTelemetryDomainDisplay
};

@protocol MMTelemetryProvider <NSObject>
@property (nonatomic, readonly) MMTelemetryDomain domain;
@property (nonatomic, readonly, copy) NSString *providerIdentifier;
@property (nonatomic, readonly, getter=isAvailable) BOOL available;

- (nullable NSDictionary<NSString *, id> *)sampleTelemetryWithError:(NSError * _Nullable * _Nullable)error;
@optional
- (void)startMonitoring;
- (void)stopMonitoring;
@end

NS_ASSUME_NONNULL_END

3. Dispatch Coordinator (MMTelemetryCoordinator.m)

#import "MMTelemetryCoordinator.h"

@interface MMTelemetryCoordinator ()
@property (nonatomic, strong) dispatch_queue_t telemetryQueue;
@property (nonatomic, strong) dispatch_source_t timerSource;
@property (nonatomic, strong) NSMutableArray<id<MMTelemetryProvider>> *providers;
@property (nonatomic, assign) NSTimeInterval sampleInterval;
@end

@implementation MMTelemetryCoordinator

- (instancetype)initWithSampleInterval:(NSTimeInterval)interval {
    self = [super init];
    if (self) {
        _sampleInterval = interval > 0.2 ? interval : 1.0;
        _providers = [NSMutableArray array];
        _telemetryQueue = dispatch_queue_create("com.i3omb.macmonitor.telemetry", DISPATCH_QUEUE_SERIAL);
    }
    return self;
}

- (void)registerProvider:(id<MMTelemetryProvider>)provider {
    dispatch_sync(self.telemetryQueue, ^{
        [self.providers addObject:provider];
        if ([provider respondsToSelector:@selector(startMonitoring)]) {
            [provider startMonitoring];
        }
    });
}

- (void)startSamplingWithHandler:(void (^)(NSDictionary<NSString *, id> *snapshot))handler {
    self.timerSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, self.telemetryQueue);
    uint64_t intervalNs = (uint64_t)(self.sampleInterval * NSEC_PER_SEC);
    dispatch_source_set_timer(self.timerSource, dispatch_time(DISPATCH_TIME_NOW, 0), intervalNs, intervalNs / 10);

    __weak typeof(self) weakSelf = self;
    dispatch_source_set_event_handler(self.timerSource, ^{
        __strong typeof(weakSelf) strongSelf = weakSelf;
        if (!strongSelf) return;

        NSMutableDictionary *batch = [NSMutableDictionary dictionaryWithCapacity:strongSelf.providers.count];
        for (id<MMTelemetryProvider> provider in strongSelf.providers) {
            if (!provider.isAvailable) continue;
            NSError *err = nil;
            NSDictionary *data = [provider sampleTelemetryWithError:&err];
            if (data) {
                batch[provider.providerIdentifier] = data;
            }
        }
        if (handler) {
            handler([batch copy]);
        }
    });

    dispatch_resume(self.timerSource);
}

- (void)stopSampling {
    if (self.timerSource) {
        dispatch_source_cancel(self.timerSource);
        self.timerSource = nil;
    }
}
@end

4. Swift State Store (SystemTelemetryStore.swift)

import SwiftUI
import Observation

@Observable
@MainActor
public final class SystemTelemetryStore {
    public static let shared = SystemTelemetryStore()

    public var cpu = CPUSnapshot()
    public var memory = MemorySnapshot()
    public var thermals = ThermalSnapshot()
    public var fans = FanSnapshot()
    public var disks: [DiskSnapshot] = []
    public var network = NetworkSnapshot()
    public var battery: BatterySnapshot? = nil

    private var coordinator: MMTelemetryCoordinator?

    public init(interval: TimeInterval = 1.0) {
        let coord = MMTelemetryCoordinator(sampleInterval: interval)
        self.coordinator = coord
    }

    public func start() {
        coordinator?.startSampling { [weak self] rawBatch in
            Task { @MainActor in
                self?.digest(batch: rawBatch)
            }
        }
    }

    private func digest(batch: [String: Any]) {
        if let cpuData = batch["cpu"] as? [String: Any] {
            self.cpu.update(from: cpuData)
        }
        // Additional provider unmarshaling...
    }
}

5. Verification & Edge Cases

  • Leak Prevention: Ensure autorelease pools inside dispatch_source_set_event_handler block to release Mach port references and CoreFoundation allocations on each tick.
  • Sleep/Wake Resilience: Listen to NSWorkspace.willSleepNotification and NSWorkspace.didWakeNotification to suspend the timer and reconnect IOKit services cleanly.
## Technical Implementation Plan & Code Solution ### 1. Architecture Overview The application follows a decoupled Unidirectional Data Flow (UDF) pattern: 1. **Low-Level Telemetry Layer (Objective-C/C)**: Implements providers adhering to `MMTelemetryProvider` protocol. Each provider interacts with Mach, IOKit, or BSD APIs, returning thread-safe immutable snapshot dictionaries or structs. 2. **Dispatch & Polling Coordinator (`MMTelemetryCoordinator`)**: A central engine running a `dispatch_source_t` timer on `QOS_CLASS_UTILITY`. Gathers snapshots asynchronously and broadcasts to Swift. 3. **Reactive Presentation Layer (Swift/SwiftUI)**: A Swift `@Observable` / `@MainActor` state store (`SystemTelemetryStore`) receiving snapshots, triggering 60 FPS SwiftUI updates without blocking the main thread. ```mermaid flowchart TD HW["Hardware / Mach Kernel / IOKit"] PROV["Objective-C Providers<br/>(MMAppleSMC, MMMachHost, MMProcessCollector, etc.)"] COORD["MMTelemetryCoordinator<br/>(GCD Serial Queue · QOS_CLASS_UTILITY)"] STORE["SystemTelemetryStore<br/>(@Observable · @MainActor)"] VIEWS["SwiftUI Presentation Layer<br/>(Dashboard, MenuBarExtra, Popover, Charts)"] HW <-->|"C / Objective-C Low-Level APIs"| PROV PROV -->|"Immutable Snapshot DTOs / Structs"| COORD COORD -->|"Async @MainActor Dispatch"| STORE STORE -->|"Declarative State Binding (60 FPS)"| VIEWS ``` --- ### 2. Objective-C / Swift Bridging Contracts #### `MacMonitor-Bridging-Header.h` ```objc #import <Foundation/Foundation.h> #import <mach/mach.h> #import <mach/mach_host.h> #import <mach/processor_info.h> #import <IOKit/IOKitLib.h> #import <IOKit/ps/IOPowerSources.h> #import <IOKit/ps/IOPSKeys.h> #import <sys/sysctl.h> #import <sys/mount.h> #import <libproc.h> #import "MMTelemetryProvider.h" #import "MMTelemetryCoordinator.h" ``` #### `MMTelemetryProvider.h` ```objc #import <Foundation/Foundation.h> NS_ASSUME_NONNULL_BEGIN typedef NS_ENUM(NSInteger, MMTelemetryDomain) { MMTelemetryDomainCPU, MMTelemetryDomainMemory, MMTelemetryDomainThermals, MMTelemetryDomainFans, MMTelemetryDomainDisks, MMTelemetryDomainNetwork, MMTelemetryDomainGPU, MMTelemetryDomainBattery, MMTelemetryDomainDisplay }; @protocol MMTelemetryProvider <NSObject> @property (nonatomic, readonly) MMTelemetryDomain domain; @property (nonatomic, readonly, copy) NSString *providerIdentifier; @property (nonatomic, readonly, getter=isAvailable) BOOL available; - (nullable NSDictionary<NSString *, id> *)sampleTelemetryWithError:(NSError * _Nullable * _Nullable)error; @optional - (void)startMonitoring; - (void)stopMonitoring; @end NS_ASSUME_NONNULL_END ``` --- ### 3. Dispatch Coordinator (`MMTelemetryCoordinator.m`) ```objc #import "MMTelemetryCoordinator.h" @interface MMTelemetryCoordinator () @property (nonatomic, strong) dispatch_queue_t telemetryQueue; @property (nonatomic, strong) dispatch_source_t timerSource; @property (nonatomic, strong) NSMutableArray<id<MMTelemetryProvider>> *providers; @property (nonatomic, assign) NSTimeInterval sampleInterval; @end @implementation MMTelemetryCoordinator - (instancetype)initWithSampleInterval:(NSTimeInterval)interval { self = [super init]; if (self) { _sampleInterval = interval > 0.2 ? interval : 1.0; _providers = [NSMutableArray array]; _telemetryQueue = dispatch_queue_create("com.i3omb.macmonitor.telemetry", DISPATCH_QUEUE_SERIAL); } return self; } - (void)registerProvider:(id<MMTelemetryProvider>)provider { dispatch_sync(self.telemetryQueue, ^{ [self.providers addObject:provider]; if ([provider respondsToSelector:@selector(startMonitoring)]) { [provider startMonitoring]; } }); } - (void)startSamplingWithHandler:(void (^)(NSDictionary<NSString *, id> *snapshot))handler { self.timerSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, self.telemetryQueue); uint64_t intervalNs = (uint64_t)(self.sampleInterval * NSEC_PER_SEC); dispatch_source_set_timer(self.timerSource, dispatch_time(DISPATCH_TIME_NOW, 0), intervalNs, intervalNs / 10); __weak typeof(self) weakSelf = self; dispatch_source_set_event_handler(self.timerSource, ^{ __strong typeof(weakSelf) strongSelf = weakSelf; if (!strongSelf) return; NSMutableDictionary *batch = [NSMutableDictionary dictionaryWithCapacity:strongSelf.providers.count]; for (id<MMTelemetryProvider> provider in strongSelf.providers) { if (!provider.isAvailable) continue; NSError *err = nil; NSDictionary *data = [provider sampleTelemetryWithError:&err]; if (data) { batch[provider.providerIdentifier] = data; } } if (handler) { handler([batch copy]); } }); dispatch_resume(self.timerSource); } - (void)stopSampling { if (self.timerSource) { dispatch_source_cancel(self.timerSource); self.timerSource = nil; } } @end ``` --- ### 4. Swift State Store (`SystemTelemetryStore.swift`) ```swift import SwiftUI import Observation @Observable @MainActor public final class SystemTelemetryStore { public static let shared = SystemTelemetryStore() public var cpu = CPUSnapshot() public var memory = MemorySnapshot() public var thermals = ThermalSnapshot() public var fans = FanSnapshot() public var disks: [DiskSnapshot] = [] public var network = NetworkSnapshot() public var battery: BatterySnapshot? = nil private var coordinator: MMTelemetryCoordinator? public init(interval: TimeInterval = 1.0) { let coord = MMTelemetryCoordinator(sampleInterval: interval) self.coordinator = coord } public func start() { coordinator?.startSampling { [weak self] rawBatch in Task { @MainActor in self?.digest(batch: rawBatch) } } } private func digest(batch: [String: Any]) { if let cpuData = batch["cpu"] as? [String: Any] { self.cpu.update(from: cpuData) } // Additional provider unmarshaling... } } ``` --- ### 5. Verification & Edge Cases - **Leak Prevention**: Ensure autorelease pools inside `dispatch_source_set_event_handler` block to release Mach port references and CoreFoundation allocations on each tick. - **Sleep/Wake Resilience**: Listen to `NSWorkspace.willSleepNotification` and `NSWorkspace.didWakeNotification` to suspend the timer and reconnect IOKit services cleanly.
gronod added this to the M1: Architecture Foundation & Hardware Abstraction milestone 2026-09-08 10:41:50 +01:00
gronod added a new dependency 2026-09-08 11:36:51 +01:00
gronod added a new dependency 2026-09-08 11:37:03 +01:00
gronod added a new dependency 2026-09-08 11:37:04 +01:00
gronod added a new dependency 2026-09-08 11:37:04 +01:00
gronod added a new dependency 2026-09-08 11:37:04 +01:00
gronod added a new dependency 2026-09-08 11:37:05 +01:00
gronod added a new dependency 2026-09-08 11:37:06 +01:00
gronod added a new dependency 2026-09-08 11:37:06 +01:00
gronod added a new dependency 2026-09-08 11:37:07 +01:00
gronod added a new dependency 2026-09-08 11:37:07 +01:00
gronod added a new dependency 2026-09-08 11:37:08 +01:00
gronod added a new dependency 2026-09-08 11:37:09 +01:00
gronod added a new dependency 2026-09-08 11:37:10 +01:00
gronod added a new dependency 2026-09-08 11:37:10 +01:00
gronod added a new dependency 2026-09-08 11:37:10 +01:00
gronod added a new dependency 2026-09-08 11:37:12 +01:00
Author
Owner

Implementation Completed (Milestone 1)

The Core Application Architecture & Objective-C/SwiftUI Bridging Foundation has been implemented in commit 4dedf17 on branch feat/1-core-architecture and merged into milestone/m1-foundation (commit 558a19f).

Delivered Components:

  • Deterministic Xcode Project (project.yml): Declarative XcodeGen configuration for Intel x86_64 macOS 14+ targets.
  • Entitlements (MacMonitor.entitlements): Configured hardened runtime and disabled App Sandbox for low-level IOKit and Mach kernel access.
  • Objective-C Bridging Header (MacMonitor-Bridging-Header.h): Exposing core contracts and domain models to Swift.
  • Telemetry Protocols & Coordinator (MMTelemetryDomain.h, MMTelemetryProvider.h, MMTelemetryCoordinator.m): Central Grand Central Dispatch timer source executing on serial com.i3omb.macmonitor.telemetry (QOS_CLASS_UTILITY) with scoped @autoreleasepool.
  • MainActor Telemetry Store (SystemTelemetryStore.swift): Modern Swift @Observable state repository ingesting background snapshots and publishing to SwiftUI.
  • Dashboard UI (ContentView.swift, MacMonitorApp.swift): Real-time system identity card, coordinator engine controls, and provider health monitors.
  • Test Suite (MacMonitorTests.swift): Verified coordinator timer lifecycle and domain conversions.
### Implementation Completed (Milestone 1) The Core Application Architecture & Objective-C/SwiftUI Bridging Foundation has been implemented in commit `4dedf17` on branch `feat/1-core-architecture` and merged into `milestone/m1-foundation` (commit `558a19f`). **Delivered Components:** - **Deterministic Xcode Project (`project.yml`)**: Declarative XcodeGen configuration for Intel `x86_64` macOS 14+ targets. - **Entitlements (`MacMonitor.entitlements`)**: Configured hardened runtime and disabled App Sandbox for low-level IOKit and Mach kernel access. - **Objective-C Bridging Header (`MacMonitor-Bridging-Header.h`)**: Exposing core contracts and domain models to Swift. - **Telemetry Protocols & Coordinator (`MMTelemetryDomain.h`, `MMTelemetryProvider.h`, `MMTelemetryCoordinator.m`)**: Central Grand Central Dispatch timer source executing on serial `com.i3omb.macmonitor.telemetry` (`QOS_CLASS_UTILITY`) with scoped `@autoreleasepool`. - **MainActor Telemetry Store (`SystemTelemetryStore.swift`)**: Modern Swift `@Observable` state repository ingesting background snapshots and publishing to SwiftUI. - **Dashboard UI (`ContentView.swift`, `MacMonitorApp.swift`)**: Real-time system identity card, coordinator engine controls, and provider health monitors. - **Test Suite (`MacMonitorTests.swift`)**: Verified coordinator timer lifecycle and domain conversions.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Reference: gronod/MacMonitor#1