This cleanup commit resolves the issue where the branch was accidentally based on master instead of v3-alpha. It removes all master-specific files, restores any v3-alpha files to their correct state, and ensures only the 3 intended bugfix changes differ from v3-alpha: - v3/pkg/application/webview_window_windows.go - v3/pkg/w32/constants.go - v3/pkg/w32/user32.go
14 KiB
Wails v3 iOS Architecture
Executive Summary
This document provides a comprehensive technical architecture for iOS support in Wails v3. The implementation enables Go applications to run natively on iOS with a WKWebView frontend, maintaining the Wails philosophy of using web technologies for UI while leveraging Go for business logic.
Table of Contents
- Architecture Overview
- Core Components
- Layer Architecture
- Implementation Details
- Battery Optimization
- Build System
- Security Considerations
- API Reference
Architecture Overview
Design Principles
- Battery Efficiency First: All architectural decisions prioritize battery life
- No Network Ports: Asset serving happens in-process via native APIs
- Minimal WebView Instances: Maximum 2 concurrent WebViews (1 primary, 1 for transitions)
- Native Integration: Deep iOS integration using Objective-C runtime
- Wails v3 Compatibility: Maintain API compatibility with existing Wails v3 applications
High-Level Architecture
┌─────────────────────────────────────────────────────────────┐
│ iOS Application │
├─────────────────────────────────────────────────────────────┤
│ UIKit Framework │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ WailsViewController │ │
│ │ ┌───────────────────────────────────────────────┐ │ │
│ │ │ WKWebView Instance │ │ │
│ │ │ ┌─────────────────────────────────────────┐ │ │ │
│ │ │ │ Web Application (HTML/JS) │ │ │ │
│ │ │ └─────────────────────────────────────────┘ │ │ │
│ │ └───────────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ Bridge Layer (CGO) │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │URL Handler │ │JS Bridge │ │Message Handler│ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ Go Runtime │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Wails Application │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │ │
│ │ │App Logic │ │Services │ │Asset Server │ │ │
│ │ └──────────┘ └──────────┘ └──────────────────┘ │ │
│ └──────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
Core Components
1. Platform Layer (application_ios.go)
Purpose: Go interface for iOS platform operations
Key Functions:
platformRun(): Initialize and run the iOS applicationplatformQuit(): Gracefully shutdown the applicationisDarkMode(): Detect iOS dark mode stateExecuteJavaScript(windowID uint, js string): Execute JS in WebView
Exported Go Functions (Called from Objective-C):
ServeAssetRequest(windowID C.uint, urlStr *C.char, callbackID C.uint)HandleJSMessage(windowID C.uint, message *C.char)
2. Native iOS Layer (application_ios.m)
Components:
WailsSchemeHandler
@interface WailsSchemeHandler : NSObject <WKURLSchemeHandler>
- Implements
WKURLSchemeHandlerprotocol - Intercepts
wails://URL requests - Bridges to Go for asset serving
- Manages pending requests with callback IDs
Methods:
startURLSchemeTask:: Intercept request, call Go handlerstopURLSchemeTask:: Cancel pending requestcompleteRequest:withData:mimeType:: Complete request with data from Go
WailsMessageHandler
@interface WailsMessageHandler : NSObject <WKScriptMessageHandler>
- Implements JavaScript to Go communication
- Handles
window.webkit.messageHandlers.external.postMessage() - Serializes messages to JSON for Go processing
Methods:
userContentController:didReceiveScriptMessage:: Process JS messages
WailsViewController
@interface WailsViewController : UIViewController
- Main view controller containing WKWebView
- Manages WebView lifecycle
- Handles JavaScript execution requests
Properties:
webView: WKWebView instanceschemeHandler: Custom URL scheme handlermessageHandler: JS message handlerwindowID: Unique window identifier
Methods:
viewDidLoad: Initialize WebView with configurationexecuteJavaScript:: Run JS code in WebView
3. Bridge Layer (CGO)
C Interface Functions:
void ios_app_init(void); // Initialize iOS app
void ios_app_run(void); // Run main loop
void ios_app_quit(void); // Quit application
bool ios_is_dark_mode(void); // Check dark mode
unsigned int ios_create_webview(void); // Create WebView
void ios_execute_javascript(unsigned int windowID, const char* js);
void ios_complete_request(unsigned int callbackID, const char* data, const char* mimeType);
Layer Architecture
Layer 1: Presentation Layer (WebView)
Responsibilities:
- Render HTML/CSS/JavaScript UI
- Handle user interactions
- Communicate with native layer
Key Features:
- WKWebView for modern web standards
- Hardware-accelerated rendering
- Efficient memory management
Layer 2: Communication Layer
Request Interception:
WebView Request → WKURLSchemeHandler → Go ServeAssetRequest → AssetServer → Response
JavaScript Bridge:
JS postMessage → WKScriptMessageHandler → Go HandleJSMessage → Process → ExecuteJavaScript
Layer 3: Application Layer (Go)
Components:
- Application lifecycle management
- Service binding and method calls
- Asset serving from embedded fs.FS
- Business logic execution
Layer 4: Platform Integration Layer
iOS-Specific Features:
- Dark mode detection
- System appearance integration
- iOS-specific optimizations
Implementation Details
Request Handling Flow
- WebView makes request to
wails://localhost/path - WKURLSchemeHandler intercepts request
- Creates callback ID and stores
WKURLSchemeTask - Calls Go function
ServeAssetRequestwith URL and callback ID - Go processes request through AssetServer
- Go calls
ios_complete_requestwith response data - Objective-C completes the
WKURLSchemeTaskwith response
JavaScript Execution Flow
- Go calls
ios_execute_javascriptwith JS code - Bridge dispatches to main thread
- WKWebView evaluates JavaScript
- Completion handler logs any errors
Message Passing Flow
- JavaScript calls
window.webkit.messageHandlers.wails.postMessage(data) - WKScriptMessageHandler receives message
- Serializes to JSON and passes to Go
- Go processes message in
HandleJSMessage - Go can respond via
ExecuteJavaScript
Battery Optimization
WebView Configuration
// Disable unnecessary features
config.suppressesIncrementalRendering = NO;
config.allowsInlineMediaPlayback = YES;
config.mediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypeNone;
Memory Management
- Single WebView Instance: Reuse instead of creating new instances
- Automatic Reference Counting: Use ARC for Objective-C objects
- Lazy Loading: Initialize components only when needed
- Resource Cleanup: Properly release resources when done
Request Optimization
- In-Process Serving: No network overhead
- Direct Memory Transfer: Pass data directly without serialization
- Efficient Caching: Leverage WKWebView's built-in cache
- Minimal Wake Locks: No background network activity
Build System
Build Tags
//go:build ios
CGO Configuration
#cgo CFLAGS: -x objective-c -fobjc-arc
#cgo LDFLAGS: -framework Foundation -framework UIKit -framework WebKit
Build Script (build_ios.sh)
Steps:
- Check dependencies (go, xcodebuild, xcrun)
- Set up iOS cross-compilation environment
- Build Go binary with iOS tags
- Create app bundle structure
- Generate Info.plist
- Sign for simulator
- Create launch script
Environment Variables:
export CGO_ENABLED=1
export GOOS=ios
export GOARCH=arm64
export SDK_PATH=$(xcrun --sdk iphonesimulator --show-sdk-path)
Simulator Deployment
xcrun simctl install "$DEVICE_ID" "WailsIOSDemo.app"
xcrun simctl launch "$DEVICE_ID" "com.wails.iosdemo"
Security Considerations
URL Scheme Security
- Custom Scheme: Use
wails://to avoid conflicts - Origin Validation: Only serve to authorized WebViews
- No External Access: Scheme handler only responds to app's WebView
JavaScript Execution
- Input Validation: Sanitize JS code before execution
- Sandboxed Execution: WKWebView provides isolation
- No eval(): Avoid dynamic code evaluation
Data Protection
- In-Memory Only: No temporary files on disk
- ATS Compliance: App Transport Security enabled
- Secure Communication: All data stays within app process
API Reference
Go API
Application Functions
// Create new iOS application
app := application.New(application.Options{
Name: "App Name",
Description: "App Description",
})
// Run the application
app.Run()
// Execute JavaScript
app.ExecuteJavaScript(windowID, "console.log('Hello')")
Service Binding
type MyService struct{}
func (s *MyService) Greet(name string) string {
return fmt.Sprintf("Hello, %s!", name)
}
app := application.New(application.Options{
Services: []application.Service{
application.NewService(&MyService{}),
},
})
JavaScript API
Send Message to Go
window.webkit.messageHandlers.wails.postMessage({
type: 'methodCall',
service: 'MyService',
method: 'Greet',
args: ['World']
});
Receive from Go
window.wailsCallback = function(data) {
console.log('Received:', data);
};
Objective-C Bridge API
From Go to Objective-C
// Execute JavaScript
ios_execute_javascript(windowID, "alert('Hello')");
// Complete asset request
ios_complete_request(callbackID, htmlData, "text/html");
From Objective-C to Go
// Serve asset request
ServeAssetRequest(windowID, urlString, callbackID);
// Handle JavaScript message
HandleJSMessage(windowID, jsonMessage);
Performance Metrics
Target Metrics
- WebView Creation: < 100ms
- Asset Request: < 10ms for cached, < 50ms for first load
- JS Execution: < 5ms for simple scripts
- Message Passing: < 2ms round trip
- Memory Usage: < 50MB baseline
- Battery Impact: < 2% per hour active use
Monitoring
- Xcode Instruments: CPU, Memory, Energy profiling
- WebView Inspector: JavaScript performance
- Go Profiling: pprof for Go code analysis
Future Enhancements
Phase 1: Core Stability
- Production-ready error handling
- Comprehensive test suite
- Performance optimization
Phase 2: Feature Parity
- Multiple window support
- System tray integration
- Native menu implementation
Phase 3: iOS-Specific Features
- Widget extension support
- App Clip support
- ShareSheet integration
- Siri Shortcuts
Phase 4: Advanced Features
- Background task support
- Push notifications
- CloudKit integration
- Apple Watch companion app
Conclusion
This architecture provides a solid foundation for iOS support in Wails v3. The design prioritizes battery efficiency, native performance, and seamless integration with the existing Wails ecosystem. The proof of concept demonstrates all four required capabilities:
- ✅ WebView Creation: Native WKWebView with optimized configuration
- ✅ Request Interception: Custom scheme handler without network ports
- ✅ JavaScript Execution: Bidirectional communication bridge
- ✅ iOS Simulator Support: Complete build and deployment pipeline
The architecture is designed to scale from this proof of concept to a full production implementation while maintaining the simplicity and elegance that Wails developers expect.