My project like following:
ExampleCam is the main app, which install CMIO extension and USB driver extension.
The ExampleCam.entitlements:
<?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>com.apple.developer.system-extension.install</key>
<true/>
<key>com.apple.developer.driver-extension.install</key>
<true/>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.application-groups</key>
<array>
<string>$(TeamIdentifierPrefix)com.lqs.example.ExampleCam</string>
</array>
<key>com.apple.security.files.user-selected.read-only</key>
<true/>
</dict>
</plist>
If I use the line:
com.apple.developer.driver-extension.install
, I can't run the app as the picture 2.
But If I delete it, I got the error picture 1:
picture 1:

picture 2:

ContentView.swift:
//
// ContentView.swift
// ExampleCam
//
//
import SwiftUI
import SystemExtensions
import Logging
struct ContentView: View {
@State private var logs: [String] = []
@State private var extensionDelegate: ExtensionDelegate?
var body: some View {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundStyle(.tint)
Text("Hello, world!")
// 日志显示区域
ScrollView {
Text(logs.joined(separator: "\n"))
.frame(maxWidth: .infinity, alignment: .leading)
.padding()
}
// 按钮区域
HStack {
Button("Start USB Driver Extension") {
startCameraExtension()
}
Button("Stop USB Driver Extension") {
stopCameraExtension()
}
}
.padding()
}
.padding()
}
// MARK: - Private Methods
private func startCameraExtension() {
guard let identifier = Self.extensionBundle().bundleIdentifier else {
return
}
let logString = "identifier \(identifier)"
logger.info("\(logString)")
logs.append(logString)
let activationRequest = OSSystemExtensionRequest.activationRequest(
forExtensionWithIdentifier: identifier,
queue: .main
)
extensionDelegate = ExtensionDelegate(logs: $logs)
activationRequest.delegate = extensionDelegate
OSSystemExtensionManager.shared.submitRequest(activationRequest)
}
private func stopCameraExtension() {
guard let identifier = Self.extensionBundle().bundleIdentifier else {
return
}
let logString = "identifier \(identifier)"
logger.info("\(logString)")
logs.append(logString)
let deactivationRequest = OSSystemExtensionRequest.deactivationRequest(
forExtensionWithIdentifier: identifier,
queue: .main
)
extensionDelegate = ExtensionDelegate(logs: $logs)
deactivationRequest.delegate = extensionDelegate
OSSystemExtensionManager.shared.submitRequest(deactivationRequest)
}
private static func extensionBundle() -> Bundle {
let extensionsDirectoryURL = URL(
fileURLWithPath: "Contents/Library/SystemExtensions",
relativeTo: Bundle.main.bundleURL
)
let extensionURLs: [URL]
do {
extensionURLs = try FileManager.default.contentsOfDirectory(
at: extensionsDirectoryURL,
includingPropertiesForKeys: nil,
options: .skipsHiddenFiles
)
} catch let error {
fatalError("fatal 1 \(error)")
}
// 专门查找 ExampleMyUSB.dext
guard let extensionURL = extensionURLs.first(where: { url in
url.lastPathComponent.contains("ExampleMyUSB.dext")
}) else {
fatalError("fatal 2: ExampleMyUSB.dext not found")
}
guard let extensionBundle = Bundle(url: extensionURL) else {
fatalError("fatal 3 \(extensionURL.absoluteString)")
}
return extensionBundle
}
}
// MARK: - Extension Delegate
class ExtensionDelegate: NSObject, OSSystemExtensionRequestDelegate {
@Binding var logs: [String]
init(logs: Binding<[String]>) {
self._logs = logs
}
func request(
_ request: OSSystemExtensionRequest,
actionForReplacingExtension existing: OSSystemExtensionProperties,
withExtension ext: OSSystemExtensionProperties
) -> OSSystemExtensionRequest.ReplacementAction {
let logString = "\(#function): (request: \(request.identifier))"
logger.trace("\(logString)")
DispatchQueue.main.async {
self.logs.append(logString)
}
return .replace
}
func requestNeedsUserApproval(_ request: OSSystemExtensionRequest) {
let logString = "\(#function): (request: \(request.identifier))"
logger.trace("\(logString)")
DispatchQueue.main.async {
self.logs.append(logString)
}
}
func request(_ request: OSSystemExtensionRequest, didFinishWithResult result: OSSystemExtensionRequest.Result) {
let logString = "\(#function): (request: \(request.identifier), result: \(result.rawValue))"
logger.trace("\(logString)")
DispatchQueue.main.async {
self.logs.append(logString)
}
}
func request(_ request: OSSystemExtensionRequest, didFailWithError error: Error) {
let logString = "\(#function): (request: \(request.identifier), error: \(error))"
logger.trace("\(logString)")
DispatchQueue.main.async {
self.logs.append(logString)
}
}
}
#Preview {
ContentView()
}