如何在 Swift 中创建设置对象
How to create a settings object in Swift
我正在尝试在 Swift-3 中创建一个对象,它将保存各种基本的用户设置,这些设置可以在整个应用程序中轻松访问。我目前将此设置作为一个名为 PTSettings
的结构。它是这样实现的:
struct PTSettings {
static var aUserSettings: String()
}
可以像这样在应用程序周围轻松访问:PTSettings.aUserSetting = "Foo"
我在这里苦苦挣扎的是我希望这个结构观察来自 NotificationCenter
的 UIScreen 通知。当屏幕连接时 PTSettings
初始化外部屏幕,为其分配视图,显示横幅让用户知道等等...
我熟悉在 UIViewController 上执行所有这些任务;但是我不精通使用结构。我希望当应用程序加载时,该结构将被初始化,并且 init 将观察 NotificationCenter
,同时还会检查在加载应用程序之前是否连接了屏幕。
以下是我目前拥有的。
/// Struct containing various user-generate data such as color, messages and other settings.
struct PTSettings {
// External UI
//
static var externalScreen: UIScreen!
//
static var externalWindow: UIWindow!
//
static var extDisplay: PTExternalDisplayVC?
init () {
// Receive notifications if a screen is connected or disconnected
//
let center = NotificationCenter.default
center.addObserver(self, selector: #selector(PTSettings.handleScreenDidConnectNotification(notification:)), name: NSNotification.Name.UIScreenDidConnect, object: nil)
center.addObserver(self, selector: #selector(PTSettings.handleScreenDidDisconnectNotification(notification:)), name: NSNotification.Name.UIScreenDidDisconnect, object: nil)
center.addObserver(self, selector: #selector(PTSettings.handleScreenModeDidChangeNotification), name: NSNotification.Name.UIScreenModeDidChange, object: nil)
}
// MARK: External Displays
//
static func initializeExternalScreen(externalScreen:UIScreen) {
self.externalScreen = externalScreen
externalScreen.overscanCompensation = UIScreenOverscanCompensation(rawValue: 3)!
// Create a new window sized to the external screen's bounds
self.externalWindow = UIWindow(frame: self.externalScreen.bounds)
// Assign screen object to screen property of the new window
self.externalWindow.screen = externalScreen
// Load the clock view
let viewForExternalScreen = self.storyboard?.instantiateViewController(withIdentifier: "ExternalDisplay") as! PTExternalDisplayVC
viewForExternalScreen.view.frame = self.externalWindow.frame
// Add the view to the window
self.externalWindow.addSubview(viewForExternalScreen.view)
// Create a reference to the viewForExternalScreen
self.extDisplay = viewForExternalScreen
// Make the window visible
self.externalWindow.makeKeyAndVisible()
}
//
static func handleScreenDidConnectNotification (notification:Notification) {
if let screen = notification.object as? UIScreen {
initializeExternalScreen(externalScreen: screen)
}
}
//
static func handleScreenDidDisconnectNotification (notification:Notification) {
if externalWindow != nil {
externalWindow.isHidden = true
externalWindow = nil
displayConnectedLabel.text = "No Display"
displayConnectedLabel.textColor = CustomColors.Red.color
JSSAlertView().warning(self, title: "External Display Disconnected.")
}
}
//
static func handleScreenModeDidChangeNotification () {
let screen = UIScreen.screens[1]
initializeExternalScreen(externalScreen: screen)
}
}
编译器在 init()
方法中每次添加观察者时都会抱怨,如下所示:
“#selector”的参数指的是未公开给 Objective-C
的静态方法 'handleScreenDidConnectNotification(notification:)'
但是在方法前添加 @objc
时,它会抱怨:
@objc 只能与 类 的成员、@objc 协议和 类.
的具体扩展一起使用
我怎样才能达到预期的结果,我是否完全不喜欢这种方法?
am I just totally off in this approach
你确实完全不对劲。区分 Objective-C(和 Cocoa)和 Swift。 Swift 结构是纯粹的 Swift 特性。您正在尝试使用 Cocoa 功能,即通过 选择器 调用具有 Swift 功能的方法,一个结构。你不能那样做。 Swift 结构缺少允许选择器工作的 Objective-C 自省功能。这就是为什么您只能为 Objective-C class 的方法创建选择器,即 继承自的 class NSObject(就像你过去所做的那样)。
但是,another form 添加通知中心观察器,您在其中使用尾随闭包/函数,而不是选择器。您可以尝试这样做(尽管我不保证任何事情)。
我正在尝试在 Swift-3 中创建一个对象,它将保存各种基本的用户设置,这些设置可以在整个应用程序中轻松访问。我目前将此设置作为一个名为 PTSettings
的结构。它是这样实现的:
struct PTSettings {
static var aUserSettings: String()
}
可以像这样在应用程序周围轻松访问:PTSettings.aUserSetting = "Foo"
我在这里苦苦挣扎的是我希望这个结构观察来自 NotificationCenter
的 UIScreen 通知。当屏幕连接时 PTSettings
初始化外部屏幕,为其分配视图,显示横幅让用户知道等等...
我熟悉在 UIViewController 上执行所有这些任务;但是我不精通使用结构。我希望当应用程序加载时,该结构将被初始化,并且 init 将观察 NotificationCenter
,同时还会检查在加载应用程序之前是否连接了屏幕。
以下是我目前拥有的。
/// Struct containing various user-generate data such as color, messages and other settings.
struct PTSettings {
// External UI
//
static var externalScreen: UIScreen!
//
static var externalWindow: UIWindow!
//
static var extDisplay: PTExternalDisplayVC?
init () {
// Receive notifications if a screen is connected or disconnected
//
let center = NotificationCenter.default
center.addObserver(self, selector: #selector(PTSettings.handleScreenDidConnectNotification(notification:)), name: NSNotification.Name.UIScreenDidConnect, object: nil)
center.addObserver(self, selector: #selector(PTSettings.handleScreenDidDisconnectNotification(notification:)), name: NSNotification.Name.UIScreenDidDisconnect, object: nil)
center.addObserver(self, selector: #selector(PTSettings.handleScreenModeDidChangeNotification), name: NSNotification.Name.UIScreenModeDidChange, object: nil)
}
// MARK: External Displays
//
static func initializeExternalScreen(externalScreen:UIScreen) {
self.externalScreen = externalScreen
externalScreen.overscanCompensation = UIScreenOverscanCompensation(rawValue: 3)!
// Create a new window sized to the external screen's bounds
self.externalWindow = UIWindow(frame: self.externalScreen.bounds)
// Assign screen object to screen property of the new window
self.externalWindow.screen = externalScreen
// Load the clock view
let viewForExternalScreen = self.storyboard?.instantiateViewController(withIdentifier: "ExternalDisplay") as! PTExternalDisplayVC
viewForExternalScreen.view.frame = self.externalWindow.frame
// Add the view to the window
self.externalWindow.addSubview(viewForExternalScreen.view)
// Create a reference to the viewForExternalScreen
self.extDisplay = viewForExternalScreen
// Make the window visible
self.externalWindow.makeKeyAndVisible()
}
//
static func handleScreenDidConnectNotification (notification:Notification) {
if let screen = notification.object as? UIScreen {
initializeExternalScreen(externalScreen: screen)
}
}
//
static func handleScreenDidDisconnectNotification (notification:Notification) {
if externalWindow != nil {
externalWindow.isHidden = true
externalWindow = nil
displayConnectedLabel.text = "No Display"
displayConnectedLabel.textColor = CustomColors.Red.color
JSSAlertView().warning(self, title: "External Display Disconnected.")
}
}
//
static func handleScreenModeDidChangeNotification () {
let screen = UIScreen.screens[1]
initializeExternalScreen(externalScreen: screen)
}
}
编译器在 init()
方法中每次添加观察者时都会抱怨,如下所示:
“#selector”的参数指的是未公开给 Objective-C
的静态方法 'handleScreenDidConnectNotification(notification:)'但是在方法前添加 @objc
时,它会抱怨:
@objc 只能与 类 的成员、@objc 协议和 类.
的具体扩展一起使用我怎样才能达到预期的结果,我是否完全不喜欢这种方法?
am I just totally off in this approach
你确实完全不对劲。区分 Objective-C(和 Cocoa)和 Swift。 Swift 结构是纯粹的 Swift 特性。您正在尝试使用 Cocoa 功能,即通过 选择器 调用具有 Swift 功能的方法,一个结构。你不能那样做。 Swift 结构缺少允许选择器工作的 Objective-C 自省功能。这就是为什么您只能为 Objective-C class 的方法创建选择器,即 继承自的 class NSObject(就像你过去所做的那样)。
但是,another form 添加通知中心观察器,您在其中使用尾随闭包/函数,而不是选择器。您可以尝试这样做(尽管我不保证任何事情)。