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?
Post
Replies
Boosts
Views
Activity
Is there possible to record audio during application in kill/terminate state?
I am working with application where I have to record microphone voice for some process so I can it during application in foreground and background state, I have no idea about application kill state.
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
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.
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
}
We have QuickLook thumbnailing framework which is used to provide thumbnails for custom file types. However, how can we provide thumbnails for system defined file types for eg. image file types?
Is there any way to achieve this?
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.
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
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...
I'm trying to create an app that uses artificial intelligence technology.
One of the models provided on this website(https://developer.apple.com/machine-learning/models/) will be used.
Are there any copyright or legal issues if I create an app using the model provided by this website and distribute it to the App Store?
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.
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.
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() -> Void {
// Perform operations specific to SwiftClassA }
}
public class SwiftClassB {
public init() {}
public func FuncA() -> 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
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.
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<Substring>()
let minuteRef = Reference<Substring>()
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<Substring>()
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.
I have a virtual machine using apple's sample code on their developer page but i have no audio.
How do i create and setup an audio device for the vm?
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?
Hi, I am new to Swift and would like to write a simple Swift script to show some HDR images or video on my VisionPro. I tried to find some code online as shown in the attachment to put one HDR image and one SDR side by side, but it seems like not to take any HDR effect. Thanks in advance.
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.
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.