Вопрос или проблема
В настоящее время я разрабатываю приложение текстового редактора, которое позволяет пользователям открывать, редактировать и сохранять файлы. Однако я столкнулся с проблемой управления заголовком окна.
Когда я впервые открываю приложение, заголовок окна правильно отображает “Без названия”, что мне нужно. Однако, если я закрою приложение, используя встроенную кнопку закрытия в верхнем левом углу (вместо выхода из приложения), и затем заново открою его, заголовок окна изменится на название приложения вместо того, чтобы вернуться к “Без названия”.
Кроме того, когда я открываю файл, заголовок окна изменяется на название приложения, а не на название открываемого файла.
Вот соответствующая часть моего кода:
import SwiftUI
struct ContentView: View {
@State private var text: String = ""
@State private var currentFileURL: URL?
@State private var windowTitle: String = "Без названия"
var body: some View {
VStack {
TextEditor(text: $text)
.padding()
}
.frame(minWidth: 600, minHeight: 400)
.onAppear {
updateWindowTitle()
}
.onReceive(NotificationCenter.default.publisher(for: .openFile)) { _ in
openFile()
}
.onReceive(NotificationCenter.default.publisher(for: .saveFile)) { _ in
saveFile()
}
}
func openFile() {
let panel = NSOpenPanel()
panel.allowedFileTypes = ["txt"]
panel.allowsMultipleSelection = false
panel.canChooseDirectories = false
if panel.runModal() == .OK, let url = panel.url {
do {
let fileContents = try String(contentsOf: url, encoding: .utf8)
self.text = fileContents
self.currentFileURL = url
updateWindowTitle(with: url)
} catch {
print("ошибка: \(error.localizedDescription)")
}
}
}
func saveFile() {
if let url = currentFileURL {
do {
try text.write(to: url, atomically: true, encoding: .utf8)
updateWindowTitle(with: url)
} catch {
print("ошибка: \(error.localizedDescription)")
}
} else {
let panel = NSSavePanel()
panel.allowedFileTypes = ["txt"]
panel.nameFieldStringValue = "new.txt"
if panel.runModal() == .OK, let saveURL = panel.url {
do {
try text.write(to: saveURL, atomically: true, encoding: .utf8)
self.currentFileURL = saveURL
updateWindowTitle(with: saveURL)
} catch {
print("ошибка: \(error.localizedDescription)")
}
}
}
}
func updateWindowTitle(with fileURL: URL? = nil) {
let window = NSApplication.shared.windows.first
if let url = fileURL {
window?.title = url.lastPathComponent
} else {
window?.title = "Без названия"
}
}
}
Я был бы признателен за любые советы о том, как гарантировать, чтобы заголовок окна вел себя ожидаемым образом — показывал “Без названия”, когда файлы не открыты, и отображал имя файла, когда файл открыт.
Спасибо за вашу помощь!
Ответ или решение
Проблема с заголовком окна в приложении текстового редактора на macOS, разработанном на SwiftUI
Введение
Разработка текстового редактора на SwiftUI может оказаться увлекательной задачей. Однако, как и в любом проекте, иногда возникают трудности, связанные с функциональностью. В вашем случае проблема заключается в неправильном отображении заголовка окна при открытии и закрытии приложения, а также изменении имени файла после открытия.
Проблема
Вы описали две ключевые проблемы:
- При повторном запуске приложения заголовок окна меняется с "Untitled" на название приложения.
- При открытии файла заголовок окна должен менять свое значение на имя открытого файла, но вместо этого отображается название приложения.
Это может быть связано с тем, как вы обрабатываете состояние приложения и с тем, как обновляется заголовок окна в разных случаях.
Решение
Для решения вашей проблемы необходимо внести небольшие изменения в вашу реализацию, чтобы убедиться, что заголовок окна обновляется в зависимости от состояния приложения. Рассмотрим, как это можно сделать.
-
Добавьте обработку события при закрытии окна.
Вам нужно будет установить значение заголовка окна в "Untitled" при запуске приложения. Можно использовать методapplicationDidFinishLaunching
, чтобы инициализировать заголовок. -
Измените метод
updateWindowTitle
.
Данный метод должен более четко разделять ситуации при открытии файла и при отсутствии открытых файлов. Изменения должны выглядеть следующим образом:
func updateWindowTitle(with fileURL: URL? = nil) {
guard let window = NSApplication.shared.windows.first else { return }
if let url = fileURL {
window.title = url.lastPathComponent
} else {
window.title = "Untitled"
}
}
- Добавьте обработчик при перезапуске приложения.
Убедитесь, что ваше приложение правильно переходит в состояние "Untitled" при старте. Например:
@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
ContentView()
.onAppear {
NSApplication.shared.windows.first?.title = "Untitled"
}
}
}
}
- Убедитесь, что заголовок окна обновляется после открытия файла.
Проверьте, чтоupdateWindowTitle(with: url)
вызывается правильно в методахopenFile
иsaveFile
, чтобы заголовок был всегда актуальным.
Пример кода
После внесения изменений ваш код может выглядеть следующим образом:
import SwiftUI
@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
ContentView()
.onAppear {
NSApplication.shared.windows.first?.title = "Untitled"
}
}
}
}
struct ContentView: View {
@State private var text: String = ""
@State private var currentFileURL: URL?
var body: some View {
VStack {
TextEditor(text: $text)
.padding()
}
.frame(minWidth: 600, minHeight: 400)
.onAppear {
updateWindowTitle()
}
.onReceive(NotificationCenter.default.publisher(for: .openFile)) { _ in
openFile()
}
.onReceive(NotificationCenter.default.publisher(for: .saveFile)) { _ in
saveFile()
}
}
func openFile() {
// Implement the file opening logic
}
func saveFile() {
// Implement the file saving logic
}
func updateWindowTitle(with fileURL: URL? = nil) {
let window = NSApplication.shared.windows.first
if let url = fileURL {
window?.title = url.lastPathComponent
} else {
window?.title = "Untitled"
}
}
}
Заключение
Следуя указанным выше рекомендациям, вы сможете корректно управлять заголовком окна в вашем текстовом редакторе на SwiftUI, обеспечивая правильное отображение имени файла или значения "Untitled". Убедитесь, что все элементы вашего проекта слаженно работают друг с другом для достижения оптимального результата.
Если у вас возникнут дополнительные вопросы или потребуется дальнейшая помощь, пожалуйста, не стесняйтесь обращаться.