修复:部署目标降至 11.0,秒数/12小时制改为可配置
- 将 MACOSX_DEPLOYMENT_TARGET 由项目级 27.0 / 目标级 15.6 统一改为 11.0 (代码所用 API 的最低门槛为 11.0),使屏保可在当前及更早系统加载 - showSeconds / use24Hour 由写死的 static let 改为设置驱动的可选项: * FlipClockSettings 新增键 showSeconds / use24Hour,支持持久化与读取 * 设置面板新增「显示秒数」「24 小时制」两个勾选项,取消可回滚 * 视图的 loadSettings / 跨进程轮询 / 设置通知均同步新选项 * 原 use24Hour=false 的 AM/PM 死代码现已可经设置启用
This commit is contained in:
@@ -191,7 +191,7 @@
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 27.0;
|
||||
MACOSX_DEPLOYMENT_TARGET = 11.0;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
@@ -247,7 +247,7 @@
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 27.0;
|
||||
MACOSX_DEPLOYMENT_TARGET = 11.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
SDKROOT = macosx;
|
||||
@@ -266,7 +266,7 @@
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
INFOPLIST_KEY_NSPrincipalClass = FlipClockSaverView;
|
||||
INSTALL_PATH = "$(HOME)/Library/Screen Savers";
|
||||
MACOSX_DEPLOYMENT_TARGET = 15.6;
|
||||
MACOSX_DEPLOYMENT_TARGET = 11.0;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.liucheng.FlipClockSaver;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
@@ -291,7 +291,7 @@
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
INFOPLIST_KEY_NSPrincipalClass = FlipClockSaverView;
|
||||
INSTALL_PATH = "$(HOME)/Library/Screen Savers";
|
||||
MACOSX_DEPLOYMENT_TARGET = 15.6;
|
||||
MACOSX_DEPLOYMENT_TARGET = 11.0;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.liucheng.FlipClockSaver;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
|
||||
@@ -146,9 +146,9 @@ final class FlipDigit {
|
||||
@objc(FlipClockSaverView)
|
||||
final class FlipClockSaverView: ScreenSaverView {
|
||||
|
||||
// 顶部可配置项
|
||||
static let showSeconds = true
|
||||
static let use24Hour = true
|
||||
// 顶部可配置项(运行时由设置驱动,不再写死)
|
||||
private var showSeconds = true
|
||||
private var use24Hour = true
|
||||
|
||||
// 尺寸 / 缩放(fitScale 可在设置面板中调整)
|
||||
private let unitW: CGFloat = 108
|
||||
@@ -228,11 +228,11 @@ final class FlipClockSaverView: ScreenSaverView {
|
||||
|
||||
addDigit(h0); addDigit(h1); addColon()
|
||||
addDigit(m0); addDigit(m1)
|
||||
if Self.showSeconds { addColon(); addDigit(s0); addDigit(s1) }
|
||||
if showSeconds { addColon(); addDigit(s0); addDigit(s1) }
|
||||
|
||||
digits = ds; rects = rs; colonRects = cols
|
||||
|
||||
if !Self.use24Hour {
|
||||
if !use24Hour {
|
||||
ampmRect = CGRect(x: cur, y: 0, width: 120, height: unitH)
|
||||
cur += 120 + spacing
|
||||
}
|
||||
@@ -245,7 +245,7 @@ final class FlipClockSaverView: ScreenSaverView {
|
||||
let now = Calendar.current.dateComponents([.hour, .minute, .second], from: Date())
|
||||
var h = now.hour ?? 0
|
||||
var ampm = ""
|
||||
if !Self.use24Hour {
|
||||
if !use24Hour {
|
||||
ampm = h >= 12 ? "PM" : "AM"
|
||||
h = h % 12
|
||||
if h == 0 { h = 12 }
|
||||
@@ -257,7 +257,7 @@ final class FlipClockSaverView: ScreenSaverView {
|
||||
Int(String(hh.prefix(1))) ?? 0, Int(String(hh.suffix(1))) ?? 0,
|
||||
Int(String(mm.prefix(1))) ?? 0, Int(String(mm.suffix(1))) ?? 0
|
||||
]
|
||||
if Self.showSeconds {
|
||||
if showSeconds {
|
||||
vals.append(Int(String(ss.prefix(1))) ?? 0)
|
||||
vals.append(Int(String(ss.suffix(1))) ?? 0)
|
||||
}
|
||||
@@ -292,11 +292,17 @@ final class FlipClockSaverView: ScreenSaverView {
|
||||
let newScale = FlipClockSettings.fitScale
|
||||
let newShowDate = FlipClockSettings.showDate
|
||||
let newShowLunar = FlipClockSettings.showLunar
|
||||
guard newScale != fitScale || newShowDate != showDate || newShowLunar != showLunar else { return }
|
||||
let newShowSeconds = FlipClockSettings.showSeconds
|
||||
let newUse24Hour = FlipClockSettings.use24Hour
|
||||
guard newScale != fitScale || newShowDate != showDate || newShowLunar != showLunar
|
||||
|| newShowSeconds != showSeconds || newUse24Hour != use24Hour else { return }
|
||||
let togglesChanged = newShowDate != showDate || newShowLunar != showLunar
|
||||
|| newShowSeconds != showSeconds || newUse24Hour != use24Hour
|
||||
fitScale = newScale
|
||||
showDate = newShowDate
|
||||
showLunar = newShowLunar
|
||||
showSeconds = newShowSeconds
|
||||
use24Hour = newUse24Hour
|
||||
if togglesChanged {
|
||||
buildLayout()
|
||||
update(animated: false, at: frameTime)
|
||||
@@ -321,7 +327,7 @@ final class FlipClockSaverView: ScreenSaverView {
|
||||
cardBg: cardBg, textColor: textColor, now: now)
|
||||
}
|
||||
for c in colonRects { drawColon(in: ctx, rect: c) }
|
||||
if !Self.use24Hour, let ar = ampmRect { drawAmPm(in: ctx, rect: ar) }
|
||||
if !use24Hour, let ar = ampmRect { drawAmPm(in: ctx, rect: ar) }
|
||||
if showDate || showLunar { drawInfo(in: ctx, rect: infoRect) }
|
||||
ctx.restoreGState()
|
||||
}
|
||||
@@ -418,16 +424,21 @@ final class FlipClockSaverView: ScreenSaverView {
|
||||
@objc private func handleSettingsChanged(_ note: Notification) {
|
||||
let oldShowDate = showDate
|
||||
let oldShowLunar = showLunar
|
||||
let oldShowSeconds = showSeconds
|
||||
let oldUse24Hour = use24Hour
|
||||
if let info = note.userInfo, !info.isEmpty {
|
||||
// 直接从通知携带的值应用,不依赖 defaults 读回路径
|
||||
if let v = info[FlipClockSettings.keyScale] as? Double { fitScale = CGFloat(v) }
|
||||
if let v = info[FlipClockSettings.keyShowDate] as? Bool { showDate = v }
|
||||
if let v = info[FlipClockSettings.keyShowLunar] as? Bool { showLunar = v }
|
||||
if let v = info[FlipClockSettings.keyShowSeconds] as? Bool { showSeconds = v }
|
||||
if let v = info[FlipClockSettings.keyUse24Hour] as? Bool { use24Hour = v }
|
||||
} else {
|
||||
loadSettings()
|
||||
}
|
||||
NSLog("[FlipClock] view 收到设置通知,已应用 scale=%.2f", Double(fitScale))
|
||||
if oldShowDate != showDate || oldShowLunar != showLunar {
|
||||
if oldShowDate != showDate || oldShowLunar != showLunar
|
||||
|| oldShowSeconds != showSeconds || oldUse24Hour != use24Hour {
|
||||
buildLayout()
|
||||
update(animated: false, at: frameTime)
|
||||
}
|
||||
@@ -438,6 +449,8 @@ final class FlipClockSaverView: ScreenSaverView {
|
||||
fitScale = FlipClockSettings.fitScale
|
||||
showDate = FlipClockSettings.showDate
|
||||
showLunar = FlipClockSettings.showLunar
|
||||
showSeconds = FlipClockSettings.showSeconds
|
||||
use24Hour = FlipClockSettings.use24Hour
|
||||
}
|
||||
}
|
||||
|
||||
@@ -451,6 +464,8 @@ enum FlipClockSettings {
|
||||
static let keyScale = "fitScale"
|
||||
static let keyShowDate = "showDate"
|
||||
static let keyShowLunar = "showLunar"
|
||||
static let keyShowSeconds = "showSeconds"
|
||||
static let keyUse24Hour = "use24Hour"
|
||||
static let defaultScale = 0.55
|
||||
|
||||
static let defaults: ScreenSaverDefaults = {
|
||||
@@ -459,7 +474,8 @@ enum FlipClockSettings {
|
||||
}()
|
||||
|
||||
static func registerDefaults() {
|
||||
defaults.register(defaults: [keyScale: defaultScale, keyShowDate: true, keyShowLunar: true])
|
||||
defaults.register(defaults: [keyScale: defaultScale, keyShowDate: true, keyShowLunar: true,
|
||||
keyShowSeconds: true, keyUse24Hour: true])
|
||||
}
|
||||
|
||||
// 主存储:直接读写 plist 文件,绕开 cfprefsd 缓存。
|
||||
@@ -477,8 +493,9 @@ enum FlipClockSettings {
|
||||
return dict
|
||||
}
|
||||
|
||||
static func save(scale: Double, showDate: Bool, showLunar: Bool) {
|
||||
let dict: [String: Any] = [keyScale: scale, keyShowDate: showDate, keyShowLunar: showLunar]
|
||||
static func save(scale: Double, showDate: Bool, showLunar: Bool, showSeconds: Bool, use24Hour: Bool) {
|
||||
let dict: [String: Any] = [keyScale: scale, keyShowDate: showDate, keyShowLunar: showLunar,
|
||||
keyShowSeconds: showSeconds, keyUse24Hour: use24Hour]
|
||||
var fileOK = false
|
||||
if let data = try? PropertyListSerialization.data(fromPropertyList: dict, format: .xml, options: 0) {
|
||||
try? FileManager.default.createDirectory(at: settingsURL.deletingLastPathComponent(),
|
||||
@@ -495,7 +512,10 @@ enum FlipClockSettings {
|
||||
d.set(scale, forKey: keyScale)
|
||||
d.set(showDate, forKey: keyShowDate)
|
||||
d.set(showLunar, forKey: keyShowLunar)
|
||||
NSLog("[FlipClock] 设置已保存(fileOK=%d): scale=%.2f date=%d lunar=%d", fileOK, scale, showDate, showLunar)
|
||||
d.set(showSeconds, forKey: keyShowSeconds)
|
||||
d.set(use24Hour, forKey: keyUse24Hour)
|
||||
NSLog("[FlipClock] 设置已保存(fileOK=%d): scale=%.2f date=%d lunar=%d seconds=%d hour24=%d",
|
||||
fileOK, scale, showDate, showLunar, showSeconds, use24Hour)
|
||||
}
|
||||
|
||||
static var fitScale: CGFloat {
|
||||
@@ -513,6 +533,16 @@ enum FlipClockSettings {
|
||||
if let v = readFile()[keyShowLunar] as? Bool { return v }
|
||||
return defaults.object(forKey: keyShowLunar) as? Bool ?? true
|
||||
}
|
||||
|
||||
static var showSeconds: Bool {
|
||||
if let v = readFile()[keyShowSeconds] as? Bool { return v }
|
||||
return defaults.object(forKey: keyShowSeconds) as? Bool ?? true
|
||||
}
|
||||
|
||||
static var use24Hour: Bool {
|
||||
if let v = readFile()[keyUse24Hour] as? Bool { return v }
|
||||
return defaults.object(forKey: keyUse24Hour) as? Bool ?? true
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - 设置窗口(纯代码构建,无 xib)
|
||||
@@ -524,14 +554,18 @@ final class FlipClockConfigController: NSWindowController {
|
||||
private let scaleLabel = NSTextField(labelWithString: "55%")
|
||||
private let showDateBox = NSButton(checkboxWithTitle: "显示公历日期", target: nil, action: nil)
|
||||
private let showLunarBox = NSButton(checkboxWithTitle: "显示农历", target: nil, action: nil)
|
||||
private let showSecondsBox = NSButton(checkboxWithTitle: "显示秒数", target: nil, action: nil)
|
||||
private let use24Box = NSButton(checkboxWithTitle: "24 小时制", target: nil, action: nil)
|
||||
|
||||
// 打开时的原始值,用于“取消”时回滚
|
||||
private var originalScale: Double = 0.55
|
||||
private var originalShowDate = true
|
||||
private var originalShowLunar = true
|
||||
private var originalShowSeconds = true
|
||||
private var originalUse24Hour = true
|
||||
|
||||
init() {
|
||||
let window = NSWindow(contentRect: NSRect(x: 0, y: 0, width: 340, height: 196),
|
||||
let window = NSWindow(contentRect: NSRect(x: 0, y: 0, width: 340, height: 256),
|
||||
styleMask: [.titled], backing: .buffered, defer: false)
|
||||
window.title = "翻页时钟设置"
|
||||
window.isReleasedWhenClosed = false
|
||||
@@ -546,9 +580,13 @@ final class FlipClockConfigController: NSWindowController {
|
||||
originalScale = Double(FlipClockSettings.fitScale)
|
||||
originalShowDate = FlipClockSettings.showDate
|
||||
originalShowLunar = FlipClockSettings.showLunar
|
||||
originalShowSeconds = FlipClockSettings.showSeconds
|
||||
originalUse24Hour = FlipClockSettings.use24Hour
|
||||
scaleSlider.doubleValue = originalScale
|
||||
showDateBox.state = originalShowDate ? .on : .off
|
||||
showLunarBox.state = originalShowLunar ? .on : .off
|
||||
showSecondsBox.state = originalShowSeconds ? .on : .off
|
||||
use24Box.state = originalUse24Hour ? .on : .off
|
||||
updateScaleLabel()
|
||||
}
|
||||
|
||||
@@ -557,36 +595,43 @@ final class FlipClockConfigController: NSWindowController {
|
||||
}
|
||||
|
||||
private func buildUI() {
|
||||
let content = NSView(frame: NSRect(x: 0, y: 0, width: 340, height: 196))
|
||||
let content = NSView(frame: NSRect(x: 0, y: 0, width: 340, height: 256))
|
||||
window?.contentView = content
|
||||
let left: CGFloat = 20
|
||||
|
||||
let titleLabel = NSTextField(labelWithString: "整体缩放:")
|
||||
titleLabel.frame = CGRect(x: left, y: 152, width: 76, height: 17)
|
||||
scaleSlider.frame = CGRect(x: left + 76, y: 148, width: 170, height: 24)
|
||||
titleLabel.frame = CGRect(x: left, y: 212, width: 76, height: 17)
|
||||
scaleSlider.frame = CGRect(x: left + 76, y: 208, width: 170, height: 24)
|
||||
scaleSlider.target = self
|
||||
scaleSlider.action = #selector(sliderChanged)
|
||||
scaleLabel.frame = CGRect(x: left + 254, y: 152, width: 56, height: 17)
|
||||
scaleLabel.frame = CGRect(x: left + 254, y: 212, width: 56, height: 17)
|
||||
scaleLabel.alignment = .right
|
||||
|
||||
showDateBox.frame = CGRect(x: left, y: 116, width: 200, height: 20)
|
||||
showDateBox.frame = CGRect(x: left, y: 176, width: 200, height: 20)
|
||||
showDateBox.target = self
|
||||
showDateBox.action = #selector(controlChanged)
|
||||
showLunarBox.frame = CGRect(x: left, y: 84, width: 200, height: 20)
|
||||
showLunarBox.frame = CGRect(x: left, y: 144, width: 200, height: 20)
|
||||
showLunarBox.target = self
|
||||
showLunarBox.action = #selector(controlChanged)
|
||||
showSecondsBox.frame = CGRect(x: left, y: 112, width: 200, height: 20)
|
||||
showSecondsBox.target = self
|
||||
showSecondsBox.action = #selector(controlChanged)
|
||||
use24Box.frame = CGRect(x: left, y: 80, width: 200, height: 20)
|
||||
use24Box.target = self
|
||||
use24Box.action = #selector(controlChanged)
|
||||
|
||||
let okBtn = NSButton(title: "好", target: self, action: #selector(okPressed))
|
||||
okBtn.bezelStyle = .rounded
|
||||
okBtn.keyEquivalent = "\r"
|
||||
okBtn.frame = CGRect(x: 244, y: 20, width: 76, height: 32)
|
||||
okBtn.frame = CGRect(x: 244, y: 24, width: 76, height: 32)
|
||||
|
||||
let cancelBtn = NSButton(title: "取消", target: self, action: #selector(cancelPressed))
|
||||
cancelBtn.bezelStyle = .rounded
|
||||
cancelBtn.keyEquivalent = "\u{1b}"
|
||||
cancelBtn.frame = CGRect(x: 160, y: 20, width: 76, height: 32)
|
||||
cancelBtn.frame = CGRect(x: 160, y: 24, width: 76, height: 32)
|
||||
|
||||
let views: [NSView] = [titleLabel, scaleSlider, scaleLabel, showDateBox, showLunarBox, okBtn, cancelBtn]
|
||||
let views: [NSView] = [titleLabel, scaleSlider, scaleLabel, showDateBox, showLunarBox,
|
||||
showSecondsBox, use24Box, okBtn, cancelBtn]
|
||||
for v in views { content.addSubview(v) }
|
||||
}
|
||||
|
||||
@@ -600,23 +645,29 @@ final class FlipClockConfigController: NSWindowController {
|
||||
private func applyCurrentValues() {
|
||||
apply(scale: scaleSlider.doubleValue,
|
||||
showDate: showDateBox.state == .on,
|
||||
showLunar: showLunarBox.state == .on)
|
||||
showLunar: showLunarBox.state == .on,
|
||||
showSeconds: showSecondsBox.state == .on,
|
||||
use24Hour: use24Box.state == .on)
|
||||
}
|
||||
|
||||
// 实时保存并广播(userInfo 携带最新值):同进程即时生效,跨进程靠文件轮询同步
|
||||
private func apply(scale: Double, showDate: Bool, showLunar: Bool) {
|
||||
FlipClockSettings.save(scale: scale, showDate: showDate, showLunar: showLunar)
|
||||
private func apply(scale: Double, showDate: Bool, showLunar: Bool, showSeconds: Bool, use24Hour: Bool) {
|
||||
FlipClockSettings.save(scale: scale, showDate: showDate, showLunar: showLunar,
|
||||
showSeconds: showSeconds, use24Hour: use24Hour)
|
||||
NotificationCenter.default.post(name: .flipClockSettingsDidChange, object: nil,
|
||||
userInfo: [FlipClockSettings.keyScale: scale,
|
||||
FlipClockSettings.keyShowDate: showDate,
|
||||
FlipClockSettings.keyShowLunar: showLunar])
|
||||
FlipClockSettings.keyShowLunar: showLunar,
|
||||
FlipClockSettings.keyShowSeconds: showSeconds,
|
||||
FlipClockSettings.keyUse24Hour: use24Hour])
|
||||
}
|
||||
|
||||
@objc private func okPressed() { dismissSheet() }
|
||||
|
||||
@objc private func cancelPressed() {
|
||||
// 恢复打开前的设置
|
||||
apply(scale: originalScale, showDate: originalShowDate, showLunar: originalShowLunar)
|
||||
apply(scale: originalScale, showDate: originalShowDate, showLunar: originalShowLunar,
|
||||
showSeconds: originalShowSeconds, use24Hour: originalUse24Hour)
|
||||
dismissSheet()
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user