I'm trying to define a SwiftUI view as a reusable component in my app. Here is how it is defined:
struct CustomContainer: View {
var body: some View {
ZStack {
RoundedRectangle(cornerRadius: 8, style: .circular)
.stroke(Color.gray, lineWidth: 1.2)
// foreground here ...
}
}
}
I would like for users of my code to be able to apply the view modifier stroke(_:lineWidth:) on CustomContainer, but I would like the CustomContainer to internally apply that modifier on the rounded rectangle inside its body. How would I do that?
This is my desired use of CustomContainer:
struct FormView: View {
var body: some View {
CustomContainer()
.stroke(Color.orange, lineWidth: 2)
}
}
Post
Replies
Boosts
Views
Activity
I'm struggling to understand why the async-await version of URLSession download task APIs do not call the delegate functions, whereas the old non-async version that returns a reference to the download task works just fine.
Here is my sample code:
class DownloadDelegate: NSObject, URLSessionDownloadDelegate {
func urlSession(_ session: URLSession,
downloadTask: URLSessionDownloadTask,
didWriteData bytesWritten: Int64,
totalBytesWritten: Int64,
totalBytesExpectedToWrite: Int64) {
// This only prints the percentage of the download progress.
let calculatedProgress = Float(totalBytesWritten) / Float(totalBytesExpectedToWrite)
let formatter = NumberFormatter()
formatter.numberStyle = .percent
print(formatter.string(from: NSNumber(value: calculatedProgress))!)
}
}
// Here's the VC.
final class DownloadsViewController: UIViewController {
private let url = URL(string: "https://pixabay.com/get/g0b9fa2936ff6a5078ea607398665e8151fc0c10df7db5c093e543314b883755ecd43eda2b7b5178a7e613a35541be6486885fb4a55d0777ba949aedccc807d8c_1280.jpg")!
private let delegate = DownloadDelegate()
private lazy var session = URLSession(configuration: .default, delegate: delegate, delegateQueue: nil)
// for the async-await version
private var task: Task<Void, Never>?
// for the old version
private var downloadTask: URLSessionDownloadTask?
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
task?.cancel()
task = nil
task = Task {
let (_, _) = try! await session.download(for: URLRequest(url: url))
self.task = nil
}
// If I uncomment this, the progress listener delegate function above is called.
// downloadTask?.cancel()
// downloadTask = nil
// downloadTask = session.downloadTask(with: URLRequest(url: url))
// downloadTask?.resume()
}
}
What am I missing here?
I'm using diffable data sources with compositional layout. The sections in my collection view can fetch their own items and in parallel, so at any point in time, my section snapshot may contain data models for a loading, success, or failure state. When a fetch results into a failure, I want the fetching section to be hidden.
To delete the section, I get a copy of my data source's current snapshot, call deleteSections(_:) on it, and then apply the copy with apply(_:to:).
From my logs, it seems that calling apply(_:to:) triggers a layout pass on the collection view, and the collection view behaves as intended when, inside UICollectionViewCompositionalLayoutSectionProvider, I return a garbage NSCollectionLayoutSection for a deleted section. The garbage layout is ultimately not rendered because the section is deleted from the diffable data source.
However, when I return nil from within UICollectionViewCompositionalLayoutSectionProvider (reasonable, because the return type is optional), the app crashes with the following message at the code where apply(_:to:) is called:
Invalid section definition. Please specify a valid section definition when content is to be rendered for a section. This is a client error.
I inspected my diffable data source's section identifiers and the section is actually in the snapshot copy prior to being deleted and the application of the copy. The console also logs the location of the assertion failure:
Assertion failure in -[_UICollectionCompositionalLayoutSolver _queryClientForSectionDefinitionForSectionIndex:], _UICollectionCompositionalLayoutSolver.m:2927
Therefore, it seems that the problem lies in the compositional layout and not in my concurrent fetches nor the operations conducted on the diffable data source.
So is it really just the case that I cannot return nil from UICollectionViewCompositionalLayoutSectionProvider? Because the return type is optional, and it is not anywhere in Apple documentation that I cannot return nil from it.