I'm trying to export a document file. It contains a codable struct named NoteGroup.
struct NoteGroup: Codable {
let id: UUID
let name: String
let createAt: Date
let children: [NoteChild]
init(id: UUID = .init(), name: String = "", createAt: Date = .init(), children: [NoteChild]) {
self.id = id
self.name = name
self.createAt = createAt
self.children = children
}
}
, which contains another object named NoteChild. I have a FileDocument struct as follows.
import SwiftUI
import UniformTypeIdentifiers
struct Document: FileDocument {
var document: NoteGroup
static var readableContentTypes = [UTType.frogType]
init(document: NoteGroup = NoteGroup(children: [NoteChild(id: UUID(), name: "", createAt: Date())])) {
self.document = document
}
init(configuration: ReadConfiguration) throws {
self.init()
}
func fileWrapper(configuration: WriteConfiguration) throws -> FileWrapper {
do {
let data = try getDocumentData()
let jsonFileWrapper = FileWrapper(regularFileWithContents: data)
let filename = "Note.frog"
jsonFileWrapper.filename = filename
let fileWrapper = FileWrapper(directoryWithFileWrappers: [filename: jsonFileWrapper])
return fileWrapper
} catch {
throw error
}
}
private func getDocumentData() throws -> Data {
let encoder = JSONEncoder()
do {
let data = try encoder.encode(document)
return data
} catch {
throw error
}
}
}
extension UTType {
public static let frogType = UTType(exportedAs: "com.example.frog")
}
And I export a file like the following.
import SwiftUI
import UniformTypeIdentifiers
struct ContentView: View {
@State private var showingExporter = false
@State var doc = Document()
var body: some View {
VStack {
Button("Tap to export") {
showingExporter.toggle()
}
.fileExporter(
isPresented: $showingExporter,
document: doc,
contentType: .frogType
) { result in
switch result {
case .success(let file):
print(file)
case .failure(let error):
print(error)
}
}
}.onAppear {
doc = Document(document: NoteGroup(id: UUID(), name: "Kyle", createAt: Date(), children: [NoteChild(id: UUID(), name: "Nancy", createAt: Date())]))
}
}
}
Well, I have read this topic. And I've watched this video about Uniform Type Identifiers. Thanks to the video, I am able to export a file. Yet, I end up with a folder (Frog.frog), not a packaged file. There is a JSON file in it, though. What am I doing wrong? It's for iOS. La vida no es facil. Muchos thankos.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
I have a ForEach loop with Range that I use with Picker. I'm using Range because I want to set startYear and endYear when View appears. The following is my code.
import SwiftUI
struct ProviderCalendarView: View {
@State private var startYear: Int = 2023
@State private var endYear: Int = 2034
@State private var selectedYear = 3
var body: some View {
VStack {
HStack {
Picker(selection: $selectedYear) {
ForEach((startYear...endYear), id: \.self) { year in
Text("\(year)")
}
} label: {
}
}
}
}
}
And the compiler says the following.
Picker: the selection "3" is invalid and does not have an associated tag, this will give undefined results.
It's not a critical error. But how can I stop it? Thanks.
I have a macOS application with SwiftUI. I am saving a dictionary containing two custom classes with NSSavePanel. That's not a problem.
import SwiftUI
struct ContentView: View {
var body: some View {
...
}
private func savePanel() -> URL? {
let savePanel = NSSavePanel()
savePanel.allowedContentTypes = [.myCustomeFileType]
savePanel.canCreateDirectories = true
savePanel.isExtensionHidden = false
savePanel.title = "Saving..."
savePanel.message = "Please select a path where to save a file."
savePanel.nameFieldStringValue = "Untitled"
return savePanel.runModal() == .OK ? savePanel.url : nil
}
private func fileSaveAs() {
if let url = savePanel() {
let models = colorViewModel.frameModels
let borderModel = BorderModel(showBorder: true, colorIndex: 6, borderWeightIndex: 8)
let dict = ["FrameModelArray": models, "BorderModel": borderModel] as [String : Any]
NSKeyedArchiver.setClassName("FrameModel", for: FrameModel.self)
NSKeyedArchiver.setClassName("BorderModel", for: BorderModel.self)
do {
let data = try NSKeyedArchiver.archivedData(withRootObject: dict, requiringSecureCoding: false)
try data.write(to: url, options: .atomic)
} catch {
print("Errrrrr \(error.localizedDescription)")
}
}
}
}
So my custom classes are FrameModel, BorderModel.
I can unarchive a saved file with a deprecated type method as follows.
private func fileOpen() {
if let url = openPanel() {
do {
NSKeyedUnarchiver.setClass(FrameModel.self, forClassName: "FrameModel")
NSKeyedUnarchiver.setClass(BorderModel.self, forClassName: "BorderModel")
let data = try Data(contentsOf: url)
if let someData = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data) {
if let dict = someData as? [String : Any] {
if let frameModels = dict["FrameModelArray"] as? [FrameModel] {
print("[FrameModel] read...")
}
if let borderModel = dict["BorderModel"] as? BorderModel {
print("BorderModel read...")
}
}
}
} catch {
print("Errrrrr \(error.localizedDescription)")
}
}
}
If I use unarchivedObject(ofClasses:from:), I can't unarchive my file. What am I doing wrong? Thanks.
private func fileOpen() {
if let url = openPanel() {
do {
NSKeyedUnarchiver.setClass(FrameModel.self, forClassName: "FrameModel")
NSKeyedUnarchiver.setClass(BorderModel.self, forClassName: "BorderModel")
let data = try Data(contentsOf: url)
if let dictionary = try? NSKeyedUnarchiver.unarchivedObject(ofClasses: [FrameModel.self, BorderModel.self], from: data) as? NSDictionary {
print("Being read...")
} else {
print("Not read...")
}
} catch {
print("Errrrrr \(error.localizedDescription)")
}
}
}
I have gone through several tutorials for WeatherKit. But my sample app doesn't return weather data. The following is a list of what I have.
I've registered a Bundle ID for my sample app with the WeatherKit capability on.
I've created a developer profile for my sample app.
I've opened my Xcode project to make sure that the WeatherKit capability is enabled.
I have run my sample app with an actual device.
I have waited for more than 30 minutes for the service to kick in. It's been several days.
The following is my code.
import SwiftUI
import CoreLocation
import WeatherKit
struct ContentView: View {
@State var currentWeather: CurrentWeather?
var body: some View {
NavigationStack {
List {
Group {
SampleCell(title: "Temperature", value: String(currentWeather?.apparentTemperature.value ?? 0.0) + "℃")
SampleCell(title: "Cloud coverage", value: String(currentWeather?.cloudCover ?? 0.0))
SampleCell(title: "Weather condition", value: String(currentWeather?.condition.description ?? ""))
SampleCell(title: "Dew point", value: String(currentWeather?.dewPoint.value ?? 0.0) + "℃")
SampleCell(title: "Humidity", value: String(currentWeather?.humidity ?? 0.0))
SampleCell(title: "Pressure", value: String(currentWeather?.pressure.value ?? 0.0) + "mbar")
SampleCell(title: "Pressure trend", value: String(currentWeather?.pressureTrend.description ?? ""))
SampleCell(title: "Temperature", value: String(currentWeather?.temperature.value ?? 0.0) + "℃")
SampleCell(title: "UV index", value: String(currentWeather?.uvIndex.value ?? 0))
SampleCell(title: "Visibility", value: String(currentWeather?.visibility.value ?? 0.0) + "m")
}
SampleCell(title: "Window direction", value: String(currentWeather?.wind.direction.value ?? 0.0) + "°")
SampleCell(title: "Window speed", value: String(currentWeather?.wind.speed.value ?? 0.0) + "km/h")
SampleCell(title: "Gust", value: String(currentWeather?.wind.gust?.value ?? 0.0) + "km/h")
}
.navigationTitle(Text("CurrentWeather"))
.task {
let service = WeatherService()
let location = CLLocation(
latitude: 35.467081,
longitude: 139.620798
)
do {
let weather = try await service.weather(for: location)
currentWeather = weather.currentWeather
} catch let error {
print(error.localizedDescription)
}
}
}
}
}
struct SampleCell: View {
var title: String
var value: String
var body: some View {
VStack {
HStack {
Text(title)
Spacer()
Text(value)
}
}
}
}
Yet, I constantly get the following warnings.
2023-11-29 09:33:46.504737+0900 WeatherCrazyMama[15279:9734572] [WeatherDataService] Aborting silent interpolation: no interpolator object; location=CLLocationCoordinate2D(latitude: 35.467081, longitude: 139.620798)
2023-11-29 09:33:47.900605+0900 WeatherCrazyMama[15279:9734577] [AuthService] Failed to generate jwt token for: com.apple.weatherkit.authservice with error: Error Domain=WeatherDaemon.WDSJWTAuthenticatorServiceListener.Errors Code=2 "(null)"
2023-11-29 09:33:47.989603+0900 WeatherCrazyMama[15279:9734572] [WeatherService] Encountered an error when fetching weather data subset; location=<+35.46708100,+139.62079800> +/- 0.00m (speed -1.00 mps / course -1.00) @ 2023/11/29 9:33:46 AM Japan Standard Time, error=WeatherDaemon.WDSJWTAuthenticatorServiceListener.Errors 2 Error Domain=WeatherDaemon.WDSJWTAuthenticatorServiceListener.Errors Code=2 "(null)"
The operation couldn’t be completed. (WeatherDaemon.WDSJWTAuthenticatorServiceListener.Errors error 2.)
What am I doing wrong? Thanks.
I'm just playing with Combine, and I want to limit the number of letters that the text field can show. So I have the following lines of code.
import SwiftUI
struct ContentView: View {
@State var messageText: String = ""
var body: some View {
let bindingMessage = Binding {
messageText
} set: {
messageText = String($0.prefix(10))
print(String($0.prefix(10)))
}
Form {
TextField("Message", text: bindingMessage)
}
}
}
I'm expecting that the text field will show only the first 10 letters. But, as the screenshot below indicates, it shows the entire string. What am I doing wrong? Muchos Thankos. It sounds basic. Ugghhh...
I have the following lines of code where I show a bunch of checkboxes, each of which can toggle between on and off with a tap.
import SwiftUI
struct ContentView: View {
@State private var viewModel = ContentViewModel()
var body: some View {
VStack(alignment: .leading) {
List {
ForEach(viewModel.models, id: \.id) { model in
CheckButtonView(id: model.id, text: model.name, isOn: model.isOn) { id, bool in
updateDate(id: id, bool: bool)
}
}
}
}
}
func updateDate(id: String, bool: Bool) {
for i in 0..<viewModel.models.count {
let oldModel = viewModel.models[i]
if oldModel.id == id {
let newModel = Content(id: oldModel.id, name: oldModel.name, isOn: bool)
viewModel.models.remove(at: i)
viewModel.models.insert(newModel, at: i)
break
}
}
var count = 0
for i in 0..<viewModel.models.count {
let model = viewModel.models[i]
if model.isOn {
count += 1
}
}
}
}
struct CheckButtonView: View {
let id: String
let text: String
@State var isOn: Bool
var callBack: (String, Bool) -> Void
var body: some View {
HStack {
Button {
isOn.toggle()
callBack(id, isOn)
} label: {
Image(systemName: isOn ? "checkmark.square.fill" : "square")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 18)
.tint(!isOn ? .black : .blue)
}
Text(text)
.font(.subheadline)
Spacer()
}
.frame(maxWidth: .infinity)
}
}
struct Content {
let id: String
let name: String
let isOn: Bool
}
class ContentViewModel: ObservableObject {
@Published var models = [Content]()
@Published var canChange = true
init() {
models = [
Content(id: UUID().uuidString, name: "Jim", isOn: false),
Content(id: UUID().uuidString, name: "Jenny", isOn: false),
Content(id: UUID().uuidString, name: "Nancy", isOn: false),
Content(id: UUID().uuidString, name: "Natalie", isOn: false)
]
}
}
According to the picture above, I have two checkboxes that are turned on. Now, what I want to do is let the user turn on as many as two checkboxes only. Can someone think of a good way of doing that? Thanks.
I have developed several document-based (NSDocument) applications for macOS is Cocoa. Now, I'm playing with a document app project in SwiftUI. If I launch the application out of box, a file-select panel will open just as you see in TextEdit. (Please see the picture below) How do we prevent it from appearing? I would rather show a blank window, which in fact appears if I just press Command + N. Thanks.
I'm playing with a simple document-based application with TextEditor for macOS. In Cocoa, NSViewController can call updateChangeCount(_:) to clear document changes in NSDocument. I wonder SwiftUI's View has access to the same function? Hopefully, I would like to manually set the change count to zero if the user clears text in TextEditor. I bet SwiftUI doesn't have it. Thanks.
import SwiftUI
struct ContentView: View {
@Binding var document: SampleDocumentApp
var body: some View {
VStack {
TextEditor(text: $document.text)
.onChange(of: document.text) { _, _ in
guard !document.text.isEmpty else {
return
}
// clear change count //
}
}
.frame(width: 360, height: 240)
}
}
I have a sample document-based application for macOS. According to this article (https://jujodi.medium.com/adding-a-new-tab-keyboard-shortcut-to-a-swiftui-macos-application-56b5f389d2e6), you can create a new tab programmatically. It works. Now, my question is whether you can open a tab with some data. Is that possible under the SwiftUI framework? I could do it in Cocoa. Hopefully, we can do it in SwiftUI as well. Muchos thankos.
import SwiftUI
@main
struct SomeApp: App {
var body: some Scene {
DocumentGroup(newDocument: SomeDocument()) { file in
ContentView(document: file.$document)
}
}
}
import SwiftUI
struct ContentView: View {
@Binding var document: SomeDocument
var body: some View {
VStack {
TextEditor(text: $document.text)
Button {
createNewTab()
} label: {
Text("New tab")
.frame(width: 64)
}
}
}
}
extension ContentView {
private func createNewTab() {
if let currentWindow = NSApp.keyWindow,
let windowController = currentWindow.windowController {
windowController.newWindowForTab(nil)
if let newWindow = NSApp.keyWindow,
currentWindow != newWindow {
currentWindow.addTabbedWindow(newWindow, ordered: .above)
}
}
}
}
I'm working on an iOS app with a Widget. I am able to display the Widget on the iPhone 16 Pro Simulator. It doesn't appear on iPad mini 6th gen., though. Anyway, I want to make sure that it works on an actual device. If I try to add the Widget to the Home Screen, I cannot find it in the search list on iPhone XR and iPad 9th gen. If I set the target to that of the widget, Xcode gives me the following error.
SendProcessControlEvent:toPid: encountered an error: Error Domain=com.apple.dt.deviceprocesscontrolservice Code=8 "Failed to show Widget 'some bundle ID' error: …
I hope that's not a sign of trouble. So how do you debug a Widget on an Actual Device? I've read some topics like this one here. Thanks.
In reference to this webpage, I'm turning my iPad to an iBeacon device.
class BeaconViewModel: NSObject, ObservableObject, CBPeripheralManagerDelegate {
private var peripheralManager: CBPeripheralManager?
private var beaconRegion: CLBeaconRegion?
private var beaconIdentityConstraint: CLBeaconIdentityConstraint?
//private var beaconCondition: CLBeaconIdentityCondition?
override init() {
super.init()
if let uuid = UUID(uuidString: "abc") {
beaconIdentityConstraint = CLBeaconIdentityConstraint(uuid: uuid, major: 123, minor: 456)
beaconRegion = CLBeaconRegion(beaconIdentityConstraint: beaconIdentityConstraint!, identifier: "com.example.myDeviceRegion")
peripheralManager = CBPeripheralManager(delegate: self, queue: nil, options: nil)
}
}
func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
switch peripheral.state {
case .poweredOn:
startAdvertise()
case .poweredOff:
peripheralManager?.stopAdvertising()
default:
break
}
}
func startAdvertise() {
guard let beaconRegion = beaconRegion else { return }
let peripheralData = beaconRegion.peripheralData(withMeasuredPower: nil)
peripheralManager?.startAdvertising(((peripheralData as NSDictionary) as! [String: Any]))
}
func stopAdvertise() {
peripheralManager?.stopAdvertising()
}
}
In Line 10, I'm using CLBeaconidentityConstraint to constrain the beacon. Xcode says that this class is deprecated and suggests that we use CLBeaconIdentityCondition. But if I try to use it, Xcode says
Cannot find type 'CLBeaconIdentityCondition' in scope
I've just updated Xcode to 16.4. I still get the same error. So how do we use CLBeaconIdentityCondition to constrain the beacon? My macOS version is Sequoia 15.5. Thanks.
Let me suppose that I have an Xcode project that uses the following Cocoapods.
	pod 'Firebase/Auth'
	pod 'GoogleSignIn'
And let me also suppose that the minimum deployment target for my Xcode project is 11.0. In this case, do I set the Cocoapod platform to 11.0 like
platform :ios, '11.0'
target 'MyProject' do
	use_frameworks!
	pod 'Firebase/Auth'
	pod 'GoogleSignIn'
end
Or do I use the latest versions of Cocoapods like
platform :ios, '14.2'
target 'MyProject' do
	use_frameworks!
	pod 'Firebase/Auth'
	pod 'GoogleSignIn'
end
?
Thanks.
When you develop an iOS app for some company, say Company A, under whose name should you sign up a developer account so that you can code-sign the app and send it to the iTunes Connect server? Is it you or Company A? I am thinking that I can sign up a new account to submit an app as long as I give the copyright to Company A. My concern is that there was a new rule like Spamming that took effect several years ago. I guess some guys were using the same package and only changed superficial aspects to submit a ton of similar apps. Thanks.
p.s. It's not an in-house app under an enterprise account that I'm talking about. The app will be submitted to the App Store.
Hello. I'm a little bit confused about how TestFlight works. If I have an iOS app under development that has not been in the store and that has not been submitted for a review yet, can I use TestFlight to have it tested by my development team? I know that there are two types of tests, internal tests and external tests. It seems that you can use TestFlight for internal tests even if the app has not been submitted for a review. Thanks.
I just want to show a simple navigation title like the following.
import SwiftUI
struct ContentView: View {
var body: some View {
NavigationView {
ZStack {
Color.red.edgesIgnoringSafeArea(.all)
Text("Hello")
}
.navigationTitle("GGG")
.navigationBarTitleDisplayMode(.inline)
.navigationBarHidden(false)
}
}
}
And I get a bunch of mumbo jumbo auto-layout warnings (Unable to simultaneously satisfy constraints...) in Console. If I comment out the navigationTitle line, I won't get them. I have never seen those messages in showing a navigation title when writing code with UIKit. What am I doing wrong? Muchos thankos