Developer Docs

iOS Development Setup

Repository: ngwenya-ios
Submodule: ngwenya-front/mobile/ios
Requirements: Xcode 16+, Swift 6+, Apple Silicon Mac
Tested on: M1 Max, 64 GB RAM, macOS 15, Xcode 26.3


Quick Start

# 1. Clone (or init submodule)
cd /path/to/ngwenya-front
git submodule update --init mobile/ios
cd mobile/ios

# 2. Open Xcode and create project (see detailed steps below)
open -a Xcode

# 3. Build & run on Simulator (โŒ˜R in Xcode)

The repo contains only Swift source files โ€” no .xcodeproj is committed. You create the Xcode project locally, add the existing sources, and you're running in under 10 minutes.


Prerequisites

Tool Minimum Check
Xcode 16.0+ xcodebuild -version
Swift 6.0+ swift --version
macOS 15.0+ sw_vers
# Verify simulator runtimes
xcrun simctl list runtimes | grep iOS
# Should show iOS 17.x or 18.x

# Accept Xcode license (if needed)
sudo xcodebuild -license accept

Project Setup in Xcode

Step 1: Create New Project

  1. File โ†’ New โ†’ Project... (โ‡งโŒ˜N)
  2. Select iOS โ†’ App โ†’ Next
  3. Configure:
Field Value
Product Name Ngwenya
Organization Identifier com.mallnline
Interface SwiftUI
Language Swift
Storage None
  1. Save inside the cloned ngwenya-ios/ directory
  2. Uncheck "Create Git repository"

Step 2: Replace Default Files

Delete Xcode's generated starter files (ContentView.swift, NgwenyaApp.swift, Assets.xcassets), then add the repo's source files:

  1. Right-click Ngwenya group โ†’ Add Files to "Ngwenya"...
  2. Select everything in the Ngwenya/ directory:
    • NgwenyaApp.swift
    • Views/, Bridge/, Services/
    • Assets.xcassets/, Info.plist
  3. Options: Create groups โœ…, Copy items โŒ, Add to target โœ…

Step 3: Set Info.plist Path

  1. Select project โ†’ Build Settings โ†’ search Info.plist
  2. Set INFOPLIST_FILE to Ngwenya/Info.plist

Step 4: Set Deployment Target

General โ†’ Minimum Deployments โ†’ iOS 17.0


Add Push Notification Capability

  1. Select target โ†’ Signing & Capabilities
  2. Click + Capability โ†’ Add Push Notifications
  3. Add Background Modes โ†’ check โœ… Remote notifications

Push tokens are only available on physical devices. The Simulator works for everything else.

APNs Key Setup (for real push testing)

  1. Apple Developer Portal โ†’ Keys โ†’ Create a Key
  2. Name: Ngwenya Push Key, check โœ… APNs
  3. Download the .p8 file (one-time download)
  4. Configure the backend (alerts subgraph):
APNS_KEY_ID=ABC123DEF4
APNS_TEAM_ID=YOURTEAMID
APNS_KEY_CONTENTS="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----"
APNS_BUNDLE_ID=com.mallnline.ngwenya
APNS_PRODUCTION=false

See Mobile Push Infrastructure for the full backend configuration.


Run on Simulator

  1. Select iPhone 16 Pro from the device dropdown
  2. Press โŒ˜R (Build & Run)

You should see:

  • โœ… 6-tab navigation bar at the bottom
  • โœ… Push permission dialog on first launch
  • โœ… Console: [NgwenyaApp] Push auth error: (expected โ€” simulators don't support APNs)
Feature Simulator Physical Device
Tab navigation โœ… โœ…
WebView bridge โœ… โœ…
Push token registration โŒ โœ…
Camera / biometrics โŒ โœ…

Run on Physical Device

  1. Connect iPhone via USB-C / Lightning
  2. Select your iPhone from the device dropdown
  3. โŒ˜R โ€” Xcode will install and launch
  4. Trust the developer certificate: Settings โ†’ General โ†’ VPN & Device Management

After granting notification permission, check Xcode console:

[NgwenyaApp] APNs token: a1b2c3d4e5f6...

Local Backend Development

API Endpoint

Update PushNotificationManager.swift to point to your Mac's backend:

// Your Mac and iPhone must be on the same Wi-Fi
private let graphQLEndpoint = "http://192.168.1.XXX:30000/graphql"
// Find your IP: System Settings โ†’ Network โ†’ Wi-Fi โ†’ Details

WebView URL

Update WebViewBridge.swift:

let baseURL = "http://192.168.1.XXX:5173"  // Vite dev server

The Info.plist already includes an ATS exception for localhost to permit HTTP in development.


WebView Bridge Testing

Enable Safari Web Inspector

  • iPhone: Settings โ†’ Safari โ†’ Advanced โ†’ Web Inspector โœ…
  • Mac: Safari โ†’ Settings โ†’ Advanced โ†’ Show features for web developers โœ…

Inspect the WebView

  1. Navigate to the Malet tab in the app
  2. Open Safari on Mac โ†’ Develop โ†’ select your Simulator/device โ†’ Ngwenya
  3. In the Web Inspector console:
// Verify token injection
window.__NGWENYA_TOKEN__    // โ†’ JWT string
window.__NGWENYA_PLATFORM__ // โ†’ "ios"

// Test bridge messaging
window.webkit.messageHandlers.ngwenyaBridge.postMessage({
  action: "navigate",
  route: "/cart"
});
// Check Xcode console for: [WebViewBridge] Navigate: /cart

The frontend detects this context via mobileUtils.ts โ€” isMobileWebView(), getMobilePlatform(), and getNativeAuthToken().


Project Structure

Ngwenya/
โ”œโ”€โ”€ NgwenyaApp.swift              # @main entry + APNs AppDelegate
โ”œโ”€โ”€ Info.plist                    # Bundle config, URL scheme, ATS
โ”œโ”€โ”€ Assets.xcassets/              # App icon + AccentColor
โ”œโ”€โ”€ Views/
โ”‚   โ”œโ”€โ”€ ContentView.swift         # 6-tab TabView shell
โ”‚   โ”œโ”€โ”€ LobbyView.swift           # Native discovery feed
โ”‚   โ”œโ”€โ”€ MaletView.swift            # WKWebView delegate
โ”‚   โ”œโ”€โ”€ UCartView.swift            # Native cart
โ”‚   โ”œโ”€โ”€ MurchasesView.swift        # Native order history
โ”‚   โ”œโ”€โ”€ NotificationsView.swift   # Push notification inbox
โ”‚   โ””โ”€โ”€ UChatView.swift            # Native messaging
โ”œโ”€โ”€ Bridge/
โ”‚   โ””โ”€โ”€ WebViewBridge.swift        # WKWebView + JS bridge + token injection
โ””โ”€โ”€ Services/
    โ”œโ”€โ”€ AuthManager.swift          # JWT token singleton
    โ””โ”€โ”€ PushNotificationManager.swift  # GraphQL push token registration

Troubleshooting

Problem Solution
"No such module 'SwiftUI'" Set deployment target to iOS 17.0+
"Signing requires a development team" Select team in Signing & Capabilities, or disable for sim-only
Push token not in console Simulators don't support APNs โ€” use physical device
WebView blank white screen Update baseURL in WebViewBridge.swift to your local IP
"Multiple commands produce" Delete DerivedData: rm -rf ~/Library/Developer/Xcode/DerivedData/Ngwenya-*