Discuss Swift.

Swift Documentation

Post

Replies

Boosts

Views

Activity

Archiving my macOS target app fails with BOOL error
I'm building a macOS target for my App (which also has some Obj-C code). Building and running the app is fine but when I archive the app in XCode, the process / build fails with the following error Type 'BOOL' (aka ;Int32') cannot be used as a boolean;test for '!=0' instead It happens in a couple of places, one of the places being private func getRootDirectory(createIfNotExists: Bool = true) throws -> URL { return try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true) } where it complains that create: true is not acceptable and throws the above error. If I comment out this line, the archive works successfully. When i Cmd + click the definition of Filemanager.default.url , i get this @available(macOS 10.6, *) open func url(for directory: FileManager.SearchPathDirectory, in domain: FileManager.SearchPathDomainMask, appropriateFor url: URL?, create shouldCreate: BOOL) throws -> URL This looks fishy since it it says create shouldCreate: BOOL whereas the documentation says it should be just Bool func url( for directory: FileManager.SearchPathDirectory, in domain: FileManager.SearchPathDomainMask, appropriateFor url: URL?, create shouldCreate: Bool ) throws -> URL My minimum deployment target is macOS 13.0 I'm quite stumped at this error - which happens only while archiving. Does anybody know why?
4
0
612
Jun ’24
Files App Share Context with Security scoped resource fails
I'm creating an App that can accepted PDFs from a shared context. I am using iOS, Swift, and UIKit with IOS 17.1+ The logic is: get the context see who is sending in (this is always unknown) see if I can open in place (in case I want to save later) send the URL off to open the (PDF) document and load it into PDFKit's pdfView.document I have no trouble loading PDF docs with the file picker. And everything works as expected for shares from apps like Messages, email, etc... (in which case URLContexts.first.options.openInPlace == False) The problem is with opening (sharing) a PDF that is sent from the Files App. (openInPlace == True) If the PDF is in the App's Document Folder, I need the Security scoped resource, to access the URL from the File's App so that I can copy the PDF's data to the PDFViewer.document. I get Security scoped resource access granted each time I get the File App's context URL. But, when I call fileCoordinator.coordinate and try to access a file outside of the App's document folder using the newUrl, I get an error. FYI - The newUrl (byAccessor) and context url (readingItemAt) paths are always same for the Files App URL share context. I can, however, copy the file to a new location in my apps directory and then open it from there and load in the data. But I really do not want to do that. . . . . . Questions: Am I missing something in my pList or are there other parameters specific to sharing a file from the Files App? I'd appreciate if someone shed some light on this? . . . . . Here are the parts of my code related to this with some print statements... . . . . . SceneDelegate func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) { // nothing to see here, move along guard let urlContext = URLContexts.first else { print("No URLContext found") return } // let's get the URL (it will be a PDF) let url = urlContext.url let openInPlace = urlContext.options.openInPlace let bundleID = urlContext.options.sourceApplication print("Triggered with URL: \(url)") print("Can Open In Place?: \(openInPlace)") print("For Bundle ID: \(bundleID ?? "None")") // get my Root ViewController from window if let rootViewController = self.window?.rootViewController { // currently using just the view if let targetViewController = rootViewController as? ViewController { targetViewController.prepareToLoadSharedPDFDocument(at: url) } // I might use a UINavigationController in the future else if let navigationController = rootViewController as? UINavigationController, let targetViewController = navigationController.viewControllers.first as? ViewController { targetViewController.prepareToLoadSharedPDFDocument(at: url) } } } . . . . ViewController function I broke out the if statement for accessingScope just to make it easier for me the debug and play around with the code in accessingScope == True func loadPDF(fromUrl url: URL) { // If using the File Picker / don't use this // If going through a Share.... we pass the URL and have three outcomes (1, 2a, 2b) // 1. Security scoped resource access NOT needed if from a Share Like Messages or EMail // 2. Security scoped resource access granted/needed from 'Files' App // a. success if in the App's doc directory // b. fail if NOT in the App's doc directory // Set the securty scope variable var accessingScope = false // Log the URLs for debugging print("URL String: \(url.absoluteString)") print("URL Path: \(url.path())") // Check if the URL requires security scoped resource access if url.startAccessingSecurityScopedResource() { accessingScope = true print("Security scoped resource access granted.") } else { print("Security scoped resource access denied or not needed.") } // Stop accessing the scope once everything is compeleted defer { if accessingScope { url.stopAccessingSecurityScopedResource() print("Security scoped resource access stopped.") } } // Make sure the file is still there (it should be in this case) guard FileManager.default.fileExists(atPath: url.path) else { print("File does not exist at URL: \(url)") return } // Let's see if we can open it in place if accessingScope { let fileCoordinator = NSFileCoordinator() var error: NSError? fileCoordinator.coordinate(readingItemAt: url, options: [], error: &error) { (newUrl) in DispatchQueue.main.async { print(url.path()) print(newUrl.path()) if let document = PDFDocument(url: newUrl) { self.pdfView.document = document self.documentFileName = newUrl.deletingPathExtension().lastPathComponent self.fileLoadLocation = newUrl.path() self.updateGUI(pdfLoaded: true) self.setPDFScale(to: self.VM.pdfPageScale, asNewPDF: true) } else { print("Could not load PDF directly from url: \(newUrl)") } } } if let error = error { PRINT("File coordination error: \(error)") } } else { DispatchQueue.main.async { if let document = PDFDocument(url: url) { self.pdfView.document = document self.documentFileName = url.deletingPathExtension().lastPathComponent self.fileLoadLocation = url.path() self.updateGUI(pdfLoaded: true) self.setPDFScale(to: self.VM.pdfPageScale, asNewPDF: true) } else { PRINT("Could not load PDF from url: \(url)") } } } } . . . . Other relevant pList settings I've added are: Supports opening documents in place - YES Document types - PDFs (com.adobe.pdf) UIDocumentBrowserRecentDocumentContentTypes - com.adobe.pdf Application supports iTunes file sharing - YES And iCloud is one for Entitlements with iCloud Container Identifiers Ubiquity Container Identifiers . . . . Thank you in advance!. B
1
0
495
Jun ’24
Function called isolated on MainActor via an isolated parameter are not considered run on the MainActor
If I try to compile the following, I get a compilation error: import Foundation func isolatedPrint<A : Actor>(on actor: isolated A) { print("hello") } Task{ @MainActor in isolatedPrint(on: MainActor.shared) } The error: toto.swift:9:2: error: expression is 'async' but is not marked with 'await' isolatedPrint(on: MainActor.shared) ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ await toto.swift:9:2: note: calls to global function 'isolatedPrint(on:)' from outside of its actor context are implicitly asynchronous isolatedPrint(on: MainActor.shared) ^ I don’t understand why the compiler does not detect the function is called on the MainActor via the actor parameter.
1
0
427
May ’24
Ensuring exclusive access to a function in structured concurrency
So our back end manages tokens in a strange way. Whenever we try to request a new access token using our refresh token, it invalidates our old refresh token and returns us with a new access + refresh token. The problem with this is that multiple concurrent network requests can see that a user's access token has expired and try to get a new access token, potentially causing us to get a 401 unauthorized error. Is there any way with structured/unstructured concurrency to ensure that our method for grabbing the access token can only at max be run once at a time? Im assuming the only realistic way would be to do something like this: @MyGlobalActor private var tokenTask: Task<String, any Error>? @MyGlobalActor func getAccessToken() async await -> String { if let tokenTask { return try await tokenTask.value } self.tokenTask = Task<String, any Error> { // refresh access token } let token = try await self.tokenTask!.value self.tokenTask = nil return token }
1
0
385
May ’24
"Unexpectedly found nil while unwrapping an Optional value" in URL
Before anyone rants and raves about checking documentation - I have spent the last 4 hours trying to solve this issue on my own before asking for help. Coding in Swift is VERY new for me and I'm banging my head against the wall trying to teach myself. I am very humbly asking for help. If you refer me to documentation, that's fine but I need examples or it's going to go right over my head. Teaching myself is hard, please don't make it more difficult. I have ONE swift file with everything in it. import Foundation import Cocoa import Observation class GlobalString: ObservableObject { @Published var apiKey = "" @Published var link = "" } struct ContentView: View { @EnvironmentObject var globalString: GlobalString var body: some View { Form { Section(header: Text("WallTaker for macOS").font(.title)) { TextField( "Link ID:", text: $globalString.link ) .disableAutocorrection(true) TextField( "API Key:", text: $globalString.apiKey ) .disableAutocorrection(true) Button("Take My Wallpaper!") { } } .padding() } .task { await Wallpaper().fetchLink() } } } @main struct WallTaker_for_macOSApp: App { @AppStorage("showMenuBarExtra") private var showMenuBarExtra = true @EnvironmentObject var globalString: GlobalString var body: some Scene { WindowGroup { ContentView() .environmentObject(GlobalString()) } // MenuBarExtra("WallTaker for macOS", systemImage: "WarrenHead.png", isInserted: $showMenuBarExtra) { // Button("Refresh") { //// currentNumber = "1" // } // Button("Love It!") { //// currentNumber = "2" // } // Button("Hate It!") { //// currentNumber = "3" // } // Button("EXPLOSION!") { // // currentNumber = "3" // } //// // } } } class Wallpaper { var url: URL? = nil var lastPostUrl: URL? = nil let mainMonitor: NSScreen init() { mainMonitor = NSScreen.main! } struct LinkResponse: Codable { var post_url: String? var set_by: String? var updated_at: String } struct Link { var postUrl: URL? var setBy: String var updatedAt: Date } func parseIsoDate(timestamp: String) -> Date? { let formatter = DateFormatter() formatter.locale = Locale(identifier: "en_US_POSIX") formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ" return formatter.date(from: timestamp) } func fetchLink() async { do { url = URL(string: GlobalString().link) let (data, _) = try await URLSession.shared.data(from: url!) let decoder = JSONDecoder() let linkResponse = try decoder.decode(LinkResponse.self, from: data) let postUrl: URL? = linkResponse.post_url != nil ? URL(string: linkResponse.post_url!) : nil let date = parseIsoDate(timestamp: linkResponse.updated_at) let link = Link( postUrl: postUrl, setBy: linkResponse.set_by ?? "anon", updatedAt: date ?? Date() ) try update(link: link) } catch { } } func update(link: Link) throws { guard let newPostUrl = link.postUrl else { return } if (newPostUrl != lastPostUrl) { lastPostUrl = newPostUrl let tempFilePath = try getTempFilePath() try downloadImageTo(sourceURL: newPostUrl, destinationURL: tempFilePath) try applyWallpaper(url: tempFilePath) } else { } } private func applyWallpaper(url: URL) throws { try NSWorkspace.shared.setDesktopImageURL(url, for: mainMonitor, options: [:]) } private func getTempFilePath() throws -> URL { let directory = NSTemporaryDirectory() let fileName = NSUUID().uuidString let fullURL = NSURL.fileURL(withPathComponents: [directory, fileName])! return fullURL } private func downloadImageTo(sourceURL: URL, destinationURL: URL) throws { let data = try Data(contentsOf: sourceURL) try data.write(to: destinationURL) } } The 'fetchLink' function is where things explode, specifically when setting the URL. I do not know what I'm doing wrong.
5
0
801
May ’24
Swift: Declaration name is not covered by macro
Hello! I'm trying to generate a protocol dependent for another one using Swift macros. The implementation looks like the following: @attached (peer, names: suffixed (Dependent),prefixed (svc)) public macro dependableService() = #externalMacro (module: "Macros", type: "DependableServiceMacro") public struct DependableServiceMacro: PeerMacro { public static func expansion (of node: AttributeSyntax, providingPeersOf declaration: some DeclSyntaxProtocol, in context: some MacroExpansionContext) throws -> [DeclSyntax] { guard let baseProto = declaration.as (ExtensionDeclSyntax.self) else { return [] } let nm = baseProto.extendedType.trimmedDescription let protoNm = nm + "Dependent" let varNm = "svc" + nm let protoDecl: DeclSyntax = """ protocol \(raw: protoNm) : ServiceDependent { var \(raw: varNm) : \(raw: nm) { get set } } """ return [protoDecl] } } When I try using it in my code like this @dependableService extension MyService {} the macro correctly expands to the following text: protocol MyServiceDependent : ServiceDependent { var svcMyService : MyService { get set } } However, the compiler gives me the error: error: declaration name 'MyServiceDependent' is not covered by macro 'dependableService' protocol MyServiceDependent : ServiceDependent { ^ Do I understand correctly, that for some reason the compiler cannot deduce the name of the generated protocol based on the name of the extensible protocol, despite the presence of the names: suffixed(Dependent) attribute in the macro declaration? Could anybody please tell me what I'm doing wrong here? Thanks in advance
1
0
645
May ’24
SwiftData does not retrieve my inverse one-to-many Relationship
Here is my models: import SwiftData @Model final public class FirstModel { let name: String @Relationship(deleteRule: .cascade, inverse: \SecondModel.parent) var children = [SecondModel]() init(name: String) { self.name = name } } @Model final public class SecondModel { let parent: FirstModel let name: String @Relationship(deleteRule: .cascade, inverse: \ThirdModel.parent) var children = [ThirdModel]() init(name: String, parent: FirstModel) { self.name = name self.parent = parent } } @Model final public class ThirdModel { let parent: SecondModel let name: String init(name: String, parent: SecondModel) { self.name = name self.parent = parent } } Then I create my model entries: let schema = Schema([ FirstModel.self, SecondModel.self, ThirdModel.self ]) let container = try ModelContainer(for: schema) let context = ModelContext(container) let firstModel = FirstModel(name: "my first model") let secondModel = SecondModel(name: "my second model", parent: firstModel) let thirdModel = ThirdModel(name: "my third model", parent: secondModel) context.insert(firstModel) context.insert(secondModel) context.insert(thirdModel) try context.save() I want to retrieve the children from my models: print("-- Fetch Third Model") let thirdFetchDescriptor: FetchDescriptor<ThirdModel> = FetchDescriptor<ThirdModel>(predicate: #Predicate { $0.name == "my third model" }) let thirdModels = try context.fetch(thirdFetchDescriptor) for entry in thirdModels { print(">>> \(entry) - \(entry.parent) - \(entry.parent.parent)") } print("-- Fetch First Model") let firstFetchDescriptor: FetchDescriptor<FirstModel> = FetchDescriptor<FirstModel>(predicate: #Predicate { $0.name == "my first model" }) let firstModels = try context.fetch(firstFetchDescriptor) for entry in firstModels { print(">>> \(entry) - \(entry.children)") for child in entry.children { print("\t>>> \(child) - \(child.children)") } } ... But it does not seem to work: -- Fetch Third Model >>> cardapart_sdk_app_ui.ThirdModel - cardapart_sdk_app_ui.SecondModel - cardapart_sdk_app_ui.FirstModel -- Fetch First Model >>> cardapart_sdk_app_ui.FirstModel - [] What I would expect to see: -- Fetch First Model >>> cardapart_sdk_app_ui.FirstModel - [cardapart_sdk_app_ui.SecondModel] >>> cardapart_sdk_app_ui.SecondModel - [cardapart_sdk_app_ui.ThirdModel] I am not sure what I am doing wrong or missing...
1
0
644
May ’24
Game Center fetchSavedGames sometimes returns empty list of games, although it works correctly on the next tries
I have implemented the Game Center for authentication and saving player's game data. Both authentication and saving player's data works correctly all the time, but there is a problem with fetching and loading the data. The game works like this: At the startup, I start the authentication After the player successfully logs in, I start loading the player's data by calling fetchSavedGames method If a game data exists for the player, I receive a list of SavedGame object containing the player's data The problem is that after I uninstall the game and install it again, sometimes the SavedGame list is empty(step 3). But if I don't uninstall the game and reopen the game, this process works fine. Here's the complete code of Game Center implementation: class GameCenterHandler { public func signIn() { GKLocalPlayer.local.authenticateHandler = { viewController, error in if let viewController = viewController { viewController.present(viewController, animated: false) return } if error != nil { // Player could not be authenticated. // Disable Game Center in the game. return } // Auth successfull self.load(filename: "TestFileName") } } public func save(filename: String, data: String) { if GKLocalPlayer.local.isAuthenticated { GKLocalPlayer.local.saveGameData(Data(data.utf8), withName: filename) { savedGame, error in if savedGame != nil { // Data saved successfully } if error != nil { // Error in saving game data! } } } else { // Error in saving game data! User is not authenticated" } } public func load(filename: String) { if GKLocalPlayer.local.isAuthenticated { GKLocalPlayer.local.fetchSavedGames { games, error in if let game = games?.first(where: {$0.name == filename}){ game.loadData { data, error in if data != nil { // Data loaded successfully } if error != nil { // Error in loading game data! } } } else { // Error in loading game data! Filename not found } } } else { // Error in loading game data! User is not authenticated } } } I have also added Game Center and iCloud capabilities in xcode. Also in the iCloud section, I selected the iCloud Documents and added a container. I found a simillar question here but it doesn't make things clearer.
0
0
415
May ’24
Weird Swift overriding cocoapods
I don't even use Swift. I use Flutter. I am getting this odd always_embed_swift library warning that seems to be overriding my runner target on xcode. I'll just attach the image down below of what I'm dealing with. Please an apple engineer or someone just help me because this has been a struggle lol. I need to change this but can't find the setting to do so.
0
0
349
May ’24
Storing Different Types of Swift Objects in C++ Using New Interop
Hello Everyone, I'm working on an app that utilizes the new C++ - Swift interop feature. I have a module called ModuleA that contains multiple Swift classes, and I need to store instances of these classes in a C++ class as a class member(to ensure ARC until the class object is deallocated). However, I want to retain the Swift class objects on the stack without directly allocating heap memory from C++. Sample Swift Code: public class SwiftClassA { public init() {} public func FuncA() -&gt; Void { // Perform operations specific to SwiftClassA } } public class SwiftClassB { public init() {} public func FuncA() -&gt; Void { // Perform operations specific to SwiftClassB } } // Additional Swift classes (SwiftClassC to SwiftClassN) follow a similar structure. Sample Cpp Code: CppClass.hpp #include "ModuleA-Swift.h" // Include generated Swift headerclass CppClass { public: // Functions and declarationsprivate: XYZ vClassObject; // Placeholder for Any Swift class object }; CppClass.cpp #include "ModuleA-Swift.h" // Include generated Swift headervoid CppClass::SomeFuncA() noexcept { ModuleA::SwiftClassA obj = ModuleA::SwiftClassA::init(); // Initialize SwiftClassA object vClassObject = obj; // Assign SwiftClassA object to vClassObject } void CppClass::SomeFuncB() noexcept { ModuleA::SwiftClassB obj = ModuleA::SwiftClassB::init(); // Initialize SwiftClassB object vClassObject = obj; // How do I Assign SwiftClassB object to vClassObject? } I'm looking for suggestions on how to efficiently store different types of Swift class objects in my C++ class while maintaining stack-based object retention and proper memory management. Any help or insights would be greatly appreciated. Thanks, Harshal
4
0
722
May ’24
How to use .a in swift with an empty header
I'm making a Swift Program. I got a .a file that builded from some c++ scripts,and I can see some fuctions in it by commed "nm *.a", and a .h file like this My question is how to call the fuctions in .a like "testDebug",I can call from c# like [DllImport("__Internal")] private static extern void testDebug(); Google's answer always with a right .h file,Maybe I should make .h file correct first. Any reply would be greatly appreciated.
2
0
394
May ’24
Regex Builder error message???
I'm debugging some Regex Builder code in my Playground. I run the following piece code: let timeMatchWithout = possibleTime.firstMatch(of: timeWithoutSec) and I get this error message: Regex.Match optional storedCapture contains no some What could this possibly mean? contains no some??? Here is a more complete snippet, if this helps: let hourRef = Reference&lt;Substring&gt;() let minuteRef = Reference&lt;Substring&gt;() let hourReg = Regex { ChoiceOf { Capture(as: hourRef) { One(.digit) One(.digit) } Capture(as: hourRef) { One(.digit) } } } let minuteReg = Regex { ChoiceOf { Capture(as: minuteRef) { One(.digit) One(.digit) } Capture(as: minuteRef) { One(.digit) } } } let ampmRef = Reference&lt;Substring&gt;() let ampmReg = Regex { Capture(as: ampmRef) { ZeroOrMore { ChoiceOf { One("am") One("pm") One("a.m.") One("p.m.") } } } /* transform: { $0.lowercase } */ }.ignoresCase() let timeWithoutSec = Regex { hourReg One(":") minuteReg ZeroOrMore(.whitespace) ampmReg }.ignoresCase() let possibleTime = "10:20 AM" let timeMatchWithout = possibleTime.firstMatch(of: timeWithoutSec) The last line produces the error message. Thanks for the help. Note the removed transform: on the ampmReg definition. If that is included the compiler times out as noted in my previous post, yesterday.
2
0
539
May ’24
Swift Regex Builder issue
Why does this Regex Builder code in my SwiftUI app not work? I'm parsing a string that might be a date and time with either AM or PM specified for the time. This bit of code looks for the optional AM or PM. The error I get is: The compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions What would 'distinct sub-expressions' mean in this case? The code: let ampmRef = Reference<Substring>() let ampmReg = Regex { Capture(as: ampmRef) { ZeroOrMore { ChoiceOf { One("am") One("pm") } } } transform: { $0.lowercase } }.ignoresCase() In a related question, is there a way to return a default if the ChoiceOf fails both AM and PM?
3
0
613
May ’24
IBOutlet becomes nil after ViewController is initialized
I have an extremely straightforward situation where an @IBOutlet in a ViewController is connected to a property in an XIB file. I've been working with iOS apps for more than ten years, and done this about a million times. For some reason, the property becomes nil at some point after the view is loaded. I can check with the debugger to see that it is not nil at viewDidLoad, and there is nothing in my code that sets it to anything else. I added a custom setter and getter to the variable so that I could stop in the debugger when it gets set, and the setter only gets called once, with a non-nil value. I suspect that somehow, a different copy of my ViewController is getting instantiated, but when it does, there are no calls to any of the usual methods like viewDidLoad. In fact there is not even a call to the init method. I don't understand how this is possible.
1
1
507
May ’24
Alternative to CoreTelephony for Accessing Cellular Network Information in Private iOS App
Hello, I am developing a private internal Flutter app for our customer, which will not be published on the Apple Store. One of the key features of this app is to collect RF strength metrics to share user experience with the network. For Android, we successfully implemented the required functionality and are able to collect the following metrics: Signal strength level (0-4) Signal strength in dBm RSSI RSRQ Cell ID Location Area Code Carrier name Mobile country code Mobile network code Radio access technology Connection status Duplex mode However, for iOS, we are facing challenges with CoreTelephony, which is not returning the necessary data. We are aware that CoreTelephony is deprecated and are looking for alternatives. We noticed that a lot of the information we need is available via FTMInternal-4. Is there a way to access this data for a private app? Are there any other recommended approaches or frameworks that can be used to gather cellular network information on iOS for an app that won't be distributed via the Apple Store? my swift code import Foundation import CoreTelephony class RfSignalStrengthImpl: RfSignalStrengthApi { func getCellularSignalStrength(completion: @escaping (Result<CellularSignalStrength, Error>) -> Void) { let networkInfo = CTTelephonyNetworkInfo() guard let carrier = networkInfo.serviceSubscriberCellularProviders?.values.first else { completion(.failure(NSError(domain: "com.xxxx.yyyy", code: 0, userInfo: [NSLocalizedDescriptionKey: "Carrier not found"]))) return } let carrierName = carrier.carrierName ?? "Unknown" let mobileCountryCode = carrier.mobileCountryCode ?? "Unknown" let mobileNetworkCode = carrier.mobileNetworkCode ?? "Unknown" let radioAccessTechnology = networkInfo.serviceCurrentRadioAccessTechnology?.values.first ?? "Unknown" var connectionStatus = "Unknown" ... ... } Thank you for your assistance.
4
0
998
May ’24