Post

Replies

Boosts

Views

Activity

Reply to Keep ScrollView position when adding items on the top
@Frameworks Engineer I've refined your code a bit with suggestions from other answers here to try and explain the question better. struct ContentView: View { @State var data: [String] = (0 ..< 25).map { String($0) } @State var dataID: String? var body: some View { ScrollView { VStack { Text("Header") LazyVStack { ForEach(data, id: \.self) { item in Color.red .frame(width: 100, height: 100) .overlay { Text("\(item)") .padding() .background() } } } .scrollTargetLayout() } } .scrollPosition(id: $dataID) .safeAreaInset(edge: .bottom) { VStack { Text("\(Text("Scrolled").bold()) \(dataIDText)") HStack { Button { scrollTo(data.first) } label: { Label("Top", systemImage: "arrow.up") .frame(maxWidth: .infinity) } Button { scrollTo(data.last) } label: { Label("Bottom", systemImage: "arrow.down") .frame(maxWidth: .infinity) } Menu { Button("Prepend") { let items = createMoreItems() data.insert(contentsOf: items, at: 0) } Button("Append") { let items = createMoreItems() data.append(contentsOf: items) } Button("Remove First") { data.removeFirst() } Button("Remove Last") { data.removeLast() } } label: { Label("More", systemImage: "ellipsis.circle") .frame(maxWidth: .infinity) } } } .background(Material.ultraThin) } } var dataIDText: String { dataID.map(String.init(describing:)) ?? "None" } private func scrollTo(_ dataID: String?, animation: Animation? = .easeInOut, position: UnitPoint = .bottom) { withAnimation(animation) { withTransaction(\.scrollTargetAnchor, position) { self.dataID = dataID } } } private func createMoreItems(count: Int = 10) -> [String] { return (0..<count).map { String(data.count + $0) } } } #Preview { ContentView() } While most of the times when adding a single item (append, insert) the dataID scrolled position is kept correctly, when adding multiple items (like a page) on top (prepend) it fails to maintain the right content offset, pushing the whole content down. Notice that on this scenario dataID won't change its value. There are a lot of hacky ways to try fix this like transforming the ScrollView and its subviews, accessing UIScrollView directly using introspect,, or re-setting dataID few moments after appending a page, but none of them is robust and most of the times they create weird scroll jumps. I've also tried to create a custom ScrollTargetBehavior updating the scroll target to the old page content offset, but it works only when new content is added while drugging, and also creates weird scroll jumps. Unfortunately achieving reverse scroll behavior in SwiftUI 5 feels impossible ATM.
Dec ’23
Reply to URLSessionWebSocketTask custom close code
Thanks @eskimo , I'll give this article a read, but I have to admit that I find the URLSession implementation quite straightforward, at least until now. About using the enum's raw value, the thing is that I can't use any custom close code because enum, by definition, have a close set of cases. Using webSocketTask.value(forKey: "_closeCode") seems to be a good enough solution, but I'm not sure if it counts as using private api.
Oct ’23
Reply to URLSessionDownloadDelegate never called
Iv'e sent a feedback, FB13228209. but that you then turn around and read the entire file into memory. That’s counter productive For the time being our average download size is about 4MB, mostly photos and attachments, and we do limit maximum upload size, but I get your point. I will find a way to avoid loading file data directly providing a local file url instead. Thanks.
Oct ’23
Reply to URLSessionDownloadDelegate never called
Hi @eskimo, thanks for the response. About the swift concurrency interface, the fact that those APIs do not trigger certain delegate methods is really confusing, it is not documented properly and what makes it even more confusing is that delegate is one of the function parameters. I would like to calculate download progress, and prefer doing it using delegates instead of KVO. is there an easy way doing this using concurrency convenience functions?. About the way I structured my download task, it is a work in progress, if you have a good reference for downloading in chunks using concurrency I'll be more than happy to take a look, I guess it involves delegates like didReceive data and saving to FileManager? Does the fact that I read the contents of the download immediately into memory prevent urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) from getting called? Thanks.
Oct ’23
Reply to Live preview presenting app root ViewController
So after reading this and this I've added a new flag to our code: static var isXcodeRunningForPreviews: Bool { return ProcessInfo.processInfo.environment["XCODE_RUNNING_FOR_PREVIEWS"] == "1" } I wonder if this flag is robust and we can relay on it, or if there is any cleaner way to prevent some code from running when building live previews.
Feb ’23
Reply to Live preview presenting app root ViewController
Hi @kcathey, thanks for the quick response. Yes previews are intractable like in simulator. It's an enterprise app, so I need to get legal team approval before posting logs that ,may contain sensitive data. For now I fond 2 entry points in our code (AppDelegate) that responsible for that glitch, any way to avoid them when running live previews? I'm thinking about something like #if DEBUG for previews.
Feb ’23