Thanks for your help. I will test it tomorrow and report back.
Post
Replies
Boosts
Views
Activity
Now I was able to build a simplified example which shows the error.
I have two days and a click on the button does send it to the other day and back. It does sometimes crash on the first call but on another run on the 3rd call.
I post the code below. Perhaps it gives a clue what's wrong:
import SwiftUI
enum Weekdays : String, CaseIterable {
case Montag
case Dienstag
case Mittwoch
case Donnerstag
case Freitag
case Samstag
//case Sonntag
}
class Vorlesung : Hashable, Equatable, Identifiable, ObservableObject {
@Published var subject : String
@Published var day : Weekdays
let vID = UUID()
init(subject: String, day : Weekdays) {
self.subject = subject
self.day = day
}
static func == (lhs: Vorlesung, rhs: Vorlesung) -> Bool {
let result = lhs.subject.compare(rhs.subject) == .orderedSame
return result
}
func hash(into hasher: inout Hasher) {
hasher.combine(vID) // UUID
}
}
public class VorlesungsHandler : ObservableObject {
let dayList : [Weekdays] = [.Montag, .Dienstag]//, .Mittwoch, .Donnerstag, .Freitag]
@Published var vorlesungen : [Vorlesung] = [
Vorlesung(subject: "banana", day: .Montag),
Vorlesung(subject: "strawberry", day: .Montag),
Vorlesung(subject: "apple", day: .Montag),
Vorlesung(subject: "pear", day: .Montag)
]
func updateVorlesung(oldID : UUID?, newV : Vorlesung) {
self.vorlesungen.removeAll { value in
value.vID == oldID
}
self.vorlesungen.append(newV)
}
}
struct PlanEntryView: View {
@EnvironmentObject var appData : VorlesungsHandler
@ObservedObject var setup : Vorlesung
@State private var showDataView : Bool = false
var body: some View {
ZStack {
Button(setup.subject) {
let switchedDay : Weekdays = setup.day == .Montag ? .Dienstag : .Montag
appData.updateVorlesung(oldID: setup.vID, newV: Vorlesung(subject: setup.subject, day: switchedDay))
}
}
}
}
struct RoomView: View {
@EnvironmentObject var appData : VorlesungsHandler
var day : Weekdays
var body: some View {
VStack() {
VStack {
ForEach(appData.vorlesungen, id: \.self) { value in
if (value.day == day) {
PlanEntryView(setup: value)
.environmentObject(appData)
}
}
}
}
}
}
struct DayView: View {
@EnvironmentObject var appData : VorlesungsHandler
var day : Weekdays
var body: some View {
VStack {
Text(day.rawValue)
HStack {
RoomView(day: day)
.environmentObject(appData)
}
Spacer()
}
}
}
struct ContentView: View {
@EnvironmentObject var appData : VorlesungsHandler
var body: some View {
VStack {
ForEach(appData.dayList, id: \.self) { value in
DayView(day: value)
.environmentObject(appData)
}
}
}
}
struct ContentView_Previews: PreviewProvider {
@StateObject static var previewData = VorlesungsHandler()
static var previews: some View {
ContentView()
.environmentObject(previewData)
}
}
@main
struct crasherApp: App {
@StateObject private var appData = VorlesungsHandler()
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(appData)
}
}
}
Tested right now. No difference.
The error message is
2023-03-16 08:06:52.903332+0100 ITR-Stundenplan[91211:778159] Fatal error: Duplicate keys of type 'Vorlesung' were found in a Dictionary. This usually means either that the type violates Hashable's requirements, or that members of such a dictionary were mutated after insertion.
I wonder if there is perhaps a timing issue, where the data is accessed during the change although I use objectWillChange:
self.objectWillChange.send()
self.vorlesungen = newList
Really strange…
Where do you call updateVorlesung ?
I show a separate data-entry Window and I call it in a Button("Ok").action.
The Class Vorlesung is Hashable:
func hash(into hasher: inout Hasher) {
hasher.combine(vID) // UUID
}
The debug output of the class properties and the Hash does not show a duplicate hash value. It is also very unlikely that there is a duplicate hash because of the used UUID…
Any other ideas how to solve this?
That makes no difference. Using following code instead of the loop gives the same error:
self.vorlesungen.removeAll { value in
value.vID == oldID
}
I did another test using a small sample based on https://stackoverflow.com/questions/18265760/get-exif-data-in-mac-os-development.
I wrote a simple console App with following code:
#import <Foundation/Foundation.h>
#import <ImageIO/ImageIO.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *imageFileURL = [NSURL fileURLWithPath: [@"~/Desktop/IMG_1845.HEIC" stringByStandardizingPath]];
CGImageSourceRef imageSource = CGImageSourceCreateWithURL((CFURLRef)imageFileURL, NULL);
NSDictionary *treeDict;
NSMutableString *exifData;
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:NO],
(NSString *)kCGImageSourceShouldCache, nil];
CFDictionaryRef imageProperties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, ( CFDictionaryRef)options);
CFRelease(imageSource);
if (imageProperties) {
treeDict = [NSDictionary dictionaryWithDictionary:(__bridge NSDictionary*)(imageProperties)];
id exifTree = [treeDict objectForKey:@"{Exif}"];
exifData = [NSMutableString stringWithString:@""];
for (NSString *key in [[exifTree allKeys] sortedArrayUsingSelector:@selector(compare:)])
{
NSString* locKey = [[NSBundle bundleWithIdentifier:@"com.apple.ImageIO.framework"] localizedStringForKey:key value:key table: @"CGImageSource"];
id value = [exifTree valueForKey:key];
[exifData appendFormat:@"key =%@ ; Value = %@ \n", locKey,value];
}
NSLog(@" exifData %@", exifData);
}
return 0;
}
}
On macOS 14.6 I get following output:
$ ./exifTest
2023-01-25 09:44:32.532 exifTest[2409:21024] exifData key =Aperture Value ; Value = 1.169925002106682
key =Brightness Value ; Value = 4.710561089652368
key =Color Space ; Value = 65535
key =Date Time Digitized ; Value = 2022:10:27 16:31:42
key =Date Time Original ; Value = 2022:10:27 16:31:42
key =Digital Zoom Ratio ; Value = 1.2096
key =Exif Version ; Value = (
2,
3,
2
)
key =Exposure Bias Value ; Value = 0
key =Exposure Mode ; Value = 0
key =Exposure Program ; Value = 2
key =Exposure Time ; Value = 0.00684931506849315
key =FNumber ; Value = 1.5
key =Flash ; Value = 16
key =Focal Length In 35mm Film ; Value = 31
key =Focal Length ; Value = 5.7
key =ISO Speed Ratings ; Value = (
64
)
key =Lens Make ; Value = Apple
key =Lens Model ; Value = iPhone 14 back dual wide camera 5.7mm f/1.5
key =Lens Specification ; Value = (
"1.54",
"5.7",
"1.5",
"2.4"
)
key =Metering Mode ; Value = 5
key =Pixel X Dimension ; Value = 4032
key =Pixel Y Dimension ; Value = 3024
key =Scene Type ; Value = 1
key =Sensing Method ; Value = 2
key =Shutter Speed Value ; Value = 7.185264202431158
key =Subject Area ; Value = (
2016,
1508,
2319,
1327
)
key =Sub-second Time Digitized ; Value = 305
key =Sub-second Time Original ; Value = 305
key =White Balance ; Value = 0
on macOS 13.2 I get
$ ./exifTest
2023-01-25 09:37:19.219 exifTest[21828:415974] exifData key =(null) ; Value = 1.169925002106682
key =(null) ; Value = 4.710561089652368
key =(null) ; Value = 65535
key =(null) ; Value = 2
key =(null) ; Value = 2022:10:27 16:31:42
key =(null) ; Value = 2022:10:27 16:31:42
key =(null) ; Value = 1.2096
key =(null) ; Value = (
2,
3,
2
)
key =(null) ; Value = 0
key =(null) ; Value = 0
key =(null) ; Value = 2
key =(null) ; Value = 0.00684931506849315
key =(null) ; Value = 1.5
key =(null) ; Value = 16
key =(null) ; Value = 31
key =(null) ; Value = 5.7
key =(null) ; Value = (
64
)
key =(null) ; Value = Apple
key =(null) ; Value = iPhone 14 back dual wide camera 5.7mm f/1.5
key =(null) ; Value = (
"1.54",
"5.7",
"1.5",
"2.4"
)
key =(null) ; Value = 5
key =(null) ; Value = +02:00
key =(null) ; Value = +02:00
key =(null) ; Value = +02:00
key =(null) ; Value = 4032
key =(null) ; Value = 3024
key =(null) ; Value = 1
key =(null) ; Value = 2
key =(null) ; Value = 7.185264202431158
key =(null) ; Value = (
2016,
1508,
2319,
1327
)
key =(null) ; Value = 305
key =(null) ; Value = 305
key =(null) ; Value = 0
So it seems that the EXIF keys are no longer provided from the OS!
I build Universal Binary and so it should run on M1 and Intel based Macs.
Now I made another test:
New Xib-based Swift project (macOS, App).
Set the build target to macOS 10.14.
Build without any changes.
Copy to a Mac running Mojave.
Result: the same error message.
It seems so that the support of older macOS versions is broken in current Xcode.
It is a Xib based project and so it should run on Mojave.
Now I tried to set the target OS to macOS 10.13. It does still now work.
The error message is now
You can’t use this version of the application “APPNAME” with this version of macOS.
You have macOS 10.14.6. The application requires macOS 10.13 or later.
In "Project" and "Targets" is the target 10.14. Therefore the error message shows that OS version.
Now I got it working. I fixed the "-o" option by removing the space and removed all additional quoting.
Many thanks for your help (again).
Thanks for your explanation. My assumption was obviously wrong.
In fact the command
mount_smbfs -onodev,nosuid "//DOMAIN;USER:PASS@SERVER_ADDRESS/REMOTEPATH" /SOMEPATH
works well in shell. Note: The password needs a HTML like % encoding for funny chars, e.g. "my%23pass" for "my#pass".
I use a similar call already with sshfs on a Linux server. Now I will perform some more debugging to get a clue what's wrong. I will post a reply with my discoveries.
Oops. The code has to be Hex encoded. It does also not work:
$ mount_smbfs -N -o nodev,nosuid "//DOMAIN%3BUSER:PASS@SERVER_ADDRESS/REMOTEPATH" /LOCALPATH
mount_smbfs: server rejected the connection: Authentication error
No. I tried backslash quoting and quotes.
Unfortunately it does not work using percent encoding. In Terminal I get this error:
$ mount_smbfs -N -o nodev,nosuid "//DOMAIN%59USER:PASS@SERVER_ADDRESS/REMOTEPATH" /LOCALPATH
mount_smbfs: server rejected the connection: Authentication error
Also it does not work in my application.
Now I got it working. I use a check at start of my application with following code:
if !NetworkCheck().waitForNetwork() {
print("Error: No network available!")
exit(exitCodes.NoNetwork.rawValue)
}
and this is my NetworkCheck class:
import Foundation
import Network
class NetworkCheck {
private let networkMonitor : NWPathMonitor
init() {
self.networkMonitor = NWPathMonitor(requiredInterfaceType: .wiredEthernet)
self.networkMonitor.start(queue: .global())
}
func waitForNetwork(networkTimeout : Double = 30.0) -> Bool {
let networkLookupStart = Date.now
var isConected = false
while abs(networkLookupStart.timeIntervalSinceNow) <= networkTimeout {
networkMonitor.pathUpdateHandler = { path in
if path.status == .satisfied {
isConected = true
}
}
if isConected {
break
}
sleep(1)
}
return isConected
}
deinit {
networkMonitor.cancel()
}
}