فهرست منبع

iOS+macOS: fix new vm config getting reset

We were not following SwiftUI rule for object ownership.
osy 5 سال پیش
والد
کامیت
4b6c057bbe

+ 2 - 2
Configuration/UTMConfiguration.h

@@ -27,11 +27,11 @@ NS_ASSUME_NONNULL_BEGIN
 @property (nonatomic, nullable, copy) NSURL *selectedCustomIconPath;
 
 - (void)migrateConfigurationIfNecessary;
-- (instancetype)init NS_UNAVAILABLE;
-- (instancetype)initDefaults:(NSString *)name NS_DESIGNATED_INITIALIZER NS_SWIFT_NAME(init(name:));
+- (instancetype)init NS_DESIGNATED_INITIALIZER;
 - (instancetype)initWithDictionary:(NSDictionary *)dictionary name:(NSString *)name path:(NSURL *)path NS_DESIGNATED_INITIALIZER;
 
 - (NSURL*)terminalInputOutputURL;
+- (void)resetDefaults;
 - (void)reloadConfigurationWithDictionary:(NSDictionary *)dictionary name:(NSString *)name path:(NSURL *)path;
 
 @end

+ 33 - 28
Configuration/UTMConfiguration.m

@@ -59,36 +59,10 @@ const NSString *const kUTMConfigInfoKey = @"Info";
 
 #pragma mark - Initialization
 
-- (instancetype)initDefaults:(NSString *)name {
+- (instancetype)init {
     self = [super init];
     if (self) {
-        _rootDict = [[NSMutableDictionary alloc] initWithCapacity:8];
-        _rootDict[kUTMConfigSystemKey] = [[NSMutableDictionary alloc] init];
-        _rootDict[kUTMConfigDisplayKey] = [[NSMutableDictionary alloc] init];
-        _rootDict[kUTMConfigInputKey] = [[NSMutableDictionary alloc] init];
-        _rootDict[kUTMConfigNetworkingKey] = [[NSMutableDictionary alloc] init];
-        _rootDict[kUTMConfigPrintingKey] = [[NSMutableDictionary alloc] init];
-        _rootDict[kUTMConfigSoundKey] = [[NSMutableDictionary alloc] init];
-        _rootDict[kUTMConfigSharingKey] = [[NSMutableDictionary alloc] init];
-        _rootDict[kUTMConfigDrivesKey] = [[NSMutableArray alloc] init];
-        _rootDict[kUTMConfigDebugKey] = [[NSMutableDictionary alloc] init];
-        _rootDict[kUTMConfigInfoKey] = [[NSMutableDictionary alloc] init];
-        self.systemArchitecture = @"x86_64";
-        self.systemTarget = @"pc";
-        self.systemMemory = @512;
-        self.systemBootDevice = @"cd";
-        self.systemUUID = [[NSUUID UUID] UUIDString];
-        self.displayUpscaler = @"linear";
-        self.displayDownscaler = @"linear";
-        self.consoleFont = @"Menlo";
-        self.consoleFontSize = @12;
-        self.consoleTheme = @"Default";
-        self.networkEnabled = YES;
-        self.soundEnabled = YES;
-        self.soundCard = @"ac97";
-        self.networkCard = @"rtl8139";
-        self.shareClipboardEnabled = YES;
-        self.name = name;
+        [self resetDefaults];
     }
     return self;
 }
@@ -114,6 +88,37 @@ const NSString *const kUTMConfigInfoKey = @"Info";
     return ioFile;
 }
 
+- (void)resetDefaults {
+    [self propertyWillChange];
+    _rootDict = [[NSMutableDictionary alloc] initWithCapacity:8];
+    _rootDict[kUTMConfigSystemKey] = [[NSMutableDictionary alloc] init];
+    _rootDict[kUTMConfigDisplayKey] = [[NSMutableDictionary alloc] init];
+    _rootDict[kUTMConfigInputKey] = [[NSMutableDictionary alloc] init];
+    _rootDict[kUTMConfigNetworkingKey] = [[NSMutableDictionary alloc] init];
+    _rootDict[kUTMConfigPrintingKey] = [[NSMutableDictionary alloc] init];
+    _rootDict[kUTMConfigSoundKey] = [[NSMutableDictionary alloc] init];
+    _rootDict[kUTMConfigSharingKey] = [[NSMutableDictionary alloc] init];
+    _rootDict[kUTMConfigDrivesKey] = [[NSMutableArray alloc] init];
+    _rootDict[kUTMConfigDebugKey] = [[NSMutableDictionary alloc] init];
+    _rootDict[kUTMConfigInfoKey] = [[NSMutableDictionary alloc] init];
+    self.systemArchitecture = @"x86_64";
+    self.systemTarget = @"pc";
+    self.systemMemory = @512;
+    self.systemBootDevice = @"cd";
+    self.systemUUID = [[NSUUID UUID] UUIDString];
+    self.displayUpscaler = @"linear";
+    self.displayDownscaler = @"linear";
+    self.consoleFont = @"Menlo";
+    self.consoleFontSize = @12;
+    self.consoleTheme = @"Default";
+    self.networkEnabled = YES;
+    self.soundEnabled = YES;
+    self.soundCard = @"ac97";
+    self.networkCard = @"rtl8139";
+    self.shareClipboardEnabled = YES;
+    self.name = [NSUUID UUID].UUIDString;
+}
+
 - (void)reloadConfigurationWithDictionary:(NSDictionary *)dictionary name:(NSString *)name path:(NSURL *)path {
     [self propertyWillChange];
     _rootDict = CFBridgingRelease(CFPropertyListCreateDeepCopy(kCFAllocatorDefault, (__bridge CFDictionaryRef)dictionary, kCFPropertyListMutableContainers));

+ 1 - 2
Configuration/UTMViewState.h

@@ -33,8 +33,7 @@ NS_ASSUME_NONNULL_BEGIN
 @property (nonatomic, copy, nullable) NSData *sharedDirectory;
 @property (nonatomic, copy, nullable) NSString *sharedDirectoryPath;
 
-- (instancetype)init NS_UNAVAILABLE;
-- (instancetype)initDefaults NS_DESIGNATED_INITIALIZER;
+- (instancetype)init NS_DESIGNATED_INITIALIZER;
 - (instancetype)initWithDictionary:(NSDictionary *)dictionary NS_DESIGNATED_INITIALIZER;
 
 - (void)setBookmark:(NSData *)bookmark path:(NSString *)path forRemovableDrive:(NSString *)drive persistent:(BOOL)persistent;

+ 1 - 1
Configuration/UTMViewState.m

@@ -193,7 +193,7 @@ const NSString *const kUTMViewStateRemovableDrivesPathKey = @"RemovableDrivesPat
 
 #pragma mark - Init
 
-- (instancetype)initDefaults {
+- (instancetype)init {
     self = [super init];
     if (self) {
         _rootDict = [NSMutableDictionary dictionary];

+ 1 - 1
Managers/UTMVirtualMachine.h

@@ -38,7 +38,7 @@ NS_ASSUME_NONNULL_BEGIN
 @property (nonatomic, weak, nullable) id<UTMVirtualMachineDelegate> delegate;
 @property (nonatomic, weak, nullable) id ioDelegate;
 @property (nonatomic, strong) NSURL *parentPath;
-@property (nonatomic, strong, readonly) UTMConfiguration *configuration;
+@property (nonatomic, readonly, copy) UTMConfiguration *configuration;
 @property (nonatomic, readonly) UTMViewState *viewState;
 @property (nonatomic, assign, readonly) UTMVMState state;
 @property (nonatomic, readonly) BOOL busy;

+ 3 - 3
Managers/UTMVirtualMachine.m

@@ -47,7 +47,7 @@ NSString *const kSuspendSnapshotName = @"suspend";
 @interface UTMVirtualMachine ()
 
 @property (nonatomic, readwrite, nullable) NSURL *path;
-@property (nonatomic, readwrite) UTMConfiguration *configuration;
+@property (nonatomic, readwrite, copy) UTMConfiguration *configuration;
 @property (nonatomic, readonly) UTMQemuManager *qemu;
 @property (nonatomic, readonly) UTMQemu *system;
 @property (nonatomic, readwrite) UTMViewState *viewState;
@@ -144,7 +144,7 @@ NSString *const kSuspendSnapshotName = @"suspend";
     if (self) {
         self.parentPath = dstUrl;
         self.configuration = configuration;
-        self.viewState = [[UTMViewState alloc] initDefaults];
+        self.viewState = [[UTMViewState alloc] init];
     }
     return self;
 }
@@ -658,7 +658,7 @@ error:
     if (plist) {
         self.viewState = [[UTMViewState alloc] initWithDictionary:plist];
     } else {
-        self.viewState = [[UTMViewState alloc] initDefaults];
+        self.viewState = [[UTMViewState alloc] init];
     }
 }
 

+ 1 - 1
Platform/Shared/VMCardView.swift

@@ -140,6 +140,6 @@ struct Logo: View {
 @available(iOS 14, macOS 11, *)
 struct VMCardView_Previews: PreviewProvider {
     static var previews: some View {
-        VMCardView(vm: UTMVirtualMachine(configuration: UTMConfiguration(name: "Test"), withDestinationURL: URL(fileURLWithPath: "/")))
+        VMCardView(vm: UTMVirtualMachine(configuration: UTMConfiguration(), withDestinationURL: URL(fileURLWithPath: "/")))
     }
 }

+ 1 - 1
Platform/Shared/VMConfigDisplayView.swift

@@ -82,7 +82,7 @@ struct VMConfigDisplayView: View {
 
 @available(iOS 14, macOS 11, *)
 struct VMConfigDisplayView_Previews: PreviewProvider {
-    @ObservedObject static private var config = UTMConfiguration(name: "Test")
+    @ObservedObject static private var config = UTMConfiguration()
     
     static var previews: some View {
         VMConfigDisplayView(config: config)

+ 1 - 1
Platform/Shared/VMConfigInfoView.swift

@@ -195,7 +195,7 @@ private struct IconSelect: View {
 
 @available(iOS 14, macOS 11, *)
 struct VMConfigInfoView_Previews: PreviewProvider {
-    @ObservedObject static private var config = UTMConfiguration(name: "Test")
+    @ObservedObject static private var config = UTMConfiguration()
     
     static var previews: some View {
         Group {

+ 1 - 1
Platform/Shared/VMConfigInputView.swift

@@ -65,7 +65,7 @@ struct GestureSettingsSection: View {
 
 @available(iOS 14, macOS 11, *)
 struct VMConfigInputView_Previews: PreviewProvider {
-    @ObservedObject static private var config = UTMConfiguration(name: "Test")
+    @ObservedObject static private var config = UTMConfiguration()
     
     static var previews: some View {
         VMConfigInputView(config: config)

+ 1 - 1
Platform/Shared/VMConfigNetworkView.swift

@@ -130,7 +130,7 @@ struct IPConfigurationSection: View {
 
 @available(iOS 14, macOS 11, *)
 struct VMConfigNetworkingView_Previews: PreviewProvider {
-    @State static private var config = UTMConfiguration(name: "Test")
+    @State static private var config = UTMConfiguration()
     
     static var previews: some View {
         VMConfigNetworkView(config: config)

+ 1 - 1
Platform/Shared/VMConfigPortForwardForm.swift

@@ -55,7 +55,7 @@ struct VMConfigPortForwardForm: View {
 
 @available(iOS 14, macOS 11, *)
 struct VMConfigPortForwardForm_Previews: PreviewProvider {
-    @State static private var config = UTMConfiguration(name: "Test")
+    @State static private var config = UTMConfiguration()
     @State static private var configPort = UTMConfigurationPortForward()
     
     static var previews: some View {

+ 1 - 1
Platform/Shared/VMConfigQEMUView.swift

@@ -150,7 +150,7 @@ struct CustomArguments: View {
 
 @available(iOS 14, macOS 11, *)
 struct VMConfigQEMUView_Previews: PreviewProvider {
-    @ObservedObject static private var config = UTMConfiguration(name: "Test")
+    @ObservedObject static private var config = UTMConfiguration()
     
     static var previews: some View {
         VMConfigQEMUView(config: config)

+ 1 - 1
Platform/Shared/VMConfigSharingView.swift

@@ -45,7 +45,7 @@ struct VMConfigSharingView: View {
 
 @available(iOS 14, macOS 11, *)
 struct VMConfigSharingView_Previews: PreviewProvider {
-    @State static private var config = UTMConfiguration(name: "Test")
+    @State static private var config = UTMConfiguration()
     
     static var previews: some View {
         VMConfigSharingView(config: config)

+ 1 - 1
Platform/Shared/VMConfigSoundView.swift

@@ -38,7 +38,7 @@ struct VMConfigSoundView: View {
 
 @available(iOS 14, macOS 11, *)
 struct VMConfigSoundView_Previews: PreviewProvider {
-    @State static private var config = UTMConfiguration(name: "Test")
+    @State static private var config = UTMConfiguration()
     
     static var previews: some View {
         VMConfigSoundView(config: config)

+ 1 - 1
Platform/Shared/VMConfigSystemView.swift

@@ -156,7 +156,7 @@ struct VMConfigSystemView: View {
 
 @available(iOS 14, macOS 11, *)
 struct VMConfigSystemView_Previews: PreviewProvider {
-    @ObservedObject static private var config = UTMConfiguration(name: "Test")
+    @ObservedObject static private var config = UTMConfiguration()
     
     static var previews: some View {
         VMConfigSystemView(config: config)

+ 1 - 1
Platform/Shared/VMDetailsView.swift

@@ -156,7 +156,7 @@ struct DetailsLabelStyle: LabelStyle {
 
 @available(iOS 14, macOS 11, *)
 struct VMDetailsView_Previews: PreviewProvider {
-    @State static private var config = UTMConfiguration(name: "Test")
+    @State static private var config = UTMConfiguration()
     
     static var previews: some View {
         VMDetailsView(vm: UTMVirtualMachine(configuration: config, withDestinationURL: URL(fileURLWithPath: "")))

+ 1 - 1
Platform/Shared/VMRemovableDrivesView.swift

@@ -111,7 +111,7 @@ struct VMRemovableDrivesView: View {
 
 @available(iOS 14, macOS 11, *)
 struct VMRemovableDrivesView_Previews: PreviewProvider {
-    @State static private var config = UTMConfiguration(name: "Test")
+    @State static private var config = UTMConfiguration()
     
     static var previews: some View {
         VMRemovableDrivesView(vm: UTMVirtualMachine(configuration: config, withDestinationURL: URL(fileURLWithPath: "")))

+ 9 - 3
Platform/iOS/ContentView.swift

@@ -19,6 +19,7 @@ import IQKeyboardManagerSwift
 
 @available(iOS 14, *)
 struct ContentView: View {
+    @StateObject private var newConfiguration = UTMConfiguration()
     @State private var editMode = false
     @EnvironmentObject private var data: UTMData
     @State private var newPopupPresented = false
@@ -48,10 +49,15 @@ struct ContentView: View {
                     EditButton()
                 }
             }
-            .sheet(isPresented: $newVMScratchPresented) {
-                VMSettingsView(vm: nil, config: UTMConfiguration(name: data.newDefaultVMName()))
+            .sheet(isPresented: $newVMScratchPresented, onDismiss: {
+                newConfiguration.resetDefaults()
+            }, content: {
+                VMSettingsView(vm: nil, config: newConfiguration)
                     .environmentObject(data)
-            }
+                    .onAppear {
+                        newConfiguration.name = data.newDefaultVMName()
+                    }
+            })
             VMPlaceholderView(createNewVMPresented: $newVMScratchPresented)
                 .overlay(BusyOverlay())
         }.disabled(data.busy)

+ 2 - 1
Platform/iOS/Legacy/VMListViewController.m

@@ -236,7 +236,8 @@
         UINavigationController *navController = (UINavigationController *)segue.destinationViewController;
         NSAssert([navController.topViewController conformsToProtocol:@protocol(UTMConfigurationDelegate)], @"Invalid segue destination");
         id<UTMConfigurationDelegate> controller = (id<UTMConfigurationDelegate>)navController.topViewController;
-        controller.configuration = [[UTMConfiguration alloc] initDefaults:[self createNewDefaultName]];
+        controller.configuration = [[UTMConfiguration alloc] init];
+        controller.configuration.name = [self createNewDefaultName];
     } else if ([segue.identifier isEqualToString:@"startVM"]) {
         NSAssert([segue.destinationViewController isKindOfClass:[VMDisplayMetalViewController class]], @"Destination not a metal view");
         VMDisplayMetalViewController *metalView = (VMDisplayMetalViewController *)segue.destinationViewController;

+ 1 - 1
Platform/iOS/VMConfigDrivesView.swift

@@ -151,7 +151,7 @@ private struct CreateDrive: View {
 
 @available(iOS 14, *)
 struct VMConfigDrivesView_Previews: PreviewProvider {
-    @ObservedObject static private var config = UTMConfiguration(name: "Test")
+    @ObservedObject static private var config = UTMConfiguration()
     
     static var previews: some View {
         Group {

+ 1 - 1
Platform/iOS/VMConfigNetworkPortForwardView.swift

@@ -89,7 +89,7 @@ struct PortForwardEdit: View {
 
 @available(iOS 14, *)
 struct VMConfigNetworkPortForwardView_Previews: PreviewProvider {
-    @State static private var config = UTMConfiguration(name: "Test")
+    @State static private var config = UTMConfiguration()
     static var previews: some View {
         Group {
             Form {

+ 1 - 1
Platform/iOS/VMSettingsView.swift

@@ -138,7 +138,7 @@ struct RoundRectIconLabelStyle: LabelStyle {
 
 @available(iOS 14, *)
 struct VMSettingsView_Previews: PreviewProvider {
-    @State static private var config = UTMConfiguration(name: "Test")
+    @State static private var config = UTMConfiguration()
     
     static var previews: some View {
         VMSettingsView(vm: nil, config: config)

+ 9 - 3
Platform/macOS/ContentView.swift

@@ -18,6 +18,7 @@ import SwiftUI
 
 @available(macOS 11, *)
 struct ContentView: View {
+    @StateObject private var newConfiguration = UTMConfiguration()
     @State private var editMode = false
     @StateObject private var data = UTMData()
     @State private var newPopupPresented = false
@@ -44,10 +45,15 @@ struct ContentView: View {
                 }
             }
             VMPlaceholderView(createNewVMPresented: $newVMScratchPresented)
-            .sheet(isPresented: $newVMScratchPresented) {
-                VMSettingsView(vm: nil, config: UTMConfiguration(name: data.newDefaultVMName()))
+            .sheet(isPresented: $newVMScratchPresented, onDismiss: {
+                newConfiguration.resetDefaults()
+            }, content: {
+                VMSettingsView(vm: nil, config: newConfiguration)
                     .environmentObject(data)
-            }
+                    .onAppear {
+                        newConfiguration.name = data.newDefaultVMName()
+                    }
+            })
         }.overlay(BusyOverlay())
         .environmentObject(data)
         .frame(minWidth: 800, idealWidth: 1200, minHeight: 600, idealHeight: 800)

+ 1 - 1
Platform/macOS/VMConfigDrivesView.swift

@@ -135,7 +135,7 @@ struct DriveCard: View {
 
 @available(macOS 11, *)
 struct VMConfigDrivesView_Previews: PreviewProvider {
-    @ObservedObject static private var config = UTMConfiguration(name: "Test")
+    @ObservedObject static private var config = UTMConfiguration()
     
     static var previews: some View {
         Group {

+ 1 - 1
Platform/macOS/VMConfigNetworkPortForwardView.swift

@@ -99,7 +99,7 @@ struct PortForwardEdit: View {
 
 @available(macOS 11, *)
 struct VMConfigNetworkPortForwardView_Previews: PreviewProvider {
-    @State static private var config = UTMConfiguration(name: "Test")
+    @State static private var config = UTMConfiguration()
     @State static private var configPort = UTMConfigurationPortForward()
     
     static var previews: some View {

+ 1 - 1
Platform/macOS/VMSettingsView.swift

@@ -117,7 +117,7 @@ struct PreferencePane<Content: View>: View {
 
 @available(macOS 11, *)
 struct VMSettingsView_Previews: PreviewProvider {
-    @State static private var config = UTMConfiguration(name: "Test")
+    @State static private var config = UTMConfiguration()
     
     static var previews: some View {
         VMSettingsView(vm: nil, config: config)