Hi,
In my Core Data schema, I have a 'transformable' attribute in an entity, which is using a custom NSValueTransformer, the purpose of which is to convert a UIImage into NSData with some compression (basically to save a small thumbnail from the image). From this attribute, I had recently started getting these warnings about using NSKeyedUnarchiveFromData:
'NSKeyedUnarchiveFromData' should not be used to for un-archiving and will be removed in a future release
So I read about this, and figured I'd need to change the NSValueTransformer to using NSSecureUnarchiveFromDataTransformer ... but after making the changes (as best as I understood them) I can't get it to work, and now the app crashes when the attribute is accessed.
This is the existing NSValueTransformer that I was using:
@interface ImageToDataTransformer : NSValueTransformer {
}
@implementation ImageToDataTransformer (BOOL)allowsReverseTransformation {
return YES;
}
(Class)transformedValueClass {
return [NSData class];
}
(id)transformedValue:(id)value {
// for our smaller views this uses much less data and makes for faster syncing
NSData *compressedData = UIImageJPEGRepresentation(value, 0.2);
return compressedData;
}
(id)reverseTransformedValue:(id)value {
UIImage *uiImage = [[UIImage alloc] initWithData:value];
NSData *data = (NSData *) value;
//NSLog(@"reverseTransformedValue: image size: %@", [NSByteCountFormatter stringFromByteCount:data.length countStyle:NSByteCountFormatterCountStyleFile]);
return uiImage;
}
So I changed it to subclass from NSSecureUnarchiveFromDataTransformer instead, and added the following to the implementation:
(NSArrayClass *)allowedTopLevelClasses {
return @[[ImageToDataTransformer class]];
}
(void)setValueTransformer:(nullable NSValueTransformer *)transformer forName:(NSValueTransformerName)name {
NSLog(@"ImageToDataTransfer: calling setValueTransformer");
[NSValueTransformer setValueTransformer:transformer forName:name];
}
(NSArrayNSValueTransformerName *)valueTransformerNames {
return @[@"ImageToDataTransformerName"];
}
Before the Core Data persistent store is accessed, I 'register' the transformer:
[ImageToDataTransformer setValueTransformer: [[ImageToDataTransformer alloc] init] forName:@"ImageToDataTransformerName"];
Now the app crashes when the image is read:
[__NSCFData _rasterizedImage]: unrecognized selector sent to instance 0x7ff53c108800
If I change the transformer back to NSValueTransformer, it works fine. So I'm not sure if I'm missing something from the implementation, or I have misunderstood the premise of 'NSSecureUnarchiveFromDataTransformer'. Would love to know what I can do to fix this.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
Hi,
I have an 'uploader' function in my app that can populate the CloudKit private database with a lot of user data. I batch the records into multiple CKModifyRecordsOperations, across the different record types, before I upload them. When I do this with a lot of data, I sometimes get CKErrorRequestRateLimited errors, with a value for CKErrorRetryAfterKey specified in the CKError, for a few of the modify operations. I usually respond by creating new operations for the same records, delaying them by the specified CKErrorRetryAfterKey key, and then retrying the operations. But those operations end up getting more errors with CKErrorServiceUnavailable or CKErrorRequestRateLimited again.
So my question is .... is the CKErrorRetryAfterKey value supposed to be cumulative, and does it apply across operations? For e.g. if I have Operations 1, 2 and 3, and each of them returns with a 'retry' error value (say 5, 10, and 15 seconds) ... can I retry them with the retry values for each operation (5 secs for Op1 etc), or should I choose the highest retry value before trying another operation (15 secs), or should I add them up and not try anything for the sum of their retry values (30 secs)? And is this ‘retry’ value limited to each record type, or is it generally for the whole container?
If anyone has an insight into this, I would love to know.
Thanks,
Zulfi Shah.
Hi,
I am using a rich, detailed view to show information in an MKAnnotationView's detailAccessoryView. As such, I don't need to use the 'title' or 'subtitle' fields that come with the callout view. However, I also want to show the 'title' under the MKMarkerAnnotationView on the map. Unfortunately it looks like the same MKAnnotation's 'title' property is used for both the marker's name on the map, as well as in the callout view. So I'm trying to figure out if there's any way to hide the 'title' in just the callout view. One thing I was considering was hiding the 'title' when an annotationView is selected, but doing this in 'didSelectAnnotationView' is too late to take affect for the callout view, and there doesn't seem to be an option for a delegate call like 'willSelectAnnotationView'. Is there any other way to figure out just before the annotation is selected?
I am adding a small SwiftUI view to my NSTableViewCell, using NSHostingView. Occasionally (randomly) I get this crash in the debugger, but I don't understand what it means:
#0 0x00007fff4309ace6 in AG::data::table::grow_region() ()
#1 0x00007fff4309b155 in AG::data::table::alloc_page(AG::data::zone&, unsigned int) ()
#2 0x00007fff4309b430 in AG::data::zone::alloc_slow(unsigned int, unsigned int) ()
#3 0x00007fff430a1bad in AG::Graph::add_attribute(AG::Subgraph&, unsigned int, void const*, void const*) ()
#4 0x00007fff430b87fe in Attribute.initτ_0_0(body:value:flags:update:) ()
#5 0x00007fff42e8da29 in GraphHost.Data.init() ()
#6 0x00007fff4273e532 in ViewGraph.initτ_0_0(rootViewType:requestedOutputs:) ()
#7 0x00007fff4273e3be in ViewGraph.__allocating_initτ_0_0(rootViewType:requestedOutputs:) ()
#8 0x00007fff42d795d6 in NSHostingView.init(rootView:) ()
#9 0x00007fff42d785dd in NSHostingView.__allocating_init(rootView:) ()
#10 0x00000001036494ff in ContactsCountIconsInterface.makeContactsCountView() at /Users/z/Documents/Git/branches/SimpleList/Mac/ContactsCountIconsInterface.swift:23
#11 0x0000000103649558 in @objc ContactsCountIconsInterface.makeContactsCountView() ()
#12 0x000000010347ed1a in -[ContactDataCellView setupIconsCountViewWithCountForLogsCount:todosCount:filesCount:] at /Users/z/Documents/ContactsJournalGit/branches/SimpleList/ContactDataCellView.m:40
#13 0x0000000103445f88 in -[MacContactsViewController outlineView:viewForTableColumn:item:] at /Users/z/Documents/ContactsJournalGit/branches/SimpleList/Mac/MacContactsViewController.m:745
#14 0x00007fff22dde8b5 in -[NSTableView(NSTableViewViewBased) makeViewForTableColumn:row:] ()
#15 0x00007fff22dddf03 in -[NSTableRowData _addViewToRowView:atColumn:row:] ()
#16 0x00007fff22dddc38 in -[NSTableRowData _addViewsToRowView:atRow:] ()
#17 0x00007fff22ddbf41 in -[NSTableRowData _initializeRowView:atRow:] ()
#18 0x00007fff22dda3d3 in -[NSTableRowData _preparedRowViewForRow:storageHandler:] ()
#19 0x00007fff22dda21e in -[NSTableRowData _addRowViewForVisibleRow:withPriorView:] ()
#20 0x00007fff22dda034 in -[NSTableRowData _addRowViewForVisibleRow:withPriorRowIndex:inDictionary:withRowAnimation:] ()
#21 0x00007fff22dd8f2a in -[NSTableRowData _updateVisibleRowEntries] ()
#22 0x00007fff236dedbb in __59-[NSTableRowData _automaticRowHeightsUpdateVisibleRowViews]_block_invoke.1371 ()
#23 0x00007fff22fff21b in -[NSTableRowData _keepTopRowStable:andDoWorkUntilDone:] ()
#24 0x00007fff22ffeff8 in -[NSTableRowData _automaticRowHeightsUpdateVisibleRowViews] ()
#25 0x00007fff22dd8873 in -[NSTableRowData updateVisibleRowViews] ()
#26 0x00007fff22f089da in -[NSTableRowData prepareContentInRect:] ()
#27 0x00007fff22f0896f in -[NSTableView prepareContentInRect:] ()
#28 0x00007fff22f086d6 in __38-[NSView _pullInExtraTilesForOverdraw]_block_invoke ()
#29 0x00007fff22f07fd2 in -[NSView _performWorkOnTilesFromRect:renderedContentRect:maximumRect:scrollVelocity:handler:] ()
#30 0x00007fff22f07767 in -[NSView _pullInExtraTilesForOverdraw] ()
#31 0x00007fff22f073ef in -[NSView _doIdlePrefetch] ()
Can anyone comment on how to decipher this crash?
Hi,
I want to install macOS Catalina on a partition on my computer's hard drive to test and fix some bugs for my Mac app. I can't seem to find a simple way to download the installer. I found a link to the Catalina page on the Mac App Store through some other website, but when I try to download it, I get an error saying "This copy of the macOS Catalina installer application is too old to be opened on this version of macOS".
I've checked the Downloads page from the developer page, and it's not listed there either. What gives? Shouldn't be easier to test Mac apps on older versions?
FWIW I'm trying this on a MacBook Pro 2016.
Hi,
I am working on a widget for my existing Mac app. The problem I am running into is that when I add a Link from the widget to the main app, the method 'openURLs' isn't called at all:
- (void) application: (NSApplication *)application openURLs:(NSArray<NSURL *> *)urls
So I'm not able to direct the app on how to best handle the widget tap.
I'm trying to work around that by trying to detect if a Link was selected. Something like this could work
Link("Test", destination: URL(string: "https://duckduckgo.com")!)
.environment(\.openURL, OpenURLAction { url in
print("---> testing link actioned")
return .systemAction
})
When I add this to the main app, it works fine. But when I add something like this to the widget, the completion handler isn't called (supposedly).
Can someone confirm if this was supposed to work inside a widget? Or is it only something that works from the main app?
I'm confused about this ... the MailKit headers files seem to suggest that MailKit APIs are available for iOS16 now. But I haven't seen any documentation mention it, and you can't create a MailKit extension for iOS (using Xcode 14) like you can with macOS. So is it available to use in iOS or not? If so, how do we create an iOS target for the MailKit extension?
Hi,
I want to work with some of the new iOS16 APIs while maintaining backward compatibility with iOS15 as well as Xcode 13. I'm running into a problem here that I can't seem to store the new iOS16 API as a property of an existing class.
For e.g. I'm interested in using the new DataScannerViewController and want to store it as a property so I can reference it when scanning. If I declare it in my ViewController:
var dataScanner: DataScannerViewController?
it won't compile with Xcode13. I can't seem to also mark this with @available or #available(iOS 16) either:
if #available(iOS 16, *) {
var dataScanner: DataScannerViewController?
}
What's the best way to handle this? In Objective-C, we could use __IPHONE_OS_VERSION_MIN_REQUIRED or something to that effect to avoid this problem, but I'm not sure what the best Swift solution is.
I recently had to make a change to my Mac app where I need to add a special "Contact Notes" entitlement, so that means that I can't rely on "Automatic Code Signing" anymore. So here are the steps I took to build and distribute the app with manual code signing:
from "Certificates, Identifiers & Profiles" from the Developer, I added entitlement to my app identifier, and then created new manual provisioning profiles (one for "macOS App Development" under Development, and one for "Mac App Store" under Distribution)
in Xcode, added the entitlement to the Entitlements files
in Xcode, in Signing & Capabilities, unselected the checkbox for "Automatically manage signing", and under "Provisioning Profile", for both Debug and Release builds, I chose to import the new provisioning profiles that were created
I can build and run in debug mode, and it works fine. I then created an 'archive' of the app, which also built fine, and opened up Organizer.
In Organizer, I choose the "Distribute" button, select "App Store Connect" as the distribution method, and choose "Upload" as the destination. After it prepares the archive, it shows the usual two checkboxes for "upload app symbols" and "manage version and build number", and I select Next.
Till now, everything works as expected.
Now I get the "Select certificates and Mac App Store profiles" page ... here, for the dropdowns for my app's targets, I select the correct provisioning profiles. BUT .. the "Next" button never next gets enabled, so I can't move forward! There's no error message, or anything in Console that makes sense to me. But I just can't seem to be able to select "Next" to the final step before uploading the build to App Store Connect.
When I went back and selected "Automatically manage signing" again, and build and archive, the new archive doesn't have this step again, so it works fine and goes to the final upload page.
What can I do to find out the issue that's causing this page to not validate? Can I upload the archive build through some other way (like from Terminal) that might give more information?
NEVERMIND: turns out, I needed to "Mac Installer Distribution" Certificate, which I generated from the dropbox.
I want to test my UNUserNotificationCenter authorization workflow for my MacOS app. I can't seem to find a way to reset the authorization status to notDetermined again. tccutil doesn't seem to contain any options for this. Any suggestions?
Hi,
I have a paid macOS app available in the Mac App Store for the past few years, and I'm looking into converting it into a freemium app. I wanted to add a check to see if the app was purchased legitimately or not, since I know there's a lot of pirated copies available on the internet.
I just did some basic analytics with the app already on the store, the app receipt validation fails because there's no file found at the receipt URL location. I'm just doing this basic check and it fails for a lot of the cases ....
NSURL *receiptURL = [NSBundle mainBundle].appStoreReceiptURL;
BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:receiptURL.path isDirectory:nil];
Does this signify that the user has a non-AppStore copy of the app? Or could the receipt be missing for other legitimate reasons? Do I have to make a call to refresh the receipt to confirm this (as I would on iOS)?
Again, this is for an existing app on the Mac App Store, not testing for sandbox users.
Thanks.
Topic:
App & System Services
SubTopic:
Core OS
Tags:
macOS
Mac App Store
App Store Receipts
StoreKit
Hi,
I am working on distributing a 'framework' I made to a client. The framework itself has a couple of dependencies on a couple of 3rd-party frameworks. Also, I don't want to disclose my source code to the client.
So after doing some research, it seems like the best way to do this would be to use Swift Packages, and make it a binary distribution, which would basically wrap a .xcframework (which I would generate with my source code). But I'm confused about the next steps ... how would I go about sharing the 'package' with the client? Would I just zip up the 'package' folder and email it to them, and they can unzip it on their end, and add it to their project by using "Add local package"? Or is there a more elegant way to do this, which doesn't require publishing a package publicly?
I am trying to create a Swift Package for a custom framework I'm building for a client. The framework has a dependency on a couple of 3rd party frameworks. I've read about how even though binary frameworks don't support dependencies directly, there is way to do this with a 'wrapper' target, so this is what I came up with for Package.swift:
let package = Package(
name: "SBCardScannerFramework",
platforms: [
.iOS(.v16)
],
products: [
// Products define the executables and libraries a package produces, and make them visible to other packages.
.library(
name: "SBCardScannerFramework",
targets: ["SBCardScannerFramework-Target"]),
],
dependencies: [
// Dependencies declare other packages that this package depends on.
.package(url: "https://github.com/apple/swift-algorithms.git", from: "1.0.0"),
.package(url: "https://github.com/marmelroy/PhoneNumberKit.git", from: "3.3.3")
],
targets: [
.target(name: "SBCardScannerFramework-Target",
dependencies: [
.target(name: "SBCardScannerFramework", condition: .when(platforms: [.iOS])),
.product(name: "Algorithms", package: "swift-algorithms"),
.product(name: "PhoneNumberKit", package: "PhoneNumberKit")
]
),
.binaryTarget(name: "SBCardScannerFramework", path: "SBCardScannerFramework.xcframework")
]
)
This works, and I can add the package to my test project and import the framework and it links against the dependancies as well, and works correctly.
The problem is that every time I run the app, it also shows these messages in the Xcode console:
objc[845]: Class _TtC14PhoneNumberKitP33_0FE53357E470A64027C8F0CAF7B114C812BundleFinder is implemented in both /private/var/containers/Bundle/Application/EEE0C0A6-4FF5-44BC-B81A-F95401219D32/TestSBCardScannerFrameworkImport.app/Frameworks/SBCardScannerFramework.framework/SBCardScannerFramework (0x100f4aaf0) and /private/var/containers/Bundle/Application/EEE0C0A6-4FF5-44BC-B81A-F95401219D32/TestSBCardScannerFrameworkImport.app/TestSBCardScannerFrameworkImport (0x10069b778). One of the two will be used. Which one is undefined.
There's multiple lines for different classes that show the "Class X is implemented in both [.../MyApp.app/Frameworks/MyFramework.frameworkMyFramework/] and [.../MyApp.app/MyApp]". I'm not sure how to avoid this problem, and whether this could cause a problem down the line. The framework that is the basis for this Swift Package is linked against the two dependencies, because I wouldn't be able to build the framework without them. But they also need to be added to the app target (at least, and if I don't, I get a run-time crash when using the PhoneNumberKit initializer.
PhoneNumberKit/resource_bundle_accessor.swift:40: Fatal error: unable to find bundle named PhoneNumberKit_PhoneNumberKit
Is there a good way to resolve this issue? I'm worried this will could be a problem for the client when they integrate it into their app, and the app is deployed to 1000s of devices.
Hi,
I have a few extensions for my iOS app: Share Extension, Widget extensions, Notification Extensions, Today Extension, WatchKit app. My app and all the extensions share data by loading the same Core Data sqlite database from a shared folder. One problem I'm having with this setup is with a Core Data lightweight migration. On updating the app to the new database model, I would like my main app to first make a backup of the database before the migration runs. But one of the app extensions always seems to run before the main app, and ends up performing the lightweight migration on the database file before the main app has a chance to backup the database sqlite file.
I can just prevent the lightweight migration from happening when an app extension loads the persistent store (and only do lightweight migrations from the main app), but it might end up in a situation with incompatible formats for the extension, so I'm looking for a sturdier solution.
When an app is installed (or an update to the app is installed), is there a way to check and control the order of the extensions that is installed / loaded by the system? That would help control the problem.
Hi,
I am building a List with a list of files saved in my app. I also want this to accept drops of multiple types of files (images, audio, PDFs, Excel, Pages etc) ... basically anything that be dragged-and-dropped from the iOS system or apps like Mail, iCloud Drive etc. I'm trying to find a good way to handle this.
The best I've come across is adding the onInsert option to accept UTTypes, like this:
List {
...
}
.onInsert(of: [UTType.data], perform: dropAction)
But now I'm not sure how I can load the object that was dropped here. From some examples I've seen, If I registered the UTType.image instead, I could load it in the dropAction handler like this:
item.loadObject(ofClass: UIImage.self) { image, _ in
DispatchQueue.main.async {
print("Image type dropped")
}
}
But how does that work for 'data' types. Or am I supposed to list out all the data types separately?