Post

Replies

Boosts

Views

Activity

Reply to UITableViewDiffableDataSource apply snapshot crashes on iOS 17
Where is DispatchQueue.main.async being called from? What object is self (a view controller or some other object)? And the controller has deallocated before it. Are you saying that the view controller has been deallocated before the table view it displays? Sounds like you might have a memory leak. You can use the memory graph debugger to try to reproduce and/or Instruments. I'd check for unintentional strong references to the table view. References in blocks is a place I'd look for first but it could be something else. It's easy to create a retain cycle using blocked based APIs. Swipe gesture action blocks, context menu action blocks, diffable datasource provider blocks, or your own blocks.
Topic: UI Frameworks SubTopic: UIKit Tags:
Jul ’24
Reply to APIs dropped from MacCatalyst SDK without prior deprecation - is this to be expected?
That must've been a nasty surprise. I don't know about you but I got way too much code and time invested to just throw it all in the trash and start using SwiftUI anytime soon. As a workaround you should be able to embed an "AppKit aware" bundle in your Catalyst app? This bundle can call all the public methods an AppKit app can. Load the bundle from the Catalyst app and call whatever public API you want... Something like this... NSURL *appKitAwareBundleURL = [[NSBundle.mainBundle.builtInPlugInsURL URLByAppendingPathComponent:@"NameOfBundle"] URLByAppendingPathExtension:@"bundle"]; NSBundle *appKitBundle = [NSBundle bundleWithURL:appKitAwareBundleURL]; NSError *errorLoadingBundle = nil; if (![appKitBundle loadAndReturnError:&errorLoadingBundle]) { // whoops check error.. return; } Class appKitWorldClass = appKitBundle.principalClass; id <YourProtocolNameHereWrappingAPIsYouNeed>myAppKitWorld = [[appKitWorldClass alloc]init]; self.appKitWrapper = myAppKitWorld; Your principalClass conforms to your protocol you define that wraps whatever API calls you need.
Topic: UI Frameworks SubTopic: UIKit Tags:
Aug ’24
Reply to APIs dropped from MacCatalyst SDK without prior deprecation - is this to be expected?
I hear you but sometimes developers gotta do what they gotta do for their users and themselves. So I was just offering a workaround that should help the developer release an update without having to drastically change the codebase. I don't know about the OP but depending on the complexity of the app it may not be feasible to just throw the whole thing out because of a bug like this and "just wait, maybe we'll fix it" and then play a commercial for SwiftUI. Always appreciate your answers though. They have often been very helpful!
Topic: UI Frameworks SubTopic: UIKit Tags:
Aug ’24
Reply to vImageConverter_CreateWithCGImageFormat Fails with kvImageInvalidImageFormat When Trying to Convert CMYK to RGB
So if I put a breakpoint right after CGImageCreateWithJPEGDataProvider and Quicklook preview sourceCGImage, the CGimageRef rendered in the Quicklook preview in the Xcode debugger is correct. But once I try to pass sourceCGImage to any higher level API it goes black. That includes NSBitmapImageRep, NSImage, CIImage, etc. I also tried creating a bitmap context and drawing the sourceCGImage in the bitmap context, but haven't been able to get that to work. Previewing the sourceCGImage right after CGImageCreateWithJPEGDataProvider from Xcode's debugger when I hit that breakpoint is the only time the image is rendered correctly. I wonder what API is being used to render the CGImage from the Xcode debugger?
Topic: Graphics & Games SubTopic: General Tags:
Sep ’24
Reply to vImageConverter_CreateWithCGImageFormat Fails with kvImageInvalidImageFormat When Trying to Convert CMYK to RGB
To workaround the issue, if I iterate over the pixel data of the CMYK image I'm able to manually convert to RGB and write it into another buffer and create a CGImage with that RGB data. Then I can use CGBitmapContextCreate with the RGB buffer to generate a new image. So there appears to be an issue with how CMYK color space is being handled. Had to take a peek back in the Quartz 2D Programming Guide in the "Documentation Archive" for a refresh on some of these APIs I haven't used in a long time...
Topic: Graphics & Games SubTopic: General Tags:
Sep ’24
Reply to vImageConverter_CreateWithCGImageFormat Fails with kvImageInvalidImageFormat When Trying to Convert CMYK to RGB
I was trying all sorts of different combinations while I was hitting errors. It looks like I messed that up. Changing destination image format to use kCGImageAlphaNone like you've shown with 24 bits per pixel does in fact fix the kvImageInvalidImageFormat problem but when I convert the image I still get a black image after the conversion. I also tied changing destination format to 32 bpp with kCGImageAlphaNoneSkipLast | kCGBitmapByteOrder32Host) but I still get a black CGImageRef from vImageCreateCGImageFromBuffer (though I am able to create a vImageConverter without error). Only thing I've been able to get working is iterating over the pixels and converting to RGB, then make another CGImage like so: CGContextRef context = CGBitmapContextCreate(nowRGBConvertedFromCMYK, sourceWidth, sourceHeight, sourceBitsPerCompontent, // 8 rgbBytesPerRow, rgbColorSpace, // deviceRGB kCGImageAlphaNoneSkipLast | kCGBitmapByteOrderDefault); // Create a new RGB image from the context CGImageRef rgbImage = CGBitmapContextCreateImage(context);
Topic: Graphics & Games SubTopic: General Tags:
Sep ’24
Reply to vImageConverter_CreateWithCGImageFormat Fails with kvImageInvalidImageFormat When Trying to Convert CMYK to RGB
Thanks for sharing that code. That Swift code wouldn't compile for me. I'm using Objective-C in my project but your Swift code doesn't appear like it would produce anything different than the code I'm experimenting with now (unless I'm missing something?): CGImageRef doConvertCMYKCGImageToRGB (CGImageRef sourceImage) { size_t sourceBitsPerComponent = CGImageGetBitsPerComponent(sourceImage); size_t sourceBitsPerPixel = CGImageGetBitsPerPixel(sourceImage); CGColorSpaceRef sourceColorSpace = CGImageGetColorSpace(sourceImage); CGBitmapInfo sourceBitmapInfo = CGImageGetBitmapInfo(sourceImage); CGColorRenderingIntent sourceRenderingIntent = CGImageGetRenderingIntent(sourceImage); const CGFloat *sourceDecode = CGImageGetDecode(sourceImage); vImage_CGImageFormat cmykFormat = { .bitsPerComponent = (uint32_t)sourceBitsPerComponent, // 8 .bitsPerPixel = (uint32_t)sourceBitsPerPixel, // 32 .colorSpace = sourceColorSpace, // (kCGColorSpaceICCBased; kCGColorSpaceModelCMYK; Generic CMYK Profile) .bitmapInfo = sourceBitmapInfo, // kCGBitmapByteOrderDefault .renderingIntent = sourceRenderingIntent, // kCGRenderingIntentDefault .version = 0, .decode = sourceDecode }; vImage_CGImageFormat rgbFormat = { .bitsPerComponent = 8, .bitsPerPixel = 24, .colorSpace = CGColorSpaceCreateDeviceRGB(), .bitmapInfo = (CGBitmapInfo)kCGImageAlphaNone, .renderingIntent = kCGRenderingIntentDefault }; /* Also tried: vImage_CGImageFormat rgbFormat = { .bitsPerComponent = 8, .bitsPerPixel = 32, .colorSpace = CGColorSpaceCreateDeviceRGB(), .bitmapInfo = (CGBitmapInfo)kCGImageAlphaNoneSkipLast | kCGBitmapByteOrderDefault, .renderingIntent = kCGRenderingIntentDefault };*/ // Initialize source buffer vImage_Buffer sourceBuffer; // You are responsible for releasing the memory pointed to by buf->data back to the system using free(). vImage_Error error = vImageBuffer_InitWithCGImage( &sourceBuffer, &cmykFormat, NULL, sourceImage, kvImageNoFlags); if (error != kvImageNoError) { os_log_error(OS_LOG_DEFAULT,"Error initializing source buffer: %ld", error); return NULL; } // Initialize destination buffer.. // You are responsible for releasing the memory pointed to by buf->data back to // the system when you are done with it using free(). If no such allocation is desired, pass // * kvImageNoAllocate in the flags to cause buf->data to be set to NULL and the preferred alignment // * to be returned from the left hand side of the function. vImage_Buffer destBuffer; error = vImageBuffer_Init(&destBuffer, sourceBuffer.height, sourceBuffer.width, rgbFormat.bitsPerPixel, kvImageNoFlags); if (error != kvImageNoError) { os_log_error(OS_LOG_DEFAULT,"Error initializing destination buffer: %ld", error); free(sourceBuffer.data); return NULL; } // Create a converter vImageConverterRef cmykToRGBConverter = vImageConverter_CreateWithCGImageFormat(&cmykFormat, &rgbFormat, NULL, kvImageNoFlags, &error); if (cmykToRGBConverter == NULL) { os_log_error(OS_LOG_DEFAULT,"Error creating vImage converter: %ld", error); free(destBuffer.data); // Free destBuffer.data. free(sourceBuffer.data); // Free sourceBuffer.data. return NULL; } // Perform the conversion error = vImageConvert_AnyToAny(cmykToRGBConverter, &sourceBuffer, &destBuffer, NULL, kvImageNoFlags); CGImageRef rgbResult = NULL; if (error == kvImageNoError) { // Create RGB result image rgbResult = vImageCreateCGImageFromBuffer(&destBuffer, &rgbFormat, NULL, NULL, kvImageNoFlags, &error); } else { os_log_error(OS_LOG_DEFAULT,"Error converting image: %ld", error); } // Create CMYK image (not needed)... //CGImageRef cmykImage = vImageCreateCGImageFromBuffer(&sourceBuffer, &cmykFormat, NULL, NULL, kvImageNoFlags, &error); // Clean up vImageConverter_Release(cmykToRGBConverter); free(destBuffer.data); // Free destBuffer.data free(sourceBuffer.data); // Free destBuffer.data return rgbResult; } Using that with image I provided in my feedback as sourceImage produces a black box (same when I pass the image data I provided in my feedback directly to higher level APIs like NSBitmapImageRep).
Topic: Graphics & Games SubTopic: General Tags:
Sep ’24
Reply to Mac App Store Bug Fix Updates Getting Blocked, Reviewer Sending "App Sandbox Design Guide" Broken Link
@App Review @DTS Engineer Thanks for replying. Most of the stuff in App Sandbox Design Guide was migrated to the App Sandbox area of the modern documentation. And if you want to see the old doc, I link to it in App Sandbox Resources. They kept sending me a broken link in the Resolution Center that just redirected. Thanks for sending that link. I do hope relevant information from the documentation will get moved to the new documentation. Especially information that App Review is currently using to evaluate apps, it is important for devs to have access. -- If you disagree with the outcome of our review, I don't want to sound rude but When an app has been on the store for so long (years not months) and it gets rejected for using an "unneeded entitlement"... then I explain why the entitlement is needed and the app goes back into review only to get rejected for completely different reasons with newly interpreted violations and citing references in retired documentation that is no longer accessible... it feels like App Review is trying overtime to keep my update off store. Nobody has ever complained to me about writing files in the sandbox container. I wish Apple provided sandbox apps a folder in a user-facing directory (like iCloud) but this isn't my choice. Although this app didn't get as popular as I was hoping, the app has many positive reviews. People like the app, and they ask me to fix bugs so it is very frustrating when I'm prevented from doing that. The instructions from app review are vague but I'm assuming they want me to show a save panel on launch to get to a starting point somewhere outside of my sandbox container. I'm not sure if this will make my app better. It's working by default vs. a more complicated setup process and this is a tradeoff. And I don't even know if this is exactly what App review is asking me to do. It's only what I think they want. Chasing what I think App Review wants has never worked out in my favor. It isn't going to increase my sales. It isn't clear to me that making these changes will help anyone. It certainly won't help me, having to spend a week or more designing some onboarding. And what do I do with existing users, migrate them out of the container? That's not going to be fun to implement. And maybe they don't want me to nag them in the next update to move a bunch of files around. -- To follow up: the app did go back into review and get approved which I'm thankful for. But it has a sister app with an update that's still being blocked for the same rejection reason. So it's really hard to make sense of what's going on. I think I would be less frustrated if App Review was a bit more clear as to what they want. And if they requested changes without blocking bug fixes.
Sep ’24