Post

Replies

Boosts

Views

Activity

Top status bar show/ hide animation is broken in iOS 15
I have the following top status bar hide/ show code snippet with animation. It works well under iOS 14.5 private var additionalHeight: CGFloat { if UIDevice.current.hasNotch { return 0 } else { return self.navigationController?.view.safeAreaInsets.top ?? 0 } } private var statusBarHidden: Bool = false { didSet { if statusBarHidden { self.navigationController?.additionalSafeAreaInsets.top = additionalHeight } else { self.navigationController?.additionalSafeAreaInsets.top = 0 } UIView.animate(withDuration: Constants.config_shortAnimTime) { () -> Void in self.setNeedsStatusBarAppearanceUpdate() } } } // https://medium.com/@badlands/unfortunately-this-also-applies-to-ipad-pro-which-have-non-zero-safeareainsets-e1aa0d002462 extension UIDevice { /// Returns 'true' if the current device has a notch var hasNotch: Bool { if #available(iOS 11.0, *) { // https://stackoverflow.com/a/57899013/72437 let keyWindow = UIWindow.key // Case 1: Portrait && top safe area inset >= 44 let case1 = !UIDevice.current.orientation.isLandscape && (keyWindow?.safeAreaInsets.top ?? 0) >= 44 // Case 2: Lanscape && left/right safe area inset > 0 let case2 = UIDevice.current.orientation.isLandscape && ((keyWindow?.safeAreaInsets.left ?? 0) > 0 || (keyWindow?.safeAreaInsets.right ?? 0) > 0) return case1 || case2 } else { // Fallback on earlier versions return false } } } iOS 14.5 However, when same code runs in iOS 15, the animation is broken. We use latest XCode 13.0 During hide, there is no more "slide up" hide animation. During show, it will try to "push down" the entire view controller. iOS 15 Does anyone has idea how to fix such animation in iOS 15, so that it behaves similar as iOS 14.5 ?
0
0
646
Oct ’21
Why I am getting Multithreading_Violation_AllThatIsLeftToUsIsHonor for this simplest NSAsynchronousFetchRequest use case?
I want to start learning to use NSAsynchronousFetchRequest by referring to  https://www.marcosantadev.com/coredata_crud_concurrency_swift_2/ I have the simplest use case of NSAsynchronousFetchRequest NSAsynchronousFetchRequest // Call from UI main thread func X() { let fetchRequest = NSFetchRequest<NSPlainNote>(entityName: "NSPlainNote") let asynchronousFetchRequest = NSAsynchronousFetchRequest(fetchRequest: fetchRequest) { asynchronousFetchResult in guard let result = asynchronousFetchResult.finalResult as? [NSPlainNote] else { return } } let coreDataStack = CoreDataStack.INSTANCE // backgroundContext created via persistentContainer.newBackgroundContext() let backgroundContext = coreDataStack.backgroundContext backgroundContext.perform { do { try backgroundContext.execute(asynchronousFetchRequest) } catch let error { backgroundContext.rollback() error_log(error) } } } However, running the above code will get me the following error CoreData`+[NSManagedObjectContextMultithreading_Violation_AllThatIsLeftToUsIsHonor]: If I modify the code by using NSFetchRequest directly. NSFetchRequest // Call from UI main thread func X() { let fetchRequest = NSFetchRequest<NSPlainNote>(entityName: "NSPlainNote") let coreDataStack = CoreDataStack.INSTANCE // backgroundContext created via persistentContainer.newBackgroundContext() let backgroundContext = coreDataStack.backgroundContext backgroundContext.perform { do { let nsPlainNotes = try fetchRequest.execute() } catch let error { backgroundContext.rollback() error_log(error) } } } Thing works fine. May I know, what's wrong with my NSAsynchronousFetchRequest version of code? This is my CoreDataStack.swift for reference purpose. CoreDataStack.swift import CoreData class CoreDataStack { static let INSTANCE = CoreDataStack() private init() { } private(set) lazy var persistentContainer: NSPersistentContainer = { let container = NSPersistentContainer(name: "wenote") container.loadPersistentStores(completionHandler: { (storeDescription, error) in if let error = error as NSError? { // This is a serious fatal error. We will just simply terminate the app, rather than using error_log. fatalError("Unresolved error \(error), \(error.userInfo)") } }) // So that when backgroundContext write to persistent store, container.viewContext will retrieve update from // persistent store. container.viewContext.automaticallyMergesChangesFromParent = true // TODO: Not sure these are required... // //container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy //container.viewContext.undoManager = nil //container.viewContext.shouldDeleteInaccessibleFaults = true return container }() private(set) lazy var backgroundContext: NSManagedObjectContext = { let backgroundContext = persistentContainer.newBackgroundContext() // Similar behavior as Android's Room OnConflictStrategy.REPLACE backgroundContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy // TODO: Not sure these are required... //backgroundContext.undoManager = nil return backgroundContext }() } Additional information Do note that, in NSAsynchronousFetchRequest example, even if backgroundContext.perform is not used. // Call from UI main thread func X() { let fetchRequest = NSFetchRequest<NSPlainNote>(entityName: "NSPlainNote") let asynchronousFetchRequest = NSAsynchronousFetchRequest(fetchRequest: fetchRequest) { asynchronousFetchResult in guard let result = asynchronousFetchResult.finalResult as? [NSPlainNote] else { return } } let coreDataStack = CoreDataStack.INSTANCE // backgroundContext created via persistentContainer.newBackgroundContext() let backgroundContext = coreDataStack.backgroundContext do { try backgroundContext.execute(asynchronousFetchRequest) } catch let error { backgroundContext.rollback() error_log(error) } } Same fatal error still occur. Please note that, this fatal error will only be triggered, by editing the schema with Arguments Passed On Launch -com.apple.CoreData.ConcurrencyDebug 1 I even try to execute some simple project from  https://github.com/abhishekbedi1432/Core-Data-Asynchronous-Fetching/tree/master which is using NSAsynchronousFetchRequest. If I do not enable -com.apple.CoreData.ConcurrencyDebug 1, the sample project from github able to perform asynchronous fetch without issue. However, once the -com.apple.CoreData.ConcurrencyDebug 1 is enabled, it will also be getting the same fatal error.
0
0
777
Dec ’21
Asynchronous read in CoreData - Difference in using newBackgroundContext + FetchRequest vs newBackgroundContext + NSAsynchronousFetchRequest?
It seems there are 2 ways to perform asynchronous read in CoreData, without blocking main thread UI. newBackgroundContext + FetchRequest Source : https://www.advancedswift.com/core-data-background-fetch-save-create/ // Create a new background managed object context let context = persistentContainer.newBackgroundContext() // If needed, ensure the background context stays // up to date with changes from the parent context.automaticallyMergesChangesFromParent = true // Perform operations on the background context // asynchronously context.perform { do { // Create a fetch request let fetchRequest: NSFetchRequest<CustomEntity> fetchRequest = CustomEntity.fetchRequest() fetchRequest.fetchLimit = 1 let objects = try context.fetch(fetchRequest) // Handle fetched objects } catch let error { // Handle error } } newBackgroundContext + NSAsynchronousFetchRequest Source: https://www.marcosantadev.com/coredata_crud_concurrency_swift_2/ let privateManagedObjectContext = persistentContainer.newBackgroundContext() // Creates a fetch request to get all the dogs saved let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Dog") // Creates `asynchronousFetchRequest` with the fetch request and the completion closure let asynchronousFetchRequest = NSAsynchronousFetchRequest(fetchRequest: fetchRequest) { asynchronousFetchResult in // Retrieves an array of dogs from the fetch result `finalResult` guard let result = asynchronousFetchResult.finalResult as? [Dog] else { return } // Dispatches to use the data in the main queue DispatchQueue.main.async { // Do something } } do { // Executes `asynchronousFetchRequest` try privateManagedObjectContext.execute(asynchronousFetchRequest) } catch let error { print("NSAsynchronousFetchRequest error: \(error)") } However, note that, the above code will unfortunately cause fatal error, if I were to enable flag -com.apple.CoreData.ConcurrencyDebug 1. So far, I do not have a good solution to such. For more detail, please refer to https://developer.apple.com/forums/thread/697718 ? May I know, what is the difference among newBackgroundContext + FetchRequest vs newBackgroundContext + NSAsynchronousFetchRequest? How should I choose one over another? Thank you.
0
0
1.6k
Dec ’21
Is using CoreData + CloudKit to store text notes, and iCloud Document to store note image attachments as image files a good design approach?
Is using CoreData + CloudKit to store text notes and iCloud Document to store note image attachments as image files a good design approach? Currently, I have almost finished implementing the app to store text notes as Core Data and note image attachments as image files. I like to provide iCloud storage support to the app. I come across a few app examples https://www.raywenderlich.com/13219461-getting-started-with-core-data-and-cloudkit https://developer.apple.com/documentation/coredata/synchronizing_a_local_store_to_the_cloud Both examples are using CoreData + CloudKit to store the image as SQLite blob binary data which CoreData will perform such task automatically) I'm aware that when storing the binary image into CoreData, CoreData is smart enough to choose either to store it as a binary blob in SQLite, or an external file. However, I am a little skeptical about such an approach We are using Kingfisher for smooth image loading in the collection view. If the image data are not in a regular flat-file, how can we integrate CoreData's blob data with Kingfisher? Storing images in CoreData seems like a black box. If something goes wrong in between, it is hard to debug where and how goes wrong. We like to provide alternative cloud storage (using cloud S3 storage to store SQLite files and multiple images) for the app. So, saving the image as flat files will make such an effort easier. Some related discussion on storing the image in DB vs flat files - https://stackoverflow.com/questions/3748/storing-images-in-db-yea-or-nay I would prefer Only use CoreData + CloudKit to store the text note and file path. The image file will store in both the app folder and the iCloud document folder (so that it syncs seamlessly to iCloud). If the required images are not in the app folder (App uninstall, then re-install), the app will try to copy the image file from the iCloud document I was wondering, anyone of you has tried such a design in your app? Do you find it is a good approach based on your experience? Thanks.
2
0
1.1k
Apr ’22
Why we need to use NSPersistentHistoryTransaction if NSFetchedResultController able to update UI correctly?
I still fail to understand, what is the problem NSPersistentHistoryTransaction is trying to solve, in the CoreDataCloudKitDemo WWDC 2019 "Using Core Data with CloudKit" https://github.com/software123inc/CoreDataCloudKitDemo/blob/master/CoreDataCloudKitDemo/DataProvider/CoreDataStack.swift#L161 I want to see, what problem will occur, if processPersistentHistory is not executed. By making the processPersistentHistory empty, I try to do the following testing. Run 2 simulators simultaneously in the same machine. Add an item to simulator A. Since, there is no way for simulator B to receive push notification, I press the home button for simulator B. In simulator B, I tap on the app icon to launch the app again. In simulator B, I can observe controllerDidChangeContent is being called. My guess is that, because the backed SQLite is seamlessly updated by CloudKit background task, NSFetchedResultController will be notified the SQLite DB change, and subsequently update the UI. Check the "Download CloudKit Changes into Core Data" of https://developer.apple.com/documentation/coredata/mirroring_a_core_data_store_with_cloudkit/syncing_a_core_data_store_with_cloudkit In simulator B, due to controllerDidChangeContent is being triggered correctly, I can observe the UI change perform by NSFetchResultController without issue. Hence, I am not clear, on what problem processPersistentHistory is trying to solve in the demo code. May I know what kind of test case I can perform, to understand the problem solved by processPersistentHistory? Based on "Integrate Store Changes Relevant to the Current View" https://developer.apple.com/documentation/coredata/mirroring_a_core_data_store_with_cloudkit/syncing_a_core_data_store_with_cloudkit Your app receives remote change notifications when the local store updates from CloudKit. However, it’s unnecessary to update your UI in response to every notification, because some changes may not be relevant to the current view. Analyze the persistent history to determine whether the changes are relevant to the current view before consuming them in the user interface. Inspect the details of each transaction, such as the entity name, its updated properties, and the type of change, to decide whether to act. For more information about persistent history tracking, see Consuming Relevant Store Changes. This part is getting confusing. Our NSFetchedResultController is receiving relevant entity change event due to SQLite, and subsequently able to update the UI correct. If that is so, why do we still need persistent history?
1
0
401
Apr ’22
Does anyone know where I can get an official StoreKit 1 example code from Apple?
We wish to implement in-app purchase for our app, which is currently targeting 14.3 The latest StoreKit 2, is only available for iOS 15 We wish to study how should we implement such, by looking at official code example of StoreKit 1. However, the current posted code at Apple site, is only available for StoreKit 2 - https://developer.apple.com/documentation/storekit/in-app_purchase/implementing_a_store_in_your_app_using_the_storekit_api Does anyone have any idea, where can I get the official StoreKit 1 code example, from Apple? Thanks.
0
0
312
Apr ’22
Is there a way to update supplementary view efficiently, analogy to update items efficiently using reconfigureItems?
In iOS15, we have an efficient way to update items cell, by using reconfigureItems. Here's the code snippet to perform such efficient update. Update items cell efficiently using reconfigureItems private func reconfigureRecordingRow(_ recording: Recording) { var snapshot = dataSource.snapshot() snapshot.reconfigureItems([recording]) dataSource.apply(snapshot) } private func makeDataSource() -> DataSource { let dataSource = DataSource( collectionView: collectionView, cellProvider: { [weak self] (collectionView, indexPath, anyHashable) -> UICollectionViewCell? in guard let self = self else { return nil } guard let recordingCell = collectionView.dequeueReusableCell( withReuseIdentifier: "recording", for: indexPath) as? RecordingCell else { return nil } When reconfigureRecordingRow is called, cellProvider's function will be executed. collectionView.dequeueReusableCell is able to re-use existing UICollectionViewCell, without constructing new UICollectionViewCell However, I was wondering, how can I achieve a similar efficiency, if I have a section, with header supplementary view, and without any item? For instance Not able to update supplementary view efficiently private func reloadAttachmentRow() { var snapshot = dataSource.snapshot() let sectionIdentifiers = snapshot.sectionIdentifiers if sectionIdentifiers.contains(.attachment) { snapshot.reloadSections([.attachment]) } else { snapshot.insertSections([.attachment], beforeSection: .title) } dataSource.apply(snapshot) } dataSource.supplementaryViewProvider = { [weak self] collectionView, kind, indexPath in guard let self = self else { return nil } if kind == UICollectionView.elementKindSectionHeader { let section = indexPath.section let sectionIdentifier = self.sectionIdentifier(section) switch sectionIdentifier { case .attachment: guard let collageViewHeader = collectionView.dequeueReusableSupplementaryView( ofKind: kind, withReuseIdentifier: "attachment", for: indexPath) as? CollageViewHeader else { return nil } When reloadSections is called, dataSource.supplementaryViewProvider will be executed. As per my testing, collectionView.dequeueReusableSupplementaryView will return a new instance of UICollectionReusableView each time. As a result, I can visually observe the entire section is "flickering", when reloadAttachmentRow is called. I was wondering, how can we update supplementary view efficiently?
0
0
931
May ’22
Is there a way to know a file is not found in iCloud Document by using NSMetadataQuery and NotificationCenter?
I'm using NSMetadataQuery and NotificationCenter, to perform file downloading from iCloud. Construct NSMetadataQuery with predicate NSPredicate(format: "%K == %@", NSMetadataItemFSNameKey, filename) Observe NSMetadataQueryDidUpdate & NSMetadataQueryDidFinishGathering using NotificationCenter. Check file status NSMetadataUbiquitousItemDownloadingStatusKey. If the file is up-to-date, copy the file to destination directory, and jump to step 6. Perform FileManager.default.startDownloadingUbiquitousItem Receive file downloading status in NSMetadataQueryDidUpdate callback. If the file is up-to-date, copy the file to destination directory, and jump to step 6. Perform cleanup by removing all observers. If file is not available in iCloud, no notification received. We wish, even if the file doesn't exist, we will still be notified, so that we have chance to perform cleanup (step 6) Here's the code snippet to perform iCloud download. DownloadManager.swift class DownloadManager { static let INSTANCE = DownloadManager() var downloaders = [iCloudDocumentDownloader]() private init() { } func append(filename: String, destinationDirectory: URL) { let downloader = iCloudDocumentDownloader(filename: filename, destinationDirectory: destinationDirectory) downloaders.append(downloader) } func removeAll(_ downloader: iCloudDocumentDownloader) { downloaders.removeAll{$0 === downloader} } } iCloudDocumentDownloader.swift class iCloudDocumentDownloader { private let filename: String private let destinationDirectory: URL private let metadataQuery = NSMetadataQuery() private static let operationQueue: OperationQueue = { let operationQueue = OperationQueue() operationQueue.name = "com.yocto.wenote.operationQueueForiCloudDocument" operationQueue.maxConcurrentOperationCount = 1 operationQueue.qualityOfService = .userInitiated return operationQueue }() deinit { NotificationCenter.default.removeObserver(self) } private func bye() { DownloadManager.INSTANCE.removeAll(self) } init(filename: String, destinationDirectory: URL) { self.filename = filename self.destinationDirectory = destinationDirectory metadataQuery.operationQueue = iCloudDocumentDownloader.operationQueue metadataQuery.predicate = NSPredicate(format: "%K == %@", NSMetadataItemFSNameKey, filename) metadataQuery.searchScopes = [ NSMetadataQueryUbiquitousDocumentsScope ] NotificationCenter.default.addObserver(self, selector: #selector(didUpdate), name: NSNotification.Name.NSMetadataQueryDidUpdate, object: metadataQuery) NotificationCenter.default.addObserver(self, selector: #selector(didFinishGathering), name: NSNotification.Name.NSMetadataQueryDidFinishGathering, object: metadataQuery) metadataQuery.start() } @objc func didUpdate(_ notification: Notification) { guard let metadataQuery = notification.object as? NSMetadataQuery else { return } metadataQuery.enumerateResults { [weak self] (item: Any, index: Int, stop: UnsafeMutablePointer<ObjCBool>) in guard let self = self else { return } guard let metadataItem = item as? NSMetadataItem else { return } guard let status = metadataItem.value(forAttribute: NSMetadataUbiquitousItemDownloadingStatusKey) as? String else { return } guard let url = metadataItem.value(forAttribute: NSMetadataItemURLKey) as? URL else { return } if status == NSMetadataUbiquitousItemDownloadingStatusCurrent { if !destinationDirectory.createCompleteDirectoryHierarchyIfDoesNotExist() { self.bye() // Early return. return } let destinationURL = destinationDirectory.appendingPathComponent(filename, isDirectory: false) do { try FileManager.default.copyItem(at: url, to: destinationURL) } catch { error_log(error) } self.bye() } else if let error = metadataItem.value(forAttribute: NSMetadataUbiquitousItemDownloadingErrorKey) as? NSError { error_log(error) self.bye() } else { } } } @objc func didFinishGathering(_ notification: Notification) { guard let metadataQuery = notification.object as? NSMetadataQuery else { return } metadataQuery.enumerateResults { [weak self] (item: Any, index: Int, stop: UnsafeMutablePointer<ObjCBool>) in guard let self = self else { return } guard let metadataItem = item as? NSMetadataItem else { return } guard let status = metadataItem.value(forAttribute: NSMetadataUbiquitousItemDownloadingStatusKey) as? String else { return } guard let url = metadataItem.value(forAttribute: NSMetadataItemURLKey) as? URL else { return } if status == NSMetadataUbiquitousItemDownloadingStatusCurrent { if !destinationDirectory.createCompleteDirectoryHierarchyIfDoesNotExist() { self.bye() // Early return. return } let destinationURL = destinationDirectory.appendingPathComponent(filename, isDirectory: false) do { try FileManager.default.copyItem(at: url, to: destinationURL) } catch { error_log(error) } self.bye() } else if let error = metadataItem.value(forAttribute: NSMetadataUbiquitousItemDownloadingErrorKey) as? NSError { error_log(error) self.bye() } else { do { try FileManager.default.startDownloadingUbiquitousItem(at: url) } catch { error_log(error) self.bye() } } } } }
0
0
1.3k
Jun ’22
How should we handle history tracking transactions purging, if we allow users to enable/ disable CloudKit sync?
Due to privacy concern, we wish to provide a toggle switch, so that user has the freedom, to choose whether to sync CoreData with iCloud. We can implement such a feature by following suggestion from https://developer.apple.com/forums/thread/118924?login=true However, we should not perform history tracking transactions purging, once user disables CloudKit sync Reason is that, if few months later/ few years later, user decides to turn on CloudKit sync again, lack of sufficient history tracking transactions, will cause CloudKit sync fail. This is causing a dilemma. If we never clean the history tracking transactions, will it cause disk full issue? If that is so, may I know, what is the correct way to handle history tracking transactions purging, if we allow users to enable/ disable CloudKit sync? Thank you.
0
0
724
Jun ’22
PHPickerConfiguration will produce wrong ordering sometimes during multi selection.
We notice PHPickerConfiguration will produce wrong ordering sometimes, during multi selection. Our app is targeting iOS 15, and the test is run on simulator iOS 15.5 Here the video to demonstrate the issue https://youtu.be/RrhqFuB2kqs Please note that, the standing cat picture suppose to be the 4th order. By looking at the console and UI outcome, it is mistakenly returned as 3rd order. Here's the code which show func chooseImage() { var configuration = PHPickerConfiguration() configuration.selectionLimit = 0 // https://developer.apple.com/documentation/photokit/phpickerconfiguration/selection configuration.selection = .ordered // GIF exclusion is still not supported - https://developer.apple.com/forums/thread/687415 configuration.filter = .images let picker = PHPickerViewController(configuration: configuration) picker.delegate = self present(picker, animated: true) } and here's the code which prints out the ordering of images. extension NewNoteViewController: PHPickerViewControllerDelegate { func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) { picker.dismiss(animated: true) guard !results.isEmpty else { return } var displayErrorOnce = false for result in results { result.itemProvider.loadFileRepresentation(forTypeIdentifier: UTType.image.identifier) { [weak self] (url, error) in precondition(!Thread.isMainThread) guard let self = self else { return } guard let url = url else { return } print(">>>> url \(url)") // ... } } } } This problem happens randomly. May I know, is there any workaround for this issue? Thank you.
Topic: UI Frameworks SubTopic: UIKit Tags:
0
0
655
Aug ’22
Can anyone share your experience in migrating CloudKit enabled CoreData to AppGroup to support Widget?
Our current app is using CloudKit enabled CoreData. Recently, we want to support Widget feature. We understand that in order to support Widget feature, we need to place our CoreData under AppGroup, so that the data can be accessed by Widget. May I know, is there any good guideline on how to do so, so that we would not cause data loss for existing users? Thank you.
0
0
600
Sep ’22
CoreData generated class - Is there memory leak risk of not using weak in inverse relationship?
When come to circular reference, it comes with risk of memory leaking, by not using a weakkeyword. For instance :- Memory leak without using weak class Human { deinit { print("bye bye from Human") } init(_ pet: Pet) { self.pet = pet } let pet: Pet } class Pet { deinit { print("bye bye from Pet") } var human: Human? } print("start of scope") if true { let pet = Pet() let human = Human(pet) pet.human = human print("going to end of scope") } print("end of scope") /* Output: start of scope going to end of scope end of scope */ No memory leak by using weak class Human { deinit { print("bye bye from Human") } init(_ pet: Pet) { self.pet = pet } let pet: Pet } class Pet { deinit { print("bye bye from Pet") } weak var human: Human? } print("start of scope") if true { let pet = Pet() let human = Human(pet) pet.human = human print("going to end of scope") } print("end of scope") /* Output: start of scope going to end of scope bye bye from Human bye bye from Pet end of scope */ In CoreData, when setup 2 entities with one-to-many relationship, it is recommended to have inverse relationship too. Hence, CoreData will generate the following class with circular reference. extension NSHolidayCountry { @nonobjc public class func fetchRequest() -> NSFetchRequest<NSHolidayCountry> { return NSFetchRequest<NSHolidayCountry>(entityName: "NSHolidayCountry") } @NSManaged public var code: String @NSManaged public var name: String @NSManaged public var holidaySubdivisions: NSOrderedSet } extension NSHolidaySubdivision { @nonobjc public class func fetchRequest() -> NSFetchRequest<NSHolidaySubdivision> { return NSFetchRequest<NSHolidaySubdivision>(entityName: "NSHolidaySubdivision") } @NSManaged public var code: String @NSManaged public var name: String @NSManaged public var holidayCountry: NSHolidayCountry? } NSHolidaySubdivision is having inverse relationship to NSHolidayCountry. However, such inverse relationship is not marked as weak, based on CoreData generated class. I was wondering, does this come with a memory leak risk? Should I, add a weak keyword manually in entity NSHolidaySubdivision's holidayCountry ?
0
0
685
Sep ’22
Why the show/ hide table view mechanism doesn't work in non iPhone SE simulator?
I am using the following mechanism, to perform UITableView's row show and hide. class TableViewController: UITableViewController { private var hiddenIndexPaths : Set<IndexPath> = [] override func viewDidLoad() { super.viewDidLoad() } @IBAction func toggle(_ sender: UISwitch) { if sender.isOn { show(1) show(2) } else { hide(1) hide(2) } tableView.beginUpdates() tableView.endUpdates() } private func isHidden(_ indexPath: IndexPath) -> Bool { hiddenIndexPaths.contains(indexPath) } private func hide(_ item: Int) { hiddenIndexPaths.insert(IndexPath(item: item, section: 0)) } private func show(_ item: Int) { hiddenIndexPaths.remove(IndexPath(item: item, section: 0)) } override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { if isHidden(indexPath) { return 0.0 } return super.tableView(tableView, heightForRowAt: indexPath) } } As you can see, it works great in iPhone SE simulator (Works well in iPhone SE real device too) iPhone SE simulator linkText However, in non iPhone SE simulator (Like iPhone 13), once the table row is hidden, it can no longer be shown. Please refer to the following video. iPhone 13 simulator I am not sure what will its behavior in iPhone 13 real device, because I do not have access. I was wondering, do you have any idea why such issue occurs? If you are interested to test, here's the complete workable sample - https://github.com/yccheok/show-hide-table-row-bug
Topic: UI Frameworks SubTopic: UIKit Tags:
4
0
1.1k
Sep ’22
Is there any static analysis tool which can help us detect memory leak cause by missing [weak self]?
I was wondering, is there any tool, which can help to detect memory leak caused by missing [weak self]. For instance, the following code contains memory leak issue caused by lack of [weak self] class ImagePageViewController: UIPageViewController { lazy var memoryLeak = UIAction( title: "memory_leak", image: nil ) { _ in print(">>>> \(self)") } } Is there any tool which can help us to prevent such issue? I have tried  https://github.com/realm/SwiftLint but it is not able to detect such.
1
0
696
Sep ’22
How to avoid CoreData corruption when developing Share extension to CoreData in AppGroup?
We plan to develop a Share extension. The CoreData is storing its SQLite file in AppGroup folder. The share extension will run in a different process than main app's. Since share extension and main app are running in different process, both will have their own instance of CoreData. However, even there are multiple instances of CoreData in different processes, their underlying are pointing to a single same SQLite file. Under https://developer.apple.com/library/archive/documentation/General/Conceptual/ExtensibilityPG/ExtensionScenarios.html#//apple_ref/doc/uid/TP40014214-CH21-SW1 It mentions When you set up a shared container, the containing app—and each contained app extension that you allow to participate in data sharing—have read and write access to the shared container. To avoid data corruption, you must synchronize data accesses. Use Core Data, SQLite, or Posix locks to help coordinate data access in a shared container. But it isn't clear, what are detailed steps required to How can we synchronize access to CoreData among 2 processes? Who should responsible to consume relevant store change, and update the single token file? (https://developer.apple.com/documentation/coredata/consuming_relevant_store_changes) Should it be main app, share extension or both? Thank you.
1
0
894
Nov ’22