If there is the following code for a notification service extension
var countOfInvocations = 0
public class NotificationService: UNNotificationServiceExtension {
public override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
NSLog("Push count: \(countOfInvocations)")
countOfInvocations = countOfInvocations + 1
Then if pushes are sent to the handset it can be observed in the console log that the value of countOfInvocations keeps increasing, meaning the NotificationService class is getting instantiated and destroyed within the same process.
However at what point does that process get torn down by the OS? It seems to be kept alive for about 10 minutes or so. Is there a way the extension can detect its the same or a new process?
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Created
If you create a CallKit extension with Xcode 15 beta, then add some logging to the template code that gets created and run it on an iOS 17.3 beta phone the logging clearly shows that the OS is running the extension twice when the user turns on the extension in Settings. Run it on any device with < iOS 17 and its only invoked once, as it should be.
However, not only does the OS run it twice, but based on the logging the two invocations are in parallel, not serial, suggesting two CallDirectoryHandler instances are being created and run simultaneously.
My app has several app extensions and I'd like to be able to unify the logging between them such that they write to a single shared file (which can be read from and subsequently uploaded to things like Crashltyics or Bugsnag etc.)
Its possible to log directly to things like Crashlytics, however none of them I've investigated have a unified approach for the app and extensions (for example, if you use Crashlytics you have to configure the app and the extensions separately, so any logging goes to two entirely separate consoles.)
Hence, instead I'm wondering if there a library that provides the ability to log to a file, and that file can be shared and simultaneously written to (in the case where the app and its extensions are running simultaneously).
Do any of the existing log libraries for iOS have this ability?
If you go to https://feedbackassistant.apple.com and create a new feedback (for iOS and iPad) item, then these are the types of feedback choices:
Incorrect/Unexpected Behavior
Application Crash
Application Slow/Unresponsive
Battery Life
Suggestion
A suggestion sounds more like something an iPhone user want so suggest as a feature, not how a developer might request an API feature. Is that really what, as a developer, you are supposed to use to make a development feature request?
On my iPhone, in Settings, I've added my company Exchange account. Consequently, within the Contacts app, 4 new lists appear - the bottom as shown in the attached image.
There's a few thousand contacts in the Company Exchange account, so why are the count values showing as 0? If I click on the Global Address list and search, it can succfully find whatever I search for. I want to programatically retrieve the contacts within the Exchange account, in addition to those stored locally or within iCloud, however if I execute the following code, for the container of type exchange, the count of results of the call to unifiedContacts() is 0.
How can I programatically get the Exchange contacts? If the call to unifiedContacts() is resulting in 0 because the count for the lists when viewing the Contacts app is 0, then how to make it not 0 in the Contacts app (but if that were the case, how come manually searching for a contact is successful?)
let keysToFetch = [
CNContactFormatter.descriptorForRequiredKeys(for: .fullName),
CNContactPhoneNumbersKey,
CNContactEmailAddressesKey,
CNContactThumbnailImageDataKey] as [Any]
var allContainers: [CNContainer] = []
do {
allContainers = try CNContactStore().containers(matching: nil)
} catch {
print("Error fetching containers")
}
var results: [CNContact] = []
for container in allContainers {
let type = container.type
let identifier = container.identifier
let fetchPredicate = CNContact.predicateForContactsInContainer(withIdentifier: container.identifier)
do {
let containerResults = try CNContactStore().unifiedContacts(matching: fetchPredicate, keysToFetch: keysToFetch as! [CNKeyDescriptor])
let count = containerResults.count
results.append(contentsOf: containerResults)
} catch {
print("Error fetching containers")
}
}
You can programatically get/set a picture and a thumbnail for a contact, however the new poster field added to iOS 17 apparently has no programatic access? I'm not able to see anything new being added to CNContact.h
My app builds fine with Xcode 14, 13 and 12, but when attempting to build it with Xcode 15 there's an "Cycle inside MyApp; building could produce unreliable results." error.
The output below isn't giving me any clues that I can see about what the cause of the cycle is nor how to fix it, any ideas?
Cycle inside MyApp; building could produce unreliable results.
Cycle details:
→ Target 'MyApp': ExtractAppIntentsMetadata
○ Target 'MyApp': CodeSign /Users/me/Library/Developer/Xcode/DerivedData/ProjectA-frqscjhianktlvbxgbzostesljpn/Build/Products/Debug-iphoneos/MyApp.app/Frameworks/3rdPartyFramework.framework
○ Target 'MyApp' has copy command from '/Users/me/Desktop/Checkouts/MyApp/theApp/MyApp/ios/3rdPartyFramework.framework' to '/Users/me/Library/Developer/Xcode/DerivedData/ProjectA-frqscjhianktlvbxgbzostesljpn/Build/Products/Debug-iphoneos/MyApp.app/Frameworks/3rdPartyFramework.framework'
○ Target 'MyApp' has copy command from '/Users/me/Library/Developer/Xcode/DerivedData/ProjectA-frqscjhianktlvbxgbzostesljpn/Build/Products/Debug-iphoneos/CallExtension.appex' to '/Users/me/Library/Developer/Xcode/DerivedData/ProjectA-frqscjhianktlvbxgbzostesljpn/Build/Products/Debug-iphoneos/MyApp.app/PlugIns/CallExtension.appex'
○ That command depends on command in Target 'MyApp': script phase “Add Git/CI Build Info”
○ Target 'MyApp' has process command with output '/Users/me/Library/Developer/Xcode/DerivedData/ProjectA-frqscjhianktlvbxgbzostesljpn/Build/Products/Debug-iphoneos/MyApp.app/Info.plist'
○ Target 'MyApp' has copy command from '/Users/me/Desktop/Checkouts/MyApp/theApp/MyApp/ios/3rdPartyFramework.framework' to '/Users/me/Library/Developer/Xcode/DerivedData/ProjectA-frqscjhianktlvbxgbzostesljpn/Build/Products/Debug-iphoneos/MyApp.app/Frameworks/3rdPartyFramework.framework'
Raw dependency cycle trace:
target: ->
node: <all> ->
command: <all> ->
node: /Users/me/Library/Developer/Xcode/DerivedData/ProjectA-frqscjhianktlvbxgbzostesljpn/Build/Intermediates.noindex/ProjectA.build/Debug-iphoneos/MyApp.build/Objects-normal/arm64/ExtractedAppShortcutsMetadata.stringsdata ->
command: P0:target-MyApp-2a7e5ca2b3fd2ca0faca1487721e3ae07ceb6b36bcfc2fb90f69ac96de4975d6-:Debug:ExtractAppIntentsMetadata ->
node: <target-MyApp-2a7e5ca2b3fd2ca0faca1487721e3ae07ceb6b36bcfc2fb90f69ac96de4975d6--package-copy-files-phase> ->
command: P0:::Gate target-MyApp-2a7e5ca2b3fd2ca0faca1487721e3ae07ceb6b36bcfc2fb90f69ac96de4975d6--package-copy-files-phase ->
node: <target-MyApp-2a7e5ca2b3fd2ca0faca1487721e3ae07ceb6b36bcfc2fb90f69ac96de4975d6--fused-phase11-copy-files> ->
command: P0:::Gate target-MyApp-2a7e5ca2b3fd2ca0faca1487721e3ae07ceb6b36bcfc2fb90f69ac96de4975d6--fused-phase11-copy-files ->
node: <CodeSign /Users/me/Library/Developer/Xcode/DerivedData/ProjectA-frqscjhianktlvbxgbzostesljpn/Build/Products/Debug-iphoneos/MyApp.app/Frameworks/3rdPartyFramework.framework> ->
command: P0:target-MyApp-2a7e5ca2b3fd2ca0faca1487721e3ae07ceb6b36bcfc2fb90f69ac96de4975d6-:Debug:CodeSign /Users/me/Library/Developer/Xcode/DerivedData/ProjectA-frqscjhianktlvbxgbzostesljpn/Build/Products/Debug-iphoneos/MyApp.app/Frameworks/3rdPartyFramework.framework ->
node: <Copy /Users/me/Library/Developer/Xcode/DerivedData/ProjectA-frqscjhianktlvbxgbzostesljpn/Build/Products/Debug-iphoneos/MyApp.app/Frameworks/3rdPartyFramework.framework> ->
CYCLE POINT ->
command: P0:target-MyApp-2a7e5ca2b3fd2ca0faca1487721e3ae07ceb6b36bcfc2fb90f69ac96de4975d6-:Debug:Copy /Users/me/Library/Developer/Xcode/DerivedData/ProjectA-frqscjhianktlvbxgbzostesljpn/Build/Products/Debug-iphoneos/MyApp.app/Frameworks/3rdPartyFramework.framework /Users/me/Desktop/Checkouts/MyApp/theApp/MyApp/ios/3rdPartyFramework.framework ->
node: <target-MyApp-2a7e5ca2b3fd2ca0faca1487721e3ae07ceb6b36bcfc2fb90f69ac96de4975d6--fused-phase10--cp--copy-pods-resources> ->
command: P0:::Gate target-MyApp-2a7e5ca2b3fd2ca0faca1487721e3ae07ceb6b36bcfc2fb90f69ac96de4975d6--fused-phase10--cp--copy-pods-resources ->
node: /Users/me/Library/Developer/Xcode/DerivedData/ProjectA-frqscjhianktlvbxgbzostesljpn/Build/Intermediates.noindex/ProjectA.build/Debug-iphoneos/MyApp.build/InputFileList-F72A917A68CD9152103DBA60-Pods-MyApp-resources-Debug-input-files-037b34732b45cb31a2dcb00ffdfe9f5c-resolved.xcfilelist ->
command: P2:target-MyApp-2a7e5ca2b3fd2ca0faca1487721e3ae07ceb6b36bcfc2fb90f69ac96de4975d6-:Debug:WriteAuxiliaryFile /Users/me/Library/Developer/Xcode/DerivedData/ProjectA-frqscjhianktlvbxgbzostesljpn/Build/Intermediates.noindex/ProjectA.build/Debug-iphoneos/MyApp.build/InputFileList-F72A917A68CD9152103DBA60-Pods-MyApp-resources-Debug-input-files-037b34732b45cb31a2dcb00ffdfe9f5c-resolved.xcfilelist ->
node: <target-MyApp-2a7e5ca2b3fd2ca0faca1487721e3ae07ceb6b36bcfc2fb90f69ac96de4975d6--fused-phase9--cp--embed-pods-frameworks> ->
command: P0:::Gate target-MyApp-2a7e5ca2b3fd2ca0faca1487721e3ae07ceb6b36bcfc2fb90f69ac96de4975d6--fused-phase9--cp--embed-pods-frameworks ->
node: /Users/me/Library/Developer/Xcode/DerivedData/ProjectA-frqscjhianktlvbxgbzostesljpn/Build/Intermediates.noindex/ProjectA.build/Debug-iphoneos/MyApp.build/InputFileList-7E0D6830477C665FCC1083CC-Pods-MyApp-frameworks-Debug-input-files-36820974ee8465975a73448c9644b936-resolved.xcfilelist ->
command: P2:target-MyApp-2a7e5ca2b3fd2ca0faca1487721e3ae07ceb6b36bcfc2fb90f69ac96de4975d6-:Debug:WriteAuxiliaryFile /Users/me/Library/Developer/Xcode/DerivedData/ProjectA-frqscjhianktlvbxgbzostesljpn/Build/Intermediates.noindex/ProjectA.build/Debug-iphoneos/MyApp.build/InputFileList-7E0D6830477C665FCC1083CC-Pods-MyApp-frameworks-Debug-input-files-36820974ee8465975a73448c9644b936-resolved.xcfilelist ->
node: <target-MyApp-2a7e5ca2b3fd2ca0faca1487721e3ae07ceb6b36bcfc2fb90f69ac96de4975d6--fused-phase8-upload-crashlytics> ->
command: P0:::Gate target-MyApp-2a7e5ca2b3fd2ca0faca1487721e3ae07ceb6b36bcfc2fb90f69ac96de4975d6--fused-phase8-upload-crashlytics ->
node: <target-MyApp-2a7e5ca2b3fd2ca0faca1487721e3ae07ceb6b36bcfc2fb90f69ac96de4975d6--fused-phase7-upload-debug-symbols-to-sentry> ->
command: P0:::Gate target-MyApp-2a7e5ca2b3fd2ca0faca1487721e3ae07ceb6b36bcfc2fb90f69ac96de4975d6--fused-phase7-upload-debug-symbols-to-sentry ->
node: <target-MyApp-2a7e5ca2b3fd2ca0faca1487721e3ae07ceb6b36bcfc2fb90f69ac96de4975d6--fused-phase6-crashlytics> ->
command: P0:::Gate target-MyApp-2a7e5ca2b3fd2ca0faca1487721e3ae07ceb6b36bcfc2fb90f69ac96de4975d6--fused-phase6-crashlytics ->
node: <target-MyApp-2a7e5ca2b3fd2ca0faca1487721e3ae07ceb6b36bcfc2fb90f69ac96de4975d6--fused-phase5-copy-files> ->
command: P0:::Gate target-MyApp-2a7e5ca2b3fd2ca0faca1487721e3ae07ceb6b36bcfc2fb90f69ac96de4975d6--fused-phase5-copy-files ->
node: <Copy /Users/me/Library/Developer/Xcode/DerivedData/ProjectA-frqscjhianktlvbxgbzostesljpn/Build/Products/Debug-iphoneos/MyApp.app/PlugIns/CallExtension.appex> ->
<snip> too large to post all
The Xcode 15 beta does not have a 17.* folder within Developer/Platforms/iPhoneOS.platform/DeviceSupport.
How therefore does it build/install/run on a a phone with iOS 17 installed? Is there a different mechanism for device support used from 17 onwards than has historically been the case?
I want to build/run using Xcode 14.n with an iOS 17 phone, but without being able to locate the iOS 17 support file am unable to do so.
Where is the iOS 17 device support files with Xcode 15? How can I build using Xcode 14 for iOS 17 if its not present in Xcode15 (in order to drag and drop it into Xcode 14)
With Xcode 15 if you attach an iPhone (with iOS 17 installed) and then select Window|Devices & Simulators, then you can see the connected iPhone of the left hand side of the organizer.
However with the iPhone selected, when the Open Console button is clicked it doesn't launch the console for the phone but instead for the Mac.
There's therefore no way to view the handset logs (you can see the app logs within Xcode as per usual, but you can't view the holistic handset logs).
In the past I've used lipo to remove unwanted architectures from fat frameworks, using lipo -remove.
However when attempting to do similarly with a .xcframework I keep getting errors, its not just the -remove command.
If for example I run lipo -info someFramework.xcframework then the error is:
can't map input file: someFramework.xcframework (Invalid argument)
if I cd into the xcframework and run
lipo -remove ios-arm64_x86_64-simulator
then the error is
unknown architecture specification flag: ios-arm64_x86_64-simulator in specifying remove operation: -remove ios-arm64_x86_64-simulator
using an xcframework supplied by 3rd party.
I can build/run/install the app and use the framework without issue when running/installing from Xcode. However if I create an archive and then attempt to upload it to TestFlight I get two errors, the first is:
CFBundelIdentifer Collision. There is more than one bundle with the CFBundelIdentifer value bundleidofframework under the application
And the second is
Invalid Bundle. The bundle at ...myextension.appex contains disallowed file Frameworks.
(I'm using the framework within both the app and an extension)
Within the embed frameworks section of Xcode, the tickbox code sign on copy is ticked (that's the default value and if its unticked then the app doesn't run when installed directly via Xcode).
Without exception, every single code example/tutorial for adding a contact group uses a nil container value i.e. the toContainerWithIdentifier parameter is nil, as below. I've not been able to find an example usage where it isn't nil.
let group = CNMutableGroup()
group.name = "whatever"
let saveRequest = CNSaveRequest()
saveRequest.add(group, toContainerWithIdentifier: nil)
do {
try store.execute(saveRequest)
} catch {
handle error
}
I've been running this code and 99.9% of the time it works as expected. However on one handset the catch is being executed with
Error Domain=CNErrorDomain Code=207 "Container is read-only"
How should I deal with this? How can I find out what container it is being added to? Why would it be read only?
If nil means add to the default container, why is the default container in this case read only?
How can I change the code that it will always run on every device? I've not been able to find any examples/tutorials for creating a custom container to which the group can be added.
I've linked my contacts app on my iPhone to my company contacts database, and it shows up in the contacts app as "My Company Global Address List", and I can tap on it and search within it.
However using CNContactFetchRequest doesn't retrieve any of those contacts, is it something that's possible to do, if so how?
I intentionally deleted iOS development/distribution related certificates from my keychain (Login, Local Items, System, System Roots).
Then built my app in Xcode. Automatically manage signing is turned on and Xcode created/installed an Apple Development certificate to my keychain).
But if I create an archive, I am able to successfully create a development distribution, an ad-hoc distribution, and even upload to App Store Connect. Yet I don't have a distribution certificate anywhere in my keychain.
I therefore don't understand how this was possible. How could I create all those distributions without a distribution certificate in the keychain?
An app can legally link into its own section of the Settings app, and if it uses CallKit, it can link into the Call Blocking & Identification section.
Linking anywhere else into Settings is making use of private URL schemes and is supposed to not be permitted and the app rejected during submission.
However the Robokiller app deep links into the Settings app with the page scrolled down to where the Phone section is.
How are they doing that? Is there some new API that permits the app to link to there? Or are they making illegal use of private URIs and have been getting away with getting past App Store review for years?