Hiya 👋! While loading some data, I'm having issues decoding arrays of basic types, specifically Int and Bool – they return nil. My app has existing data (live on the App Store for years) that is saved and loaded using NSKeyedArchiver. I'm updating to support a newer iOS version, which requires me now to adhere to NSSecureCoding. As I understand, NSSecureCoding needs strict type definitions, and it will return nil if things are ambiguous (for security reasons).
Essentially as I load data, it all works when I use strict types, like Int and Bool, because the methods themselves are strict: decodeInteger(forKey:) and decodeBool(forKey:). However, if I want to decode something more complex, like NSDate or basic type arrays (in my case [Int], [[[Int]]], [Bool] and [[Bool]]), I assume I have to decode an object: decodeObject(of:forKey:). While I was able to make NSDate work by forcing the type (decodeObject(of: NSDate.self, forKey: "modifyDate")! as Date), getting arrays to decode is proving difficult. They always return nil.
I've now tried forcing the type to different arrays, including NSArray, and listing array types. I also tried decodeArrayOfObjects(ofClass:forKey:), but no luck.
Example:
Here are some data items I might have:
var id: Int?
var isModified: Bool?
var modifyDate: Date?
var myIntegers: [Int]?
var myEmbedIntegers: [[[Int]]]?
var myBooleans: [Bool]?
var myEmbedBooleans: [[Bool]]?
Here's how I encode them:
encode(id!, forKey: "id")
encode(isModified!, forKey: "isModified")
encode(modifyDate!, forKey: "modifyDate")
encode(myIntegers!, forKey: "myIntegers")
encode(myEmbedIntegers!, forKey: "myEmbedIntegers")
encode(myBooleans!, forKey: "myBooleans")
encode(myEmbedBooleans!, forKey: "myEmbedBooleans")
This is how Int, Bool and Date are apparently successfully decoded (where Date is forced to search for NSDate type):
decodeInteger(forKey: "id")
decodeBool(forKey: "isModified")
decodeObject(of: NSDate.self, forKey: "modifyDate")! as Date
Here are attempts with Int (same with Bool) arrays, which are erroneously decoded (these all either get compiler errors or return nil):
decodeObject(forKey: "myIntegers") as! [Int] // This used to work before NSSecureCoding, but now returns nil.
decodeObject(of: [NSArray.self], forKey: "myIntegers") as! [Int] // Returns nil.
decodeObject(of: [Int.self], forKey: "myIntegers") // Compiler error about value type conversion.
decodeArrayOfObjects(ofClass: Int.self, forKey: "myIntegers") // Compiler error complaining that Int doesn't conform to NSSecureCoding.
decodeArrayOfObjects(ofClass: NSArray.self, forKey: "myIntegers") as! [Int] // Returns nil.
The funny thing is I don't even remotely need security. My data is for song compositions in an entertainment app, so it's strictly loaded and saved to device by my own code without networking, hashing or anything else being involved. Nevertheless I'm now stuck on this 😥.
How do I decode arrays (without returning nil)?
General
RSS for tagDelve into the world of built-in app and system services available to developers. Discuss leveraging these services to enhance your app's functionality and user experience.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Created
I am developing an application that utilizes Family Controls to restrict the use of certain apps. Currently, I am using the following extensions: DeviceActivityMonitor, ShieldConfiguration, and ShieldAction.
Issue Overview: While blocking a single application functions correctly, a problem arises when implementing multiple functionalities that use these extensions for the same application.
STEPS TO REPRODUCE
Functionality 1: Maximum Time in App
Description: Blocks the app after 15 minutes of continuous use.
Functionality 2: Conscious Opening
Description: Upon opening the app, it is blocked for 10 seconds and then automatically unlocked.
Steps to Reproduce the Bug:
Open the Application:
The app opens normally.
Trigger Functionality 2
The app is blocked and displays the blocking screen corresponding to Functionality 2: Conscious Opening.
Continue Using the App
After 10 seconds, the app unlocks, and I continue using it.
Important: If the app is closed at this point, the bug does not occur.
Trigger Functionality 1 After 15 Minutes
After 15 minutes of continuous use, the app should block according to Functionality 1: Maximum Time in App.
Expected Behavior: The blocking screen for Functionality 1 is displayed.
Actual Behavior: The blocking screen for Functionality 2 is displayed instead.
Technical Observations:
By adding logs in ShieldConfiguration, I observed that the configuration does not refresh correctly when the app is blocked a second time while still in use.
If the app is closed and reopened, the correct blocking screen for Functionality 1 is displayed as expected.
When I attempt to distribute my app in Xcode, I get the following error:
Can I resolve the above error by applying for permissions?
I learned from this thread that the above application was not approved by email. How can I know whether the application was approved?
In addition, from this thread, the review process may take several weeks or even 5 months. Considering that public holiday is coming, how can I speed up this process? ( I have submitted my application)
Thank you
I have a very basic App Intent extension in my macOS app that does nothing than accepting two parameters, but running it in Shortcuts always produces the error "The action “Compare” could not run because an internal error occurred.".
What am I doing wrong?
struct CompareIntent: AppIntent {
static let title = LocalizedStringResource("intent.compare.title")
static let description = IntentDescription("intent.compare.description")
static let openAppWhenRun = true
@Parameter(title: "intent.compare.parameter.original")
var original: String
@Parameter(title: "intent.compare.parameter.modified")
var modified: String
func perform() async throws -> some IntentResult {
return .result()
}
}
I have widgets providing their timeline using the .atEnd reload policy, i.e.:
// AppIntentTimelineProvider:
return Timeline(entries: entries, policy: .atEnd)
// TimelineProvider
let timeline = Timeline(entries: entries, policy: .atEnd)
completion(timeline)
I can't seem to find any information on what happens after the end of the timeline. So, let's say I've got two days worth of entries, the dev docs for the reload policy say, "A policy that specifies that WidgetKit requests a new timeline after the last date in a timeline passes."
Great! But how does it request the new timeline? Does iOS launch my app in the background and simply re-run the timeline to generate another two days worth of entries? I doubt it.
I figure I need to implement some sort of background task, and the dev docs say how to do it with an Operation, but then I read that this is an old way of doing it? I've found some info online saying to use something like this, so this is what I've implemented:
let kBackgroundWidgetRefreshTask = "my.refresh.task.identifier" // This has been registered in the info.plist correctly
class SchedulingService {
static let shared = SchedulingService()
func registerBackgroundTasks() {
let isRegistered = BGTaskScheduler.shared.register(forTaskWithIdentifier: kBackgroundWidgetRefreshTask, using: nil) { task in
print("Background task is executing: \(task.identifier)") // This does print "true"
self.handleWidgetRefresh(task: task as! BGAppRefreshTask)
}
print("Is the background task registered? \(isRegistered)")
}
func scheduleWidgetRefresh() {
let request = BGAppRefreshTaskRequest(identifier: kBackgroundWidgetRefreshTask)
// Fetch no earlier than 1 hour from now - test, will be two days
request.earliestBeginDate = Date(timeIntervalSinceNow: 60 * 60)
do {
try BGTaskScheduler.shared.submit(request)
print("Scheduled widget refresh for one hour from now")
} catch {
print("Could not schedule widget refresh: \(error)")
}
}
private func handleWidgetRefresh(task: BGAppRefreshTask) {
// Schedule a new refresh task
scheduleWidgetRefresh()
// Start refresh of the widget data
let refreshTask = Task {
do {
print("Going to refresh widgets")
try await self.backgroundRefreshWidgets()
task.setTaskCompleted(success: true)
} catch {
print("Could not refresh widgets: \(error)")
task.setTaskCompleted(success: false)
}
}
// Provide the background task with an expiration handler that cancels the operation
task.expirationHandler = {
refreshTask.cancel()
}
}
func backgroundRefreshWidgets() async throws {
print("backgroundRefreshWidgets() called")
definitelyRefreshWidgets()
}
}
As I've commented above, the line print("Background task is executing: \(task.identifier)") does print true so the task has been registered correctly.
I've put the app into the background and left it for hours and nothing is printed to the console. I've implemented a logger that writes to a file in the app container, but that doesn't get anything either.
So, is there something I'm misunderstanding? Should I change the reload policy to .after(date)? But what makes the timeline reload?
As a second but linked issue, my widgets have countdown timers on them and the entire timeline shows that every entry is correct, but the widgets on the Home Screen simply fail to refresh correctly.
For example, with timeline entries for every hour for the next two days from 6pm today (so, 7pm, 8pm...) every entry in the preview in Xcode shows the right countdown timer. However, if you put the widget on the Home Screen, after about five hours the timer shows 25:12:34 (for example).
No entry in the timeline preview ever shows more than 24 hours because the entires are every hour, and the one that shows a timer starting at 23:00:00 should never get to 24:00:00 as the next entry would kick in from 0:00:00, so it should never show more than 23:59:59 on the timer. It's like the 23:00:00 timer is just left to run for hours instead of being replaced by the next entry.
It's as though the widget isn't refreshing correctly and entries aren't loaded? Given this is the Simulator - and my development device - and both are set to Developer Mode so widget refresh budgets aren't an issue, why is this happening? How do you get widgets to refresh properly? The dev docs are not very helpful (neither is the Backyard Birds example Apple keep pushing).
Thanks!
Is there a way to prevent or disable either of the following system PTT screens?
When on the lock screen, you can tap the PTT indicator at the top of the screen to show a full-screen PTT view that includes both a "Leave" and "Talk" button
When on the home screen, you can tap the PTT indicator at the top of the screen to show the PTT "Pill" that includes a "Talk" button
I'd like to prevent showing both of these views. We don't use them in our app (we use PTT to play back messages, but use hands-free voice commands to send messages back).
Is it possible to disable/never show those system PTT views? Screenshots of them attached.
After implementing dark and tinted icon variants as per Apple’s documentation, devices running iOS versions prior to iOS 18.0 display the Dark Mode icon instead of the expected default light mode icon. As well as TestFlight showing the Dark mode icon.
I am developing an app that would like to access the contacts on the user's device. There was a recent article published that said Apple was restricting access to a user's contacts on their device. This was due to some current apps accessing the contacts and using that list for spam email and texts.
Is that they case? if so, are there specific cases that allow an App to access the contacts?
I am getting this error when I try to show device activity report view by this
DeviceActivityReport(appsContext, filter: filter)
Attempt to map database failed: permission was denied. This attempt will not be retried.
I have taken access by this way.
AuthorizationCenter.shared.requestAuthorization(for: .individual)
Bellow I created Manager to be easier for me to handle app limits, but for some reason It never reached callbacks function, I have permission for screen time, I added the capabilities for it also, I'm sure, I send correctly the appTokens, categoriesTokens ... and the time limit and it also reach ✅ Monitoring started for..., I don't know what to do anymore:
import SwiftUI
import DeviceActivity
import FamilyControls
import ManagedSettings
@MainActor
class AppUsageManager: DeviceActivityMonitor, ObservableObject {
static let shared = AppUsageManager()
private let deviceActivityCenter = DeviceActivityCenter()
private var monitoringSelections: [DeviceActivityName: (selection: FamilyActivitySelection, timeLimit: DateComponents)] = [:]
private var resetTimer: Timer?
private override init() {
super.init()
print("🟢 AppUsageManager initialized.")
}
// MARK: - Public Methods
/// Configures monitoring for a selection with a specific event name and time limit.
func configureMonitoring(
for selection: FamilyActivitySelection,
timeLimitInMinutes: Int,
activityName: String,
eventName: String
) {
let activityName = DeviceActivityName(activityName)
let eventName = DeviceActivityEvent.Name(eventName)
monitoringSelections[activityName] = (selection, DateComponents(minute: timeLimitInMinutes))
setupMonitoring(for: activityName, with: eventName)
}
/// Stops monitoring for a specific event.
func stopMonitoring(for activityName: String) {
let activityName = DeviceActivityName(activityName)
Task {
print("🛑 Stopping monitoring for \(activityName.rawValue).")
deviceActivityCenter.stopMonitoring([activityName])
monitoringSelections.removeValue(forKey: activityName)
}
}
/// Stops all monitoring.
func stopAllMonitoring() {
print("🛑 Stopping monitoring")
deviceActivityCenter.stopMonitoring()
}
// MARK: - Private Methods
/// Sets up monitoring for a specific event.
private func setupMonitoring(
for activityName: DeviceActivityName,
with eventName: DeviceActivityEvent.Name
) {
stopAllMonitoring()
guard let (selection, timeLimit) = monitoringSelections[activityName] else {
print("⚠️ No selection configured for \(activityName.rawValue).")
return
}
print("🛠 Setting up monitoring for \(activityName.rawValue).")
print("📋 Monitoring Details:")
print("- Time Limit: \(timeLimit.minute ?? 0) minutes.")
let warningThreshold = DateComponents(minute: 3)
let timeZone = TimeZone.current
let schedule = DeviceActivitySchedule(
intervalStart: DateComponents(timeZone: timeZone, hour: 0, minute: 0, second: 0),
intervalEnd: DateComponents(timeZone: timeZone, hour: 23, minute: 59, second: 59),
repeats: true,
warningTime: warningThreshold
)
let events: [DeviceActivityEvent.Name: DeviceActivityEvent] = [
eventName: DeviceActivityEvent(
applications: selection.applicationTokens,
categories: selection.categoryTokens,
webDomains: selection.webDomainTokens,
threshold: timeLimit
)
]
do {
try deviceActivityCenter.startMonitoring(
activityName,
during: schedule,
events: events
)
print("✅ Monitoring started for \(activityName.rawValue) with time limit \(timeLimit.minute ?? 0) minutes.")
} catch {
print("❌ Failed to start monitoring \(activityName.rawValue): \(error.localizedDescription)")
}
}
// MARK: - DeviceActivityMonitor Overrides
override func intervalDidStart(for activity: DeviceActivityName) {
print("🟢 Interval for \(activity.rawValue) started.")
}
override func intervalWillStartWarning(for activity: DeviceActivityName) {
print("⚠️ Warning: \(activity.rawValue) is about to start.")
}
/// Handles warnings for approaching the time limit.
override func eventWillReachThresholdWarning(
_ event: DeviceActivityEvent.Name,
activity: DeviceActivityName
) {
super.eventWillReachThresholdWarning(event, activity: activity)
print("⚠️ Warning: \(activity.rawValue) is about to reach its time limit.")
print("⚠️ Event: \(event.rawValue)")
}
/// Handles when the time limit is reached.
override func eventDidReachThreshold(
_ event: DeviceActivityEvent.Name,
activity: DeviceActivityName
) {
super.eventDidReachThreshold(event, activity: activity)
print("🟢 Limit reached.")
Task { @MainActor in
print("🕒 \(activity.rawValue) has reached its time limit.")
print("🕒 Event: \(event.rawValue)")
guard let (selection, _) = monitoringSelections[activity] else {
print("⚠️ No selection configured for \(activity.rawValue).")
return
}
blockApps(for: selection)
}
}
// MARK: - Blocking Logic
/// Blocks the selected apps/categories.
private func blockApps(for selection: FamilyActivitySelection) {
print("🔒 Blocking apps/categories for selection.")
print("- Applications: \(selection.applicationTokens)")
print("- Categories: \(selection.categoryTokens)")
let store = ManagedSettingsStore()
store.shield.applications = selection.applicationTokens
store.shield.applicationCategories = .specific(selection.categoryTokens)
print("🔒 Apps/categories blocked successfully.")
}
}
I have a question regarding a feature in the app where it calls another app.
We have a feature in our app where a WKWebView opens another app via a custom URL scheme. Initially, the system displays an alert saying, "Do you want to open Target App from My App?". However, once the user allows this action, the alert is no longer shown, and the Target App opens directly on subsequent attempts.
The issue is that if the user no longer wants the app to redirect to the Target App, they cannot reset this preference or re-enable the alert.
Is there a way, from the user's perspective, to make the alert reappear when trying to open the Target App again?
Topic:
App & System Services
SubTopic:
General
Dear fellow iOS developers,
I am interested in UWB technology and I am trying to build a dummy Indoor Navigation project.
I will be placing 3 third party UWB devices (hardware or chips) at some distance apart from each other.
I have 5 iPhones and I want to be able to connect all the 5 iPhones to the 3 UWB devices simultaneously and perform trilateration to get the iPhones x and y coordinates using the "distance" values obtained from the UWB devices (hardware or chips).
I have tried this approach using Qorvo DWM3000 chips but problem is that after the first iPhone connection, the chip stops advertising itself.
Is this approach possible?
Also, it is compulsory to establish NISessions? Can't I skip creating NISessions?
Thanks in advance. Forgive my english.
Hey Devs,
Do we have any possibility to make the apps hidden or move them to hidden folder(in iOS 18) programmatically?
Hi all,
After updating Xcode for iOS 18.2 can't add/find the widget in the simulator. However, the app work was expected with widgets with 18.1.
Has anyone else seen this?
I allowed the machine to cook for a while and it sorted itself out.
Thanks.
Blessings,
--Mark
PS I was just going to delete this post, but can not find the opetion anymore.
Topic:
App & System Services
SubTopic:
General
Hi,
There are total three errors from the app running on the device.
First one is right after the app starts running on the device:
Could not create a sandbox extension for '/var/containers/Bundle/Application/D4CBF093-EFB1-43C5-996D-7D5CB04BF643/appadmob.app'
Below second issue comes when I dismiss the Interstitial Ad
First responder issue detected: non-key window attempting reload - allowing due to manual keyboard (first responder window is <UIWindow: 0x10d11c700; frame = (0 0; 414 896); hidden = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x301749300>; backgroundColor = <UIDynamicSystemColor: 0x3002b3080; name = _windowBackgroundColor>; layer = <UIWindowLayer: 0x3019b7960>>, key window is <QUIWindow: 0x10880db00; baseClass = UIWindow; frame = (0 0; 414 896); gestureRecognizers = <NSArray: 0x3017276e0>; layer = <UIWindowLayer: 0x3019852f0>>)
And the third issue below follows right after the second one:
Error acquiring assertion: <Error Domain=RBSServiceErrorDomain Code=1 "((target is not running or doesn't have entitlement com.apple.developer.web-browser-engine.rendering AND target is not running or doesn't have entitlement com.apple.developer.web-browser-engine.networking AND target is not running or doesn't have entitlement com.apple.developer.web-browser-engine.webcontent))" UserInfo={NSLocalizedFailureReason=((target is not running or doesn't have entitlement com.apple.developer.web-browser-engine.rendering AND target is not running or doesn't have entitlement com.apple.developer.web-browser-engine.networking AND target is not running or doesn't have entitlement com.apple.developer.web-browser-engine.webcontent))}>
0x118024480 - ProcessAssertion::acquireSync Failed to acquire RBS assertion 'WebProcess NearSuspended Assertion' for process with PID=19180, error: (null)
Failed to terminate process: Error Domain=com.apple.extensionKit.errorDomain Code=18 "(null)" UserInfo={NSUnderlyingError=0x3019254a0 {Error Domain=RBSRequestErrorDomain Code=3 "No such process found" UserInfo={NSLocalizedFailureReason=No such process found}}}
Also when I dismissed the interstitial ad, the screen looks greyed out, but when I touch the screen, the screen comes to normal.
Could you please suggest any solution for the problems.
Thanks,
Topic:
App & System Services
SubTopic:
General
Tags:
Xcode
UI Frameworks
UIKit
Xcode Sanitizers and Runtime Issues
Hello, I have a Macbook Pro, 13", 2020, M1 model. Sometimes when I use my macbook, the trackpad becomes non-clickable, the only solution seems to be to manually turn it off. It has happened multiple times the past couple months, which has drawn me to write this post. I don't see manually turning it off, as a viable way of getting around the issue, on the long run.
Today I was writing an application, and it was one of those applications where you fill out a form online, and it was not saveable. My trackpad stopped working and I had to turn off my macbook and lost all progress.
Does anyone have any tips, tricks or information on what is happening? Is this just something that happens with older models? What can I do?
Topic:
App & System Services
SubTopic:
General
I'm working on an iOS app using JWPlayer to stream an HLS video. However, the stream stops and doesn't restart on both emulators and real devices. The output provides the following information:
• transportType: HTTP Live Stream
• mediaType: HTTP Live Stream
• BundleID:
• name: MEDIA_PLAYBACK_STALL
• interfaceType: Wifi
Additionally, the log shows:
(16830): Media file not received in 21s
Can anyone guide me on this issue?
While closing and reopening gamecenter, it’s not responding, and go to infinite loop
i dont know what to do
i repeated it several Times
Hello,
I have written a new app shortcut using the iOS AssistantIntent macro for the system.search scheme. It all works as it should. I can find it in the short cuts apps and if I search for my app in the Search feature of Springboard my app icon shows under top hits along with its associated search shortcut. When the shortcut is invoked it prompts for the text to search for and then it launches once the text is entered. This is fine but I would also like to have automatically created some additional shortcuts items where some of the common items I expect people to search for are already available so that when tapped they aren't prompted for search text and the intent is automatically launched with the query text. I'd like these to show up under top-hits for my app and in the shortcuts app as well.
I noticed that if I manually create the shortcuts in the shortcuts app then they show up under top-hits. However as I said I would like for my app to provide these automatically but I am unsure how to go about this and which APIs I should using.
Thx
Topic:
App & System Services
SubTopic:
General
Anyone know what exactly this means? I have enabled in Capabilities Near Field Communications Tag Read in the Xcode project AND just to make sure added it in by hand in the app certificate section on the website, yet keep on getting the error started in the title:
"/Provisioning profile "iOS Team Provisioning Profile: --------" doesn't support the Near Field Communication Tag Reading capability."
Ive taken an Apple demo and it works right out of the box.
Any ideas?
Topic:
App & System Services
SubTopic:
General