Post

Replies

Boosts

Views

Activity

User Script Sandboxing gone from Xcode 16 beta
I'm getting Sandbox:rsync.samba deny errors trying to build an app using Xcode 16 betas. There's lots of info on this on google, and the solution everybody used to fix it is to change the Xcode build setting User Script Sandboxing from NO to YES. However this doesn't exist with Xcode 16. Does it have a replacement?
1
0
1.6k
Jun ’24
No local user-override for Live Caller Id Lookup?
If an app has a Live Caller ID Lookup extension and the lookup server indicates that a caller is identified and not blocked, then if the user wished to locally block that number they can do so either via the iPhone call block button, or via the app's Call Extension block list. However there's apparently no way for the user to do the inverse. i.e. if Live Caller Id Lookup indicated that a number should be blocked, then how could a user indicate they don't want that number blocked for them? If they added it to the Call Extension as an identified number, but live lookup is saying the number should be blocked, then what does the OS do? Give priority to the blocking instruction from the live lookup server, or give priority to the fact its in the Call Extension's Identified list?
2
0
875
Jul ’24
Live Caller ID Extension - timeout connecting to PIRService
I've followed the instructions to configure and launch a live caller id test service (https://swiftpackageindex.com/apple/live-caller-id-lookup-example/main/documentation/pirservice/testinginstructions) i.e. I've constructed a database, built and installed the PIRService etc. Additionally I have created a test app with a Live Caller ID Extension. The problem I'm facing is when turning on the Live Caller ID feature on an iPhone (the Settings|Apps|Phone|Call Blocking & Identification|Live CallerID Lookup switch) with iOS 18 Beta 4 is the phone logs: "The request timed out." UserInfo={NSLocalizedDescription=The request timed out., NSErrorFailingURLKey=http://MacBook-Pro.local:8080/.well-known/private-token-issuer-directory The configuration notes say: "When running things locally on your Mac, and your testing device is on the same network, then you can use mDNS to let the device find your Mac. Let’s assume that your Mac’s hostname is Tims-MacBook-Pro.local. Then we should use the following value for the URLs: http://Tims-Macbook-Pro.local:8080. Thanks to the mDNS protocol your device should be able to resolve your hostname to the actual IP address of your Mac and make the connection." My Mac hostname is "MacBook-Pro" therefore the Live Caller ID Extension is configured as: LiveCallerIDLookupExtensionContext( serviceURL: URL(string: "http://MacBook-Pro.local:8080")!, tokenIssuerURL: URL(string: "http://MacBook-Pro.local:8080")!, userTierToken: Data(base64Encoded: "BBBB")! ) And the service-config.json is configured as: { "issuerRequestUri": "http://MacBook-Pro.local:8080", "users": [ <snip> (I've also tried excluding the issuerRequestUri as the instructions say "This value can be omitted from the configuration. Setting this explicitly will not be required for devices using iOS 18.0 beta 4 or later.") And the PIR Service is started on the Mac as: PIRService --hostname 0.0.0.0 service-config.json And it starts and runs. The iPhone and Mac are on the same Wifi network and connected by usb cable. As far as I can tell, everything has been set up in accordance with the Testing Live Caller ID instructions, yet I get the error when attempting to enable the extension on the iPhone. Is there something missing/incorrectly configured?
8
0
1.4k
Jul ’24
Its not possible to use a Contact Provider Extension from within a Notification Service Extension
A Notification Service Extension is one of the more capable extensions, and there's a lot that can be done within it (for example, it can invoke a Call Extension). However its not possible to use a Contact Provider Extension within it. If a CPE has been enabled by the main app, then if a push is sent to the NSE, then within the NSE the ContactProviderManager class reports that the CPE is disabled and its not possible to anything with it. For example a call to ContactProviderManager.signalEnumerator() will hang and not complete. I was hoping to create a contact and make it available to the system on receipt of a push, but this isn't going to possible. Is this intentional and by design, or just due to the immaturity of this feature/iOS beta? The documentation of a Contact provider Extension says: "signalEnumerator() An example of using this call is to handle a push notification to your app when the provided contacts from your server update" It therefore seems strange that the main cited use case for ContactProviderManager.signalEnumerator() isn't actually possible if the push is delivered to an extension rather than the app.
3
0
802
Aug ’24
Isn't it time to reconcile and enhance phone caller blocking for the benefit of the user?
With iOS 18 there are now five ways for a caller to be blocked/silenced: the caller can be blocked via the Live Caller ID extension the caller can be blocked via the Call Kit extension the caller can be blocked via Block Caller via the call history recents the call could be silenced via Silence Junk Callers the call could be silenced via Silence Unknown Callers These are all totally separate and there's no way of reconciling all of them and presenting a holistic overview and management system to the user. Call blocking applications have no way of knowing which numbers will be blocked by 3) or silenced by 4) or 5), or even of determining 4) and 5) are enabled. And iOS doesn't indicate to users what will be blocked by 1) or 2). Currently users have no way of knowing what's been blocked/silenced where. Neither via call blocking apps nor via the OS. From users' perspectives its a confusing and frustrating mess. If the OS exposed which numbers have been blocked via 3) to applications and exposed if Silence Unknown Callers and Silence Junk Callers are enabled then call blocking applications could present a unified way for users to see and manage what's going on with their device holistically.
1
0
743
Jul ’24
Is it possible for a Live Caller ID server to specify different datasets?
In the documentation for the example Live Caller ID server (https://swiftpackageindex.com/apple/live-caller-id-lookup-example/main/documentation/pirservice/testinginstructions) there is an example service-config.json. file shown (without thorough documentation). That config file, and the whole of the instructions, center around there being two datasets of numbers: block and identity. My question is - is it possible for more than one dataset to be specified i.e. for block1 and block2 to be specified? The use case for this would be - suppose the Live Caller ID server has a set of numbers it has identified as being nuisance callers and so it lists these in the block section. However user A might want all these nuisance callers to be blocked but user B does not. Therefore the Live Caller ID extension on the handset would need to use a different dataset on the server so that user A's calls from a set of numbers is blocked, but user B's are not. Note that I'm not suggesting that the Caller ID server should be capable of storing individual user's preferences. All that would be required would be two data sets: one where blocked content is none and and one where blocked content is some. Then a user/app could switch between them as indicated by the user. Is that possible? If the database structure and service-config.json etc. is not configured to permit that, then could two different servers be set up to achieve this instead? i.e. so the server url specified in the app's extension can be set at run time and not at compile time?
5
0
1k
Mar ’25
Obtaining carrier entitlements for development on behalf of carriers
Hello I work for a company which is not itself a carrier, however we develop applications on behalf of carriers (the relationship between us and several large household name US carriers has existed for many years). The applications that we develop typically need carrier and/or special entitlements, for example: com.apple.CommCenter.fine-grained/public-subscriber-info com.apple.developer.coretelephony.sim-inserted com.apple.developer.pushkit.unrestricted-voip com.apple.developer.usernotifications.filtering com.apple.developer.associated-domains Obtaining those entitlements for the carrier applications that are released to the App Store is itself not a problem as the customers apply for them and they are duly granted and applied to the applications. However, what is a problem is working around the strict Apple development and distribution requirements and limitations, and the consequences that has given that the apps don't belong to our Apple account but the customers. Typically, a customer would provide us a developer certificate and set of provisioning profiles, but they would keep the distribution certificate and do the TestFlight/App Store release themselves. There's two limitations that come into play here, the first is that we can't distribute the app to TestFlight and secondly, we can only install the customer's apps on hardware registered with their Apple account. Given how the limitation for that is 100 in total, and these are large companies, they just don't have slots available and hence we might have a single device on which their app can run. These are very severe limitations given the complex nature of the applications and the need to have several developers/testers involved, which isn't possible. To mitigate those limitations we have "mirror" versions of customers' apps, these are apps which are identical to the customer apps except they have bundle ids registered to our Apple account. This enables the apps to be developed by any number of developers and distributed via Testfight and hence to any number of testers. But the problem is, the functionality of the mirror apps is severely reduced due to the fact they don't have the entitlements of the customers' apps. To get to the point of the post - I would like to know if there any potential solutions to this? For example: could it be possible for our mirror applications to be granted required entitlements (given the relationships we have with the customers. I'm sure the customers could vouch for us as a company and the need for this) could the entitlements be granted if we switched the mirror apps over to an Enterprise account (as enterprise apps can't be released to the App Store)? any other technical options or suggestions? Thank you
1
0
1.4k
Aug ’24
Is it possible to change the Xcode template type?
I've got a few years old app which was created using an Xcode template type of app. I'd like to split the model part of the code (model as in model-view-controller) out into a framework. Removed the view/controller source files to leave the model code is quick and easy, however the model code is large and complex with a couple of hundred of source files. Rather than create a new Xcode template type of framework and move the source files into there, is it possible to simply just change the template type of the existing project from app to framework?
1
0
351
Nov ’24
Why does a text filter extension receive the ISO Country Code, but not the text server?
The documentation for a text filter extension states that receiverISOCountryCode is a field the extension receives https://developer.apple.com/documentation/sms_and_call_reporting/ilmessagefilterqueryrequest/3979257-receiverisocountrycode "The ISO Country Code of the receiving phone number" However, if the extension defers to its text server, then the payload sent to the server doesn't contain the iso country code: POST /server-endpoint HTTP/1.1 Accept: */* Content-Type: application/json; charset=utf-8 Content-Length: 148 { "_version": 1, "query": { "sender": "14085550001", "message": { "text": "This is a message" } }, "app": { "version": "1.1" } } from: https://developer.apple.com/documentation/sms_and_call_reporting/ilmessagefilterextensioncontext/2880240-deferqueryrequesttonetwork Why does the payload sent to the text server not contain the country code?
2
0
414
Dec ’24
og/signpost messages lost due to high rates in live mode recording.
I'm getting literally hundreds and hundreds of these lines appearing in the Xcode console when running the app. What's the cause? Too much logging? (if so this didn't used to appear with earlier version of Xcode, I'm currently running Xcode 16.2) How to do this: "set IDELogRedirectionPolicy to oslogToStdio in the environment of the executable." And what does doing that do? <snip> 1 log/signpost messages lost due to high rates in live mode recording. To guarantee delivery of all logs, set IDELogRedirectionPolicy to oslogToStdio in the environment of the executable. 1 log/signpost messages lost due to high rates in live mode recording. To guarantee delivery of all logs, set IDELogRedirectionPolicy to oslogToStdio in the environment of the executable. <snip>
1
0
711
Dec ’24
Is it safe to access the contents of an app's bundle from within an app extension?
I've got some materials in an app's bundle (some info.plist values, and some images in .xcassets files etc.) If I access them from within an app extension (a notification service extension, notification content extension for example), then it appears to work. However while running the extensions in the debugger, there were some messages in the console saying the app bundle wasn't loaded. So despite it working, this message made me wonder if its not a safe practice and it working was luck and/or timing etc. and if the materials should instead be duplicated within the extension bundle and obtained from there instead of accessing them from the app bundle?
2
0
525
Jan ’25
Is there a way of specifying unicode characters for the BUNDLE_DISPLAY_NAME in an .xcconfig?
The BUNDLE_DISPLAY_NAME of my app changes (between Testing, Staging, Production) so that it's obvious to testers etc. which varian they are using. The name contains unicode space to ensure the OS doesn't apply kerning to the spacing within the app name. If this is put directly into the info.plist then on the iPhone desktop it's displayed as desired i.e. if the info.plist contains My Application Name Then on the iPhone desktop it displays as: My Application Name However if the name is defined in an .xcconfig file as BUNDLE_DISPLAY_NAME = Xfinity Call Guard And the info.plist contains $(BUNDLE_DISPLAY_NAME) Then the name is displayed on the iPhone desktop as My Application N.... Is there a way to specify the name with the unicode characters within an .xcconfig and get that to appear as spaces on the desktop?
2
0
441
Jan ’25
CTSubscriber.simInserted no longer works with iOS 18
We have an app which is using CTSubscriber.simInserted (using the carrier entitlement com.apple.CommCenter.fine-grained). In iOS 18, simInserted returns false for every sim (where it should instead be returning true). Presumably this just is a temporary bug in 18 beta?
Replies
6
Boosts
0
Views
1k
Activity
Jan ’25
User Script Sandboxing gone from Xcode 16 beta
I'm getting Sandbox:rsync.samba deny errors trying to build an app using Xcode 16 betas. There's lots of info on this on google, and the solution everybody used to fix it is to change the Xcode build setting User Script Sandboxing from NO to YES. However this doesn't exist with Xcode 16. Does it have a replacement?
Replies
1
Boosts
0
Views
1.6k
Activity
Jun ’24
No local user-override for Live Caller Id Lookup?
If an app has a Live Caller ID Lookup extension and the lookup server indicates that a caller is identified and not blocked, then if the user wished to locally block that number they can do so either via the iPhone call block button, or via the app's Call Extension block list. However there's apparently no way for the user to do the inverse. i.e. if Live Caller Id Lookup indicated that a number should be blocked, then how could a user indicate they don't want that number blocked for them? If they added it to the Call Extension as an identified number, but live lookup is saying the number should be blocked, then what does the OS do? Give priority to the blocking instruction from the live lookup server, or give priority to the fact its in the Call Extension's Identified list?
Replies
2
Boosts
0
Views
875
Activity
Jul ’24
Live Caller ID Extension - timeout connecting to PIRService
I've followed the instructions to configure and launch a live caller id test service (https://swiftpackageindex.com/apple/live-caller-id-lookup-example/main/documentation/pirservice/testinginstructions) i.e. I've constructed a database, built and installed the PIRService etc. Additionally I have created a test app with a Live Caller ID Extension. The problem I'm facing is when turning on the Live Caller ID feature on an iPhone (the Settings|Apps|Phone|Call Blocking & Identification|Live CallerID Lookup switch) with iOS 18 Beta 4 is the phone logs: "The request timed out." UserInfo={NSLocalizedDescription=The request timed out., NSErrorFailingURLKey=http://MacBook-Pro.local:8080/.well-known/private-token-issuer-directory The configuration notes say: "When running things locally on your Mac, and your testing device is on the same network, then you can use mDNS to let the device find your Mac. Let’s assume that your Mac’s hostname is Tims-MacBook-Pro.local. Then we should use the following value for the URLs: http://Tims-Macbook-Pro.local:8080. Thanks to the mDNS protocol your device should be able to resolve your hostname to the actual IP address of your Mac and make the connection." My Mac hostname is "MacBook-Pro" therefore the Live Caller ID Extension is configured as: LiveCallerIDLookupExtensionContext( serviceURL: URL(string: "http://MacBook-Pro.local:8080")!, tokenIssuerURL: URL(string: "http://MacBook-Pro.local:8080")!, userTierToken: Data(base64Encoded: "BBBB")! ) And the service-config.json is configured as: { "issuerRequestUri": "http://MacBook-Pro.local:8080", "users": [ <snip> (I've also tried excluding the issuerRequestUri as the instructions say "This value can be omitted from the configuration. Setting this explicitly will not be required for devices using iOS 18.0 beta 4 or later.") And the PIR Service is started on the Mac as: PIRService --hostname 0.0.0.0 service-config.json And it starts and runs. The iPhone and Mac are on the same Wifi network and connected by usb cable. As far as I can tell, everything has been set up in accordance with the Testing Live Caller ID instructions, yet I get the error when attempting to enable the extension on the iPhone. Is there something missing/incorrectly configured?
Replies
8
Boosts
0
Views
1.4k
Activity
Jul ’24
The Contact Provider Extension template code has errors
If using Xcode beta 16 beta 4, a target type of Contact Provider Extension is created, then the auto-generated template code has errors right off the bat. Compiler be like what in the dickens is this?: class ContactProviderExtension: ContactProviderExtension
Replies
1
Boosts
0
Views
700
Activity
Jul ’24
Its not possible to use a Contact Provider Extension from within a Notification Service Extension
A Notification Service Extension is one of the more capable extensions, and there's a lot that can be done within it (for example, it can invoke a Call Extension). However its not possible to use a Contact Provider Extension within it. If a CPE has been enabled by the main app, then if a push is sent to the NSE, then within the NSE the ContactProviderManager class reports that the CPE is disabled and its not possible to anything with it. For example a call to ContactProviderManager.signalEnumerator() will hang and not complete. I was hoping to create a contact and make it available to the system on receipt of a push, but this isn't going to possible. Is this intentional and by design, or just due to the immaturity of this feature/iOS beta? The documentation of a Contact provider Extension says: "signalEnumerator() An example of using this call is to handle a push notification to your app when the provided contacts from your server update" It therefore seems strange that the main cited use case for ContactProviderManager.signalEnumerator() isn't actually possible if the push is delivered to an extension rather than the app.
Replies
3
Boosts
0
Views
802
Activity
Aug ’24
Isn't it time to reconcile and enhance phone caller blocking for the benefit of the user?
With iOS 18 there are now five ways for a caller to be blocked/silenced: the caller can be blocked via the Live Caller ID extension the caller can be blocked via the Call Kit extension the caller can be blocked via Block Caller via the call history recents the call could be silenced via Silence Junk Callers the call could be silenced via Silence Unknown Callers These are all totally separate and there's no way of reconciling all of them and presenting a holistic overview and management system to the user. Call blocking applications have no way of knowing which numbers will be blocked by 3) or silenced by 4) or 5), or even of determining 4) and 5) are enabled. And iOS doesn't indicate to users what will be blocked by 1) or 2). Currently users have no way of knowing what's been blocked/silenced where. Neither via call blocking apps nor via the OS. From users' perspectives its a confusing and frustrating mess. If the OS exposed which numbers have been blocked via 3) to applications and exposed if Silence Unknown Callers and Silence Junk Callers are enabled then call blocking applications could present a unified way for users to see and manage what's going on with their device holistically.
Replies
1
Boosts
0
Views
743
Activity
Jul ’24
Is it possible for a Live Caller ID server to specify different datasets?
In the documentation for the example Live Caller ID server (https://swiftpackageindex.com/apple/live-caller-id-lookup-example/main/documentation/pirservice/testinginstructions) there is an example service-config.json. file shown (without thorough documentation). That config file, and the whole of the instructions, center around there being two datasets of numbers: block and identity. My question is - is it possible for more than one dataset to be specified i.e. for block1 and block2 to be specified? The use case for this would be - suppose the Live Caller ID server has a set of numbers it has identified as being nuisance callers and so it lists these in the block section. However user A might want all these nuisance callers to be blocked but user B does not. Therefore the Live Caller ID extension on the handset would need to use a different dataset on the server so that user A's calls from a set of numbers is blocked, but user B's are not. Note that I'm not suggesting that the Caller ID server should be capable of storing individual user's preferences. All that would be required would be two data sets: one where blocked content is none and and one where blocked content is some. Then a user/app could switch between them as indicated by the user. Is that possible? If the database structure and service-config.json etc. is not configured to permit that, then could two different servers be set up to achieve this instead? i.e. so the server url specified in the app's extension can be set at run time and not at compile time?
Replies
5
Boosts
0
Views
1k
Activity
Mar ’25
Obtaining carrier entitlements for development on behalf of carriers
Hello I work for a company which is not itself a carrier, however we develop applications on behalf of carriers (the relationship between us and several large household name US carriers has existed for many years). The applications that we develop typically need carrier and/or special entitlements, for example: com.apple.CommCenter.fine-grained/public-subscriber-info com.apple.developer.coretelephony.sim-inserted com.apple.developer.pushkit.unrestricted-voip com.apple.developer.usernotifications.filtering com.apple.developer.associated-domains Obtaining those entitlements for the carrier applications that are released to the App Store is itself not a problem as the customers apply for them and they are duly granted and applied to the applications. However, what is a problem is working around the strict Apple development and distribution requirements and limitations, and the consequences that has given that the apps don't belong to our Apple account but the customers. Typically, a customer would provide us a developer certificate and set of provisioning profiles, but they would keep the distribution certificate and do the TestFlight/App Store release themselves. There's two limitations that come into play here, the first is that we can't distribute the app to TestFlight and secondly, we can only install the customer's apps on hardware registered with their Apple account. Given how the limitation for that is 100 in total, and these are large companies, they just don't have slots available and hence we might have a single device on which their app can run. These are very severe limitations given the complex nature of the applications and the need to have several developers/testers involved, which isn't possible. To mitigate those limitations we have "mirror" versions of customers' apps, these are apps which are identical to the customer apps except they have bundle ids registered to our Apple account. This enables the apps to be developed by any number of developers and distributed via Testfight and hence to any number of testers. But the problem is, the functionality of the mirror apps is severely reduced due to the fact they don't have the entitlements of the customers' apps. To get to the point of the post - I would like to know if there any potential solutions to this? For example: could it be possible for our mirror applications to be granted required entitlements (given the relationships we have with the customers. I'm sure the customers could vouch for us as a company and the need for this) could the entitlements be granted if we switched the mirror apps over to an Enterprise account (as enterprise apps can't be released to the App Store)? any other technical options or suggestions? Thank you
Replies
1
Boosts
0
Views
1.4k
Activity
Aug ’24
Is it possible to change the Xcode template type?
I've got a few years old app which was created using an Xcode template type of app. I'd like to split the model part of the code (model as in model-view-controller) out into a framework. Removed the view/controller source files to leave the model code is quick and easy, however the model code is large and complex with a couple of hundred of source files. Rather than create a new Xcode template type of framework and move the source files into there, is it possible to simply just change the template type of the existing project from app to framework?
Replies
1
Boosts
0
Views
351
Activity
Nov ’24
Why does a text filter extension receive the ISO Country Code, but not the text server?
The documentation for a text filter extension states that receiverISOCountryCode is a field the extension receives https://developer.apple.com/documentation/sms_and_call_reporting/ilmessagefilterqueryrequest/3979257-receiverisocountrycode "The ISO Country Code of the receiving phone number" However, if the extension defers to its text server, then the payload sent to the server doesn't contain the iso country code: POST /server-endpoint HTTP/1.1 Accept: */* Content-Type: application/json; charset=utf-8 Content-Length: 148 { "_version": 1, "query": { "sender": "14085550001", "message": { "text": "This is a message" } }, "app": { "version": "1.1" } } from: https://developer.apple.com/documentation/sms_and_call_reporting/ilmessagefilterextensioncontext/2880240-deferqueryrequesttonetwork Why does the payload sent to the text server not contain the country code?
Replies
2
Boosts
0
Views
414
Activity
Dec ’24
og/signpost messages lost due to high rates in live mode recording.
I'm getting literally hundreds and hundreds of these lines appearing in the Xcode console when running the app. What's the cause? Too much logging? (if so this didn't used to appear with earlier version of Xcode, I'm currently running Xcode 16.2) How to do this: "set IDELogRedirectionPolicy to oslogToStdio in the environment of the executable." And what does doing that do? <snip> 1 log/signpost messages lost due to high rates in live mode recording. To guarantee delivery of all logs, set IDELogRedirectionPolicy to oslogToStdio in the environment of the executable. 1 log/signpost messages lost due to high rates in live mode recording. To guarantee delivery of all logs, set IDELogRedirectionPolicy to oslogToStdio in the environment of the executable. <snip>
Replies
1
Boosts
0
Views
711
Activity
Dec ’24
Is it safe to access the contents of an app's bundle from within an app extension?
I've got some materials in an app's bundle (some info.plist values, and some images in .xcassets files etc.) If I access them from within an app extension (a notification service extension, notification content extension for example), then it appears to work. However while running the extensions in the debugger, there were some messages in the console saying the app bundle wasn't loaded. So despite it working, this message made me wonder if its not a safe practice and it working was luck and/or timing etc. and if the materials should instead be duplicated within the extension bundle and obtained from there instead of accessing them from the app bundle?
Replies
2
Boosts
0
Views
525
Activity
Jan ’25
Is there a way of specifying unicode characters for the BUNDLE_DISPLAY_NAME in an .xcconfig?
The BUNDLE_DISPLAY_NAME of my app changes (between Testing, Staging, Production) so that it's obvious to testers etc. which varian they are using. The name contains unicode space to ensure the OS doesn't apply kerning to the spacing within the app name. If this is put directly into the info.plist then on the iPhone desktop it's displayed as desired i.e. if the info.plist contains My Application Name Then on the iPhone desktop it displays as: My Application Name However if the name is defined in an .xcconfig file as BUNDLE_DISPLAY_NAME = Xfinity Call Guard And the info.plist contains $(BUNDLE_DISPLAY_NAME) Then the name is displayed on the iPhone desktop as My Application N.... Is there a way to specify the name with the unicode characters within an .xcconfig and get that to appear as spaces on the desktop?
Replies
2
Boosts
0
Views
441
Activity
Jan ’25
Message Filter Extension and associated domains
The documentation for adding a Message Filter Extension states that the Associated Domains capability should be added to the Xcode project. But what does that mean, should it be added to the app extension, to the app, or to both the app extension and the app? The documentation doesn't say which exactly.
Replies
2
Boosts
0
Views
441
Activity
Jan ’25