Post

Replies

Boosts

Views

Activity

UISheetPresentationController: Remove Dim Background but Keep Touch-to-Dismiss?
I'm using the UISheetPresentationController to present a view, as shown in the following code: @IBAction func click(_ sender: Any) { let whiteViewController = WhiteViewController.instanceFromMainStoryBoard() if let sheet = whiteViewController.sheetPresentationController { sheet.detents = [.medium()] sheet.prefersScrollingExpandsWhenScrolledToEdge = false sheet.prefersGrabberVisible = false // Remove dim effect. ////sheet.largestUndimmedDetentIdentifier = .medium } self.present(whiteViewController, animated: true) } The outcome is as follow This code results in a presentation with: A dimmed background. A 'Touch anywhere to dismiss' behavior. However, I want to remove the dim background while keeping the 'Touch anywhere to dismiss' functionality. When I add the line: sheet.largestUndimmedDetentIdentifier = .medium The dim background is indeed removed, but the touch-to-dismiss behavior is gone too, as illustrated: Is there a way to achieve both – removing the dim background and retaining the touch-to-dismiss functionality? Thank you.
Topic: UI Frameworks SubTopic: UIKit Tags:
1
0
2k
Oct ’23
What are some other actionable items I can do, so that I can get through "Guideline 4.3(a) - Design - Spam" app update rejection?
I have an app which is in the app store since 2022. It is an app with combined features of note taking, todo list and calendar. My most recent app update is rejected with the following message. Guideline 4.3(a) - Design - Spam We noticed your app shares a similar binary, metadata, and/or concept as apps submitted to the App Store by other developers, with only minor differences. Submitting similar or repackaged apps is a form of spam that creates clutter and makes it difficult for users to discover new apps. Next Steps Since we do not accept spam apps on the App Store, we encourage you to review your app concept and submit a unique app with distinct content and functionality. Resources Some factors that contribute to a spam rejection may include: Submitting an app with the same source code or assets as other apps already submitted to the App Store Creating and submitting multiple similar apps using a repackaged app template Purchasing an app template with problematic code from a third party Submitting several similar apps across multiple accounts Learn more about our requirements to prevent spam in App Review Guideline 4.3(a). Support Reply to this message in your preferred language if you need assistance. If you need additional support, use the Contact Us module. Consult with fellow developers and Apple engineers on the Apple Developer Forums. Help improve the review process or identify a need for clarity in our policies by suggesting guideline changes. I reply the reviewer with the following message. Hi, I am writing to appeal the rejection of my app, XXX. I would like to emphasize the unique aspects of XXX that distinguish it from other apps in the market: Integrated Functionality: Unlike most apps that are standalone note-taking, to-do, or calendar apps, XXX uniquely combines all three functions into a single app. Extensive Calendar Features: XXX includes a comprehensive calendar feature covering holidays in 250 countries and 3,680 states and provinces, a rare and valuable feature. Chinese Lunar Calendar: Our app includes a Chinese Lunar Calendar, which is highly appreciated in the Taiwanese market, adding a culturally specific feature not commonly found in other apps. Organizational Tools: XXX allows unlimited tabs and colors for organizing notes, surpassing many competitors who offer limited color options. Flexible Viewing and Sorting Modes: Users can choose from four viewing modes (Grid, Compact Grid, List, Compact List) and five sorting modes (Modified Time, Created Time, Alphabet, Color, Check, Reminder), enhancing the user experience by providing flexibility and customization. No Character Limit: Our design supports notes of any length without character limitations, unlike many apps that impose restrictions. Organized To-Do Lists: Completed to-do items are automatically moved to the bottom, keeping the list clean and organized, a feature that sets us apart from other apps. Rich Attachments: XXX supports unlimited picture attachments, drawing attachments, and voice recordings for notes, offering more versatility than many other apps. Advanced Security: XXX offers 3 different kinds of password lock mechanisms to protect note privacy, ensuring users have multiple options for securing their information. Powerful Reminders: Our app includes highly customizable reminders that can repeat daily, weekly, monthly, or yearly, making it easy for users to stay on top of their tasks and appointments. Due to the character limits of this form, I cannot list all the unique features of XXX. Please refer to our product description for a comprehensive overview. We are proud of our 5k user reviews with an average rating of 4.8, reflecting user satisfaction with XXX's unique features. Here's are some of the recent reviews. (United states only. Please kindly contact me to obtain full list of the reviews) by ??? – Jun 14, 2024 omg i cannot explain how much i love XXX like unlike the boring notes app this one is actually fun to use and rlly easy and i rlly like the fonts, color, to do list, calandar that can remind you like every day, week, month, and year like omg?!?!? i love XXX and this app is going in like my "I 💖U" folder like tysm for making XXX idk what i would do without it like omg tysm i cant explain in words how much i love it💖💖💖💖💖💖💖💖💖💖💖💖💖💖 by ??? – May 12, 2024 I love it sooo much I give it a 5 because there is a password so no one can look by ??? – Apr 30, 2024 Perfect app. All in one by ??? – Mar 26, 2024 I just downloaded this app a few days ago and I love it!! 😃 Up til recently I ALWAYS used paper sticky notes that I would have on my desk - and the reason why is because I could see everything all at once at all times; it’s very convenient - but it also produces clutter and anxiety because every subject is all in one place. XXX fixed that!! 😀 With tabs and the list or grid view mode, I can have more organization of subjects and still see almost everything all at once! I love it! 🤩 suggestion I would really love to have more format options for the text! 🙂 Like a button to indent, and be able to have sub notes with points, dashes, or numbers. It makes everything look more tidy and neat. Thank you for this wonderful app! 😆 I am available at 123-456-789 to discuss further and provide additional detail. Thank you. Till to date, I haven't received reply from the reviewer. May I know, what are some other actionable items I can do, so that I can get through "Guideline 4.3(a) - Design - Spam" app update rejection? Thank you so much!
1
0
1.2k
Aug ’24
In-App Purchase Review Delaying App Release - Next Steps?
Our submitted binary app version has been approved by Apple reviewers. It's currently pending Developer Release. However, our in-app purchase, which was submitted at the same time, is still under review. Since the newly added in-app purchase hasn't been approved yet, we've decided to hold off on releasing the binary app version. Should we just wait for Apple to approve the in-app purchase, or are there any other recommended actions? Thank you.
2
0
773
Jun ’24
How to deal with Guideline 2.1 - Information Needed (App Tracking Transparency framework related)
My app, which only shows ads one day after it is first launched, keeps being rejected due to Guideline 2.1 - Information Needed (App Tracking Transparency framework related). Here is the rejection message from Apple: Guideline 2.1 - Information Needed We're looking forward to completing our review, but we need more information to continue. Your app uses the AppTrackingTransparency framework, but we are unable to locate the App Tracking Transparency permission request when reviewed on iOS 17.5.1. Next Steps Please explain where we can find the App Tracking Transparency permission request in your app. The request should appear before any data is collected that could be used to track the user. If you've implemented App Tracking Transparency but the permission request is not appearing on devices running the latest operating system, please review the available documentation and confirm App Tracking Transparency has been correctly implemented. If your app does not track users, update your app privacy information in App Store Connect to not declare tracking. You must have the Account Holder or Admin role to update app privacy information. We have provided a detailed step-by-step guide to trigger the App Tracking Transparency. We also attached videos demonstrating how to adjust the date to one day ahead in order to show the ads. Here is our reply: Dear Reviewer, XXX will start displaying ads one day after the app is first launched. To see the App Tracking Transparency permission request and subsequent ads, please follow these steps: 1. Launch XXX for the first time. 2. Close and completely exit the XXX app. 3. Adjust the date on your device to one day ahead. 4. Re-launch XXX. You will see the App Tracking Transparency permission request. For a visual guide, please refer to the attached videos: https://youtube.com/shorts/07qsYuFkPBY - Demonstrates when the user allows tracking. https://youtube.com/shorts/voQfgjAN7h0 - Demonstrates when the user does not allow tracking. If you need further explanation, please contact me at +xxxx-xxxxxxx. Thank you. P.S. I frequently receive similar inquiries with each submission of my app. Could you please add a note to my app to prevent this recurring issue in future reviews? Thank you for your attention. However, Apple continues to reject our update, despite our clear instructions for showing App Tracking Transparency. Do you have any suggestions on what we can do next? Thank you.
2
0
1.4k
Jul ’24
Specifying Item Spacing in UICollectionLayoutListConfiguration
Currently, I am using UICollectionViewCompositionalLayout to achieve the following list layout with spacing: We were thinking of trying out UICollectionLayoutListConfiguration due to its ability to support swipe actions. We would like to specify the spacing between each item. However, I do not find a way to specify item spacing in UICollectionLayoutListConfiguration. Does UICollectionLayoutListConfiguration not support item spacing, or have I missed something? Thanks.
Topic: UI Frameworks SubTopic: UIKit Tags:
1
0
869
Jul ’24
Optimizing Sorting and Order Management in CoreData
Sorting is an important feature in my app. I am using integers to represent the ordering sequence. Items: A, B, D, E, H Order number: 0, 1, 2, 3, 4 When I insert a new item "C", here's the outcome: Items: A, B, C, D, E, H Order number: 0, 1, 2, 3, 4, 5 Here's the write operation required on existing order numbers: D: 2 -> 3 E: 3 -> 4 H: 4 -> 5 I wish to reduce the number of write operations because CoreData is pretty slow at writing. The problem becomes more significant when my users start to have a few thousand items in CoreData. Here's my current workaround: leaving gaps between each order number. For instance: Items: A, B, D, E, H Order number: 0, 10, 20, 30, 40 When I insert a new item "C", here's the outcome: Items: A, B, C, D, E, H Order number: 0, 10, 11, 20, 30, 40 No write operations are required on existing order numbers. Every 1 or 2 weeks, when my users close the app, I run background tasks to re-arrange the gaps between order numbers so that when users insert new items, fewer existing order numbers will be affected. Items: A, B, C, D, E, H Order number: 0, 10, 20, 30, 40, 50 Since sorting is pretty common, I was thinking some of you might have a better idea on how to reduce write operations on existing order numbers. If you have a better idea, do you mind to share it with us? Thanks.
1
0
514
Jul ’24
Resolving 2nd Repeated "Guideline 4.3(a) - Design - Spam" Rejection Within Six Months
We are reaching out for guidance after encountering 2nd repeated "Guideline 4.3(a) - Design - Spam" rejections for our WeNote app. Here’s a brief timeline of our journey: 2018: We launched the WeNote Android app on Google Play Store. 2019: We started promoting WeNote on YouTube and began development of the WeNote iOS app. Our progress was publicly visible on our Trello board and discussed on the Apple Developer forum. August 17, 2021: We filed an official complaint with Apple regarding a *** company infringing on our app logo, title, and description. The issue was resolved when *** agreed to update their app’s branding. 2022 Year: *** company is terminated from App Store. June 2022: WeNote for iOS was officially released on the Apple App Store. June 17, 2024: We received a rejection from the Apple Review team citing Guideline 4.3(a) - Design - Spam: “We noticed your app shares a similar binary, metadata, and/or concept as apps previously submitted by a terminated Apple Developer Program account. Submitting similar or repackaged apps is a form of spam that creates clutter and makes it difficult for users to discover new apps.” We successfully resolved this issue by providing documentation about the previous incident on August 17, 2021. November 22, 2024: Unfortunately, we received the same rejection message again, despite having already informed Apple of the previous case. Request for Assistance: We are now seeking guidance from the community or anyone with experience in navigating similar issues. We’ve provided Apple with all the necessary evidence and explanations regarding the previous incident, but our appeal was rejected. How can we resolve this issue, and prevent future rejections? Some Background on WeNote: To help provide context, I’d like to highlight what makes WeNote stand out compared to other apps in the same category: WeNote is an all-in-one solution: While most apps in the market focus on one function—whether it’s note-taking, to-do lists, or calendar management—WeNote uniquely combines all three into a single app. This integration offers users a seamless experience to manage tasks, notes, and schedules in one place. Proven user satisfaction: We are proud to have over 7,000 user reviews, with an average rating of 4.8 stars. This high rating reflects our users' satisfaction with the app’s features and functionality, as well as its ability to meet their needs in a way that other apps do not. We believe these features make WeNote a valuable and unique tool for users, and we continue to prioritize quality and user experience in our development.
2
0
630
Dec ’24
How to animate substring in a Text?
Currently, I am using multiple Texts in a horizontal stackview, to achieve animation of substring. As you can see in the above animation, the text - conversation - meeting - lecture are animated. However, there shortcoming of such an approach. Text size is not consistent among different Text block. The following Text block are having different text size. - Transform - conversation/ meeting/ lecture - to Quick Note Any idea how we can achieve, so that all text blocks have same text size so that they appear like 1 sentence? Or, how we can make the text blocks having constant text size, but able to perform line wrapping to next line, so that they appear like 1 sentence? Currently, this is the code snippet I am using. import SwiftUI struct ContentView: View { var array = ["lecture", "conversation", "meeting"] @State var currentIndex : Int = 0 @State var firstString : String = "" var body: some View { VStack { HStack { Text("Transform") .lineLimit(1) .minimumScaleFactor(0.5) .font(.title) Text(firstString) .lineLimit(1) .minimumScaleFactor(0.5) .font(.title) .transition(AnyTransition.opacity.animation(.easeInOut(duration:1.0))) .background(.yellow) Text("to Quick Note") .lineLimit(1) .minimumScaleFactor(0.5) .font(.title) }.padding() } .animation(.default) .onAppear { firstString = array[0] let timer = Timer.scheduledTimer(withTimeInterval: 2.0, repeats: true) { _ in if currentIndex == array.count - 1 { self.firstString = array[0] currentIndex = 0 } else { self.firstString = array[currentIndex+1] currentIndex += 1 } } } } } #Preview { ContentView() }
2
0
413
Dec ’24
UIKit or SwiftUI First? Exploring the Best Hybrid Approach
UIKit and SwiftUI each have their own strengths and weaknesses: UIKit: More performant (e.g., UICollectionView). SwiftUI: Easier to create shiny UI and animations. My usual approach is to base my project on UIKit and use UIHostingController whenever I need to showcase visually rich UI or animations (such as in an onboarding presentation). So far, this approach has worked well for me—it keeps the project clean while solving performance concerns effectively. However, I was wondering: Has anyone tried the opposite approach? Creating a project primarily in SwiftUI, then embedding UIKit when performance is critical. If so, what has your experience been like? Would you recommend this approach? I'm considering this for my next project but am unsure how well it would work in practice.
1
0
90
Mar ’25
CoreData common practice - Do you usually have a struct based data class, as the bridge between your UI layer, and the CoreData data layer?
I was wondering, when you use CoreData, do you usually create another equivalent struct based data class, to compliment the NSManagedObject? The struct based data class, will act as the bridge, between UI layer, and CoreData data layer. For instance, I have the following CoreData model data class. @objc(NSTabInfo) public class NSTabInfo: NSManagedObject { } extension NSTabInfo { @nonobjc public class func fetchRequest() -> NSFetchRequest<NSTabInfo> { return NSFetchRequest<NSTabInfo>(entityName: "NSTabInfo") } @NSManaged public var colorIndex: Int32 @NSManaged public var customColor: Int32 @NSManaged public var name: String? @NSManaged public var order: Int64 @NSManaged public var typeValue: Int32 @NSManaged public var syncedTimestamp: Int64 @NSManaged public var uuid: UUID } extension NSTabInfo : Identifiable { } We need a UI, to represent such model data object. Initially, we have the following UI class class TabInfoCell: UICollectionViewCell { private var tabInfo: NSTabInfo? func update(_ tabInfo: NSTabInfo) { self.tabInfo = tabInfo } } But, we just feel not comfortable with such design. Letting TabInfoCell (UI class) to hold NSTabInfo (CoreData model data class) doesn't feel right, as NSTabInfo contains CoreData's context. I do not feel comfortable, to expose CoreData's context to an UI. Will holding a class reference to NSTabInfo in UI, affect CoreData memory allocation/ deallocation strategy? Using weak reference might solve the issue. But, what should the UI do when the weak reference become nil? With such concern, We have the following design struct TabInfo { enum Kind: Int { case All = 0 case Calendar case Custom case Settings } let kind: Kind var name: String? var colorIndex: Int var customColor: Int var order: Int var syncedTimestamp: Int64 var uuid: UUID } @objc(NSTabInfo) public class NSTabInfo: NSManagedObject { convenience init(context: NSManagedObjectContext, tabInfo: TabInfo) { self.init(context: context) self.colorIndex = Int32(tabInfo.colorIndex) self.customColor = Int32(tabInfo.customColor) self.name = tabInfo.name self.order = Int64(tabInfo.order) self.typeValue = Int32(tabInfo.kind.rawValue) self.syncedTimestamp = tabInfo.syncedTimestamp self.uuid = tabInfo.uuid } func toTabInfo() -> TabInfo { return TabInfo( kind: TabInfo.Kind(rawValue: Int(self.typeValue))!, name: self.name, colorIndex: Int(self.colorIndex), customColor: Int(self.customColor), order: Int(self.order), syncedTimestamp: self.syncedTimestamp, uuid: uuid ) } } @nonobjc public class func fetchRequest() -> NSFetchRequest<NSTabInfo> { return NSFetchRequest<NSTabInfo>(entityName: "NSTabInfo") } @NSManaged public var colorIndex: Int32 @NSManaged public var customColor: Int32 @NSManaged public var name: String? @NSManaged public var order: Int64 @NSManaged public var typeValue: Int32 @NSManaged public var syncedTimestamp: Int64 @NSManaged public var uuid: UUID } extension NSTabInfo : Identifiable { } Then, in our UI class, it looks like class TabInfoCell: UICollectionViewCell { private var tabInfo: TabInfo? func update(_ tabInfo: TabInfo) { self.tabInfo = tabInfo } } I was wondering, does such design philosophy make sense? Do you usually have a struct based data class, as the bridge between your UI layer, and the CoreData data layer? Thanks.
0
0
698
Jun ’21
Why creating index in CoreData will end up duplicated index (with different name) in SQLite file?
I was wondering did anyone of you come across this strange situation? I tried to index a property in entity. For instance, for entity named NSPlainNote, I try to create an index named index_plain_note_label, on property label. This is how it looks like. However, if I inspect the content of the generated SQLite file. It seems that 2 same indices with different name are created. CREATE INDEX Z_NSPlainNote_index_plain_note_label ON ZNSPLAINNOTE (ZLABEL COLLATE BINARY ASC) CREATE INDEX Z_NSPlainNote_label ON ZNSPLAINNOTE (ZLABEL COLLATE BINARY ASC) If we observe carefully, such duplication also happen in all other index with 1 property like NSPlainNote's order NSPlainNote's sticky NSTabInfo's order Such duplication does not happen on index with 2 properties, or index with unique constraint. May I know why it is so? Is there any step which I have done incorrectly?
0
0
509
Jul ’21
performBatchUpdates completion handler is not called when there is section operation involved
So far, here's are the code snippets that almost work for NSFetchedResultsController + UICollectionView, based on the information provided https://developer.apple.com/videos/play/wwdc2018/225 (Starting at 36:50) https://stackoverflow.com/questions/38597804/how-to-order-moves-inserts-deletes-and-updates-in-a-uicollectionview-performb/53271562#53271562 Please note that, there are 2 [BlockOperation], as reloadItems and moveItem doesn't play well within single performBatchUpdates. Based on the workaround proposed in the video, we have to call reloadItems in a separate performBatchUpdates. We also do not follow 100% methods (Perform reloadItems typed performBatchUpdates first, followed by insert/ move/ delete typed performBatchUpdates) proposed in the video. This is because we notice that it doesn't work well even for simple case. Some strange behaviour including reloadItems will cause duplicated cell UI to be shown on screen. The "almost" work method we found are Perform performBatchUpdates for insert, move and delete At completion handler of performBatchUpdates, perform another performBatchUpdates for reloadItems NSFetchedResultsController + UICollectionView integration private var blockOperations: [BlockOperation] = [] // reloadItems and moveItem do not play well together. We are using the following workaround proposed at // https://developer.apple.com/videos/play/wwdc2018/225/ private var blockUpdateOperations: [BlockOperation] = [] extension DashboardViewController: NSFetchedResultsControllerDelegate { func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) { if type == NSFetchedResultsChangeType.insert { print(">> insert") blockOperations.append( BlockOperation(block: { [weak self] in if let self = self { self.collectionView!.insertItems(at: [newIndexPath!]) } }) ) } else if type == NSFetchedResultsChangeType.update { print(">> update") blockUpdateOperations.append( BlockOperation(block: { [weak self] in if let self = self, let indexPath = indexPath { self.collectionView.reloadItems(at: [indexPath]) } }) ) } else if type == NSFetchedResultsChangeType.move { print(">> move") blockOperations.append( BlockOperation(block: { [weak self] in if let self = self, let newIndexPath = newIndexPath, let indexPath = indexPath { self.collectionView.moveItem(at: indexPath, to: newIndexPath) } }) ) } else if type == NSFetchedResultsChangeType.delete { print(">> delete") blockOperations.append( BlockOperation(block: { [weak self] in if let self = self { self.collectionView!.deleteItems(at: [indexPath!]) } }) ) } } func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange sectionInfo: NSFetchedResultsSectionInfo, atSectionIndex sectionIndex: Int, for type: NSFetchedResultsChangeType) { if type == NSFetchedResultsChangeType.insert { print(">> section insert") blockOperations.append( BlockOperation(block: { [weak self] in if let self = self { self.collectionView!.insertSections(IndexSet(integer: sectionIndex)) } }) ) } else if type == NSFetchedResultsChangeType.update { print(">> section update") blockOperations.append( BlockOperation(block: { [weak self] in if let self = self { self.collectionView!.reloadSections(IndexSet(integer: sectionIndex)) } }) ) } else if type == NSFetchedResultsChangeType.delete { print(">> section delete") blockOperations.append( BlockOperation(block: { [weak self] in if let self = self { self.collectionView!.deleteSections(IndexSet(integer: sectionIndex)) } }) ) } } func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) { if blockOperations.isEmpty { performBatchUpdatesForUpdateOperations() } else { collectionView.performBatchUpdates({ [weak self] () -> Void in guard let self = self else { return } for operation: BlockOperation in self.blockOperations { operation.start() } self.blockOperations.removeAll(keepingCapacity: false) }, completion: { [weak self] (finished) -> Void in print("blockOperations completed") guard let self = self else { return } self.performBatchUpdatesForUpdateOperations() }) } } private func performBatchUpdatesForUpdateOperations() { if blockUpdateOperations.isEmpty { return } collectionView.performBatchUpdates({ [weak self] () -> Void in guard let self = self else { return } for operation: BlockOperation in self.blockUpdateOperations { operation.start() } self.blockUpdateOperations.removeAll(keepingCapacity: false) }, completion: { [weak self] (finished) -> Void in print("blockUpdateOperations completed") guard let self = self else { return } }) } } The above way, works "almost" well when no "section" operations involved. If there is item moved operation between different section, the following logging will be printed blockOperations completed >> move blockOperations completed >> move blockOperations completed However, if there are item being moved and section being added/ removed, the following logging will be printed >> section delete >> move >> section insert >> move This means the completion handler block is not executed! Does anyone know why it is so, and how I can workaround with this issue? Thanks.
0
0
1.3k
Jul ’21
CoreData: Is it possible to have SQLite CASE WHEN...END logic in NSSortDescriptor?
Currently, I am porting several SQLite statement to CoreData. "SELECT id, \"order\" FROM plain_note WHERE archived = :archived AND trashed = :trashed " + "ORDER BY " + "CASE WHEN color_index = -1 THEN 12 + ABS(custom_color) ELSE " + "color_index END DESC, " + "\"order\" ASC" "SELECT id, \"order\" FROM plain_note WHERE archived = :archived AND trashed = :trashed " + "ORDER BY " + "title COLLATE NOCASE DESC, " + "CASE WHEN locked = 1 THEN NULL ELSE " + "CASE WHEN type = 0 THEN body ELSE searched_string END " + "END COLLATE NOCASE DESC, " + "\"order\" ASC" But, I am clueless on how I can make CoreData have the following CASE WHEN...END behavior, during sorting. CASE WHEN color_index = -1 THEN 12 + ABS(custom_color) ELSE color_index END DESC CASE WHEN locked = 1 THEN NULL ELSE CASE WHEN type = 0 THEN body ELSE searched_string END END COLLATE NOCASE DESC I was wondering, is there any possible technique I can use, so that NSSortDescriptor can have the similar behavior?
0
0
430
Sep ’21
Prevent scroll position from resetting when perform UITextView typing in UICollectionView
Currently, we try to place multiple UITextViews in UICollectionView. To ensure UICollectionView's cell height, will adjust based on the dynamic content of UITextView, this is what we have done. Disable scrolling in UITextView. Use .estimated(CGFloat(44)) for UICollectionViewCompositionalLayout Whenever there is text change, call collectionView.collectionViewLayout.invalidateLayout(). This is a critical step to ensure cell height will adjust accordingly. However, calling collectionView.collectionViewLayout.invalidateLayout() does come with a side effect. The current scroll position of UICollectionView will be reset, after calling collectionView.collectionViewLayout.invalidateLayout(). Does anyone know how can I Prevent unwanted auto scroll position resetting? UICollectionView will auto scroll to current cursor position, so that what is current being typed is visible to user? The code to demonstrate this problem is as follow - https://github.com/yccheok/checklist-demo Here's the code snippet, on what was happening as typing goes on func textViewDidChange(_ checklistCell: ChecklistCell) { // // Critical code to ensure cell will resize based on cell content. // // (But comes with a side effect which will reset scroll position.) self.collectionView.collectionViewLayout.invalidateLayout() // // Ensure our checklists data structure in sync with UI state. // guard let indexPath = collectionView.indexPath(for: checklistCell) else { return } let item = indexPath.item let text = checklistCell.textView.text self.checklists[item].text = text } Side Note Note, the closest solution we have came across is posted at https://medium.com/@georgetsifrikas/embedding-uitextview-inside-uitableviewcell-9a28794daf01 In UITableViewController, during text change, the author is using DispatchQueue.main.async { tableView?.beginUpdates() tableView?.endUpdates() } It works well. But, what is the equivalent solution for UICollectionView? We can't try out with self.collectionView.performBatchUpdates, as our solution is built around Diffable Data Source. I have tried DispatchQueue.main.async { self.collectionView.collectionViewLayout.invalidateLayout() } That doesn't solve the problem either. Thank you.
Topic: UI Frameworks SubTopic: UIKit Tags:
2
0
4.2k
Nov ’21