Hi,
Just want to understand what is the current state of iOS 15 prewarming app delegate behaviour.
There is a lot of confusion (and a lack of documentation) about which app delegate methods are called during prewarming.
It's not clear if didFinishLaunchingWithOptions will be called or not during prewarming.
A lot of applications are counting on UserDefaults and Keychain access in didFinishLaunchingWithOptions, but sadly these two features seems to be unavailable during prewarming causing issues.
Some users say that this was the case before 15.4 and that from 15.4 the didFinishLaunchingWithOptions app delegate method is no more called during prewarming.
Just want to know if we can have an official statement about this.
It is safe, from iOS 15.4 onwards, to use UserDefaults and access Keychain in the didFinishLaunchingWithOptions app delegate method?
Thank you
Post
Replies
Boosts
Views
Activity
Hi,
The following code allow to build an image from an UILabel:
let label = UILabel()
label.text = "test content"
label.backgroundColor = .white
label.layer.cornerRadius = 10
label.layer.masksToBounds = true
label.sizeToFit()
let format = UIGraphicsImageRendererFormat()
format.scale = 5
let renderer = UIGraphicsImageRenderer(bounds: label.bounds, format:format)
let image: UIImage? = renderer.image { rendererContext in
label.layer.render(in: rendererContext.cgContext)
}
This works perfectly on iOS but on Mac Catalyst the label text is very blurry as you can see in the image below.
Both images are created with the same exact code and have the exact same resolution of 460x103.
On top the iOS version and on bottom the Mac Catalyst version.
Note that not all of the image is blurry, but only the text. In the code I set a corner radius of 10 and you can see that the corner is rendered with an high resolution, like the iOS version. It's just the text that for some reason is blurry. It's like if the label text is rendered with a scale of 1 and then scaled up.
Someone know why? There is something I can do to improve the rendering of the text?
Thank you
Hi,
I need to generate the image of a map at a specific resolution.
I tried to use the following code:
let options = MKMapSnapshotter.Options()
options.size = CGSize(width: 300, height: 200)
options.scale = 1.0
options.mapRect = mapRect
let mapSnapshotter = MKMapSnapshotter(options: options)
if let snapshot = try? await mapSnapshotter.start() {
let image = snapshot.image
}
Since I specified the options.scale to be 1 I expect the image resolution to be exactly 300x200 pixel (and with a scale of 1).
Unfortunately the resulting image has a scale factor of 3 (on an iPhone) and the actual resolution is 900x600 pixel.
I also tried, instead of using the scale option, to set the traitCollection option, like this:
options.traitCollection = UITraitCollection(displayScale: 1.0)
but I still get a 3x scale image with a resolution of 900x600.
Why is the scale option ignored? I miss something?
Thank you
Hi,
I'm looking for a way to get the list of pending purchases, i.e. the purchases made when the "Ask to buy" feature is enabled and which have yet to be approved.
I need this in order to update the UI of my store and disable the possibility to buy products when they are pending for approval.
I tried to look into Transaction.all but pending transactions seems to be missing.
How can we get the list of pending purchases?
Thank you
Hi,
I'm starting using StoreKit 2 and I have some questions regarding transactions.
To check which non-consumable in-app purchases the user has purchased, immediately after starting the app I look at Transaction.currentEntitlements.
That's working fine, but I have some questions about it.
Question 1:
What happens if the user is not connected to the internet? Will Transaction.currentEntitlements still return data?
Question 2:
What happens if the user sign out from the AppStore? Will Transaction.currentEntitlements be empty?
Question 3:
What happens if the user sign in AppStore with different credentials? Transaction.currentEntitlements will return the transaction of the new AppStore user?
Thank you
Hi,
In a Mac Catalyst app, I need to allow the user insert a passcode using a UITextField.
The field is used to insert a one time passcode and I want to keep the content hidden. For this reason I set the isSecureTextEntry property to true.
passcodeTextField.isSecureTextEntry = true
By doing this, a button to allow the user to pick a password from the keychain is displayed:
This option in my case should not appear because the password is a one time password that change every time. For that reason I set the textContentType to oneTimeCode.
passcodeTextField.textContentType = .oneTimeCode
This actually removes the password button, but introduce something weird. If the user type something and then delete everything, a big empty box appear under the field:
I have no idea what this box is and why it appears.
Does anyone know why it appears and how I can remove it?
Thank you
I need to set the value of a variable according to a preprocessor rule, like in the example below.
var doSomething = false
#if targetEnvironment(macCatalyst)
doSomething = true
#endif
if doSomething {
print("Execute!")
}
If I build the code for an iOS simulator, Xcode will generate a "Will never be executed" alert at the print("Execute!") line.
This make sense because preprocessor rules are evaluated before compilation and therefore the code above, when the target is an iOS simulator, corresponds to:
var doSomething = false
if doSomething {
print("Execute!")
}
I just want to know if there is any advices for handling cases like that.
Ideally, I would like to avoid using the preprocessor condition for every statement, like so:
#if targetEnvironment(macCatalyst)
print("Execute!")
#endif
but rely on a variable like the original example.
I would also prefer to avoid completely disabling in Xcode the display of "Will never be executed" warnings for all source codes.
Is there a way to set the "doSomething" variable so that Xcode doesn't display the warning in a case like that?
Thank you
Hi,
If I generate an image from a symbol the resulting image is surrounded by some margins.
For example this code:
let image = UIImage(systemName: "suit.heart")
will generate this image:
As you can see there are some margins around the content.
There is a way to build an image cropped to the actual content, like showed in the below example?
Thank you
Hi,
Inside a Mac Catalyst app, I need to display a popover starting from an NSToolbarItem contained inside the app toolbar (like the Apple Maps Mac app does, see below image).
In order to do that, when I press the button I need to find the toolbar item view and use it as popover anchor.
How can I find the view or frame of an NSToolbarItem on Mac Catalyst?
A property that could help me is the NSToolbarItem "view" property (NSView), but that property has been marked has unavailable in Mac Catalyst.
Any idea?
Thank you
Hi,
I need to understand inside an override of UIBarButtonItem what is the systemItem of the button (done, add, trash, search, ...).
Unfortunately at the moment the only method I found is to inspect the content of self.description (see below), but this solution, as well as being ugly, is very fragile because we can't be sure that the description will be the same also on future version of iOS / Swift.
Someone know a better way to check for systemItem inside an UIBarButtonItem override class?
Thank you
class BarButtonItem: UIBarButtonItem {
override func awakeFromNib() {
super.awakeFromNib()
print(self.description)
}
}
<MyApp.BarButtonItem: 0x7fadbcacbea0> systemItem=Trash
Hi,
I am faced with a strange problem with a Catalyst app that uses MapKit.
If the map is visible and I resize the window (causing the map the resize), sometime the app crashes with some Metal related error.
Is this a know issue between MapKit and Catalyst?
There is something I can do in order to prevent this crash?
Below you can find the error message and a screenshot of the thread that caused the crash.
Thank you
-[MTLDebugDevice notifyExternalReferencesNonZeroOnDealloc:]:2951: failed assertion `The following Metal object is being destroyed while still required to be alive by the command buffer 0x7f96de27f600 (label: <no label set>):
<MTLToolsObject: 0x7f96dde552e0> -> <BronzeMtlTexture: 0x7f96dc04c230>
label = <none>
textureType = MTLTextureType2D
pixelFormat = MTLPixelFormatBGRA8Unorm_sRGB
width = 2372
height = 1668
depth = 1
arrayLength = 1
mipmapLevelCount = 1
sampleCount = 1
cpuCacheMode = MTLCPUCacheModeDefaultCache
storageMode = MTLStorageModeManaged
hazardTrackingMode = MTLHazardTrackingModeTracked
resourceOptions = MTLResourceCPUCacheModeDefaultCache MTLResourceStorageModeManaged MTLResourceHazardTrackingModeTracked
usage = MTLTextureUsageShaderRead MTLTextureUsageRenderTarget
shareable = 0
framebufferOnly = 0
purgeableState = MTLPurgeableStateNonVolatile
swizzle = [MTLTextureSwizzleRed, MTLTextureSwizzleGreen, MTLTextureSwizzleBlue, MTLTextureSwizzleAlpha]
isCompressed = 0
parentTexture = <null>
parentRelativeLevel = 0
parentRelativeSlice = 0
buffer = <null>
bufferOffset = 0
bufferBytesPerRow = 0
iosurface = 0x0
iosurfacePlane = 0
allowGPUOptimizedContents = YES'
Hi,
This is how I'm currently configuring an UICollectionView sidebar cell.
let rowRegistration = UICollectionView.CellRegistration<UICollectionViewListCell, SidebarItem> {
(cell, indexPath, item) in
var contentConfiguration = UIListContentConfiguration.sidebarSubtitleCell()
contentConfiguration.text = item.title
contentConfiguration.secondaryText = item.subtitle
contentConfiguration.image = item.image
cell.contentConfiguration = contentConfiguration
}
In order to specify the selection background color of the cell I'm setting the backgroundConfiguration property.
This work as expected:
let rowRegistration = UICollectionView.CellRegistration<UICollectionViewListCell, SidebarItem> {
(cell, indexPath, item) in
var contentConfiguration = UIListContentConfiguration.sidebarSubtitleCell()
contentConfiguration.text = item.title
contentConfiguration.secondaryText = item.subtitle
contentConfiguration.image = item.image
cell.contentConfiguration = contentConfiguration
var backgroundConfiguration = UIBackgroundConfiguration.listSidebarCell()
backgroundConfiguration.backgroundColorTransformer = UIConfigurationColorTransformer { [weak cell] (color) in
if let state = cell?.configurationState {
if state.isSelected || state.isHighlighted {
return UIColor(named: "Primary")!
}
}
return .clear
}
cell.backgroundConfiguration = backgroundConfiguration
}
Now I also need to change the text color based on the cell selection.
When the cell is selected the text should be white.
I tried to set the colorTransformer of textProperties of contentConfiguration like so:
contentConfiguration.textProperties.colorTransformer = UIConfigurationColorTransformer { [weak cell] (color) in
if let state = cell?.configurationState {
if state.isSelected || state.isHighlighted {
return .white
}
}
return .black
}
Unfortunately the text color does not change after the cell has been selected.
What am I doing wrong? Can anyone help me?
Thank you
Hi,
It seems that when using the inset grouped style in a UITableView, the cells are not aligned with the navigation bar large title.
However, I've noticed that all Apple apps that seem to use this style (Settings, Notes) don't have this issue and the cells are perfectly aligned with the title.
In the below example you can see that the cells of an inset grouped table are not aligned with the title (extra space between the red line and the cells) but the one's of the Apple apps are perfectly aligned.
Do you know if there is a way to change the left and right cells margins of an inset grouped table in order to align them with the large title?
Thank you
Hi,
I'm currently let the user pick a photo using PHPickerViewController.
The advantage of PHPickerViewController is that the user is not requested to grant photo access (no permission alerts).
After the user picked the photo I need to take note of the local identifier and the cloud identifier (PHCloudIdentifier).
For the local identifier no problem, I just use the assetIdentifier from the PHPickerResult.
For obtaining the cloud identifier (PHCloudIdentifier, on iOS 15 only) I need to use the cloudIdentifierMappings method of PHPhotoLibrary.
The problem of that method is that is causing the photo library access permission alerts to display.
Someone know if there is another way to get the cloud identifier from a local identifier without having to prompt the user photo library access?
Thank you
Hi!
When using a diffable data source on iOS 13 and iOS 14 in combination with a fetched result controller, the didChangeContentWith method of the NSFetchedResultsController delegate return a new snapshot with inserted, deleted and moved items.
Unfortunately, in the new snapshot items that have been modified are not refreshed.
That's because the system appears to compare the identifiers to determine whether a refresh is needed or not.
If we change an attribute of a Core Data entity the identifier remain the same and the item in the snapshot is not refreshed.
For this reason, on iOS 13 and iOS 14, we need to manually check which objects have been updated and manually refresh the corresponding items in the snapshot.
Now, it seems that on iOS 15 this is no more needed.
The new snapshot I receive in the NSFetchedResultsController didChangeContentWith delegate method also contain refreshed items.
So, in order to apply the new snapshot I only need to call a single line of code:
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChangeContentWith snapshot: NSDiffableDataSourceSnapshotReference) {
guard let diffableDataSource = diffableDataSource else {return}
diffableDataSource.apply(snapshot as NSDiffableDataSourceSnapshot<Section, NSManagedObjectID>, animatingDifferences: true)
}
That's great, but I'm not sure if that's a feature we can count on from iOS 15 onwards.
Is this new behaviour documented somewhere?
Thank you