Thank you for responding despite my vagueness.
Apple MacBook Air M1, 8 GB, MacOS Sonoma 14.2.1, Xcode 15.2--I forgot to paste it from the TSI message.
After a few hours, I got the "Cannot preview in this file" error.
I’ve noticed that my derived data folder has a different location according to Xcode and Finder.
According to Xcode, the root path is /Users/filippo.
But, according to Finder, it's /Users/Filippo.
I changed my username a year ago.
If you think this issue could be related to my problem, please tell me how to solve it.
Post
Replies
Boosts
Views
Activity
Answer: https://stackoverflow.com/questions/77939616/change-derived-data-location-in-xcode
Okay thank you.
I don’t understand why the memory keeps growing, but I understand that I simply cannot use reloadRows(at:) in this case.
Fixed: cell.accessories = [.disclosureIndicator(), .customView(configuration: .init(customView: UIStepper(), placement: .trailing(), reservedLayoutWidth: .actual))]
https://stackoverflow.com/questions/78241008/override-show-sender-of-uiviewcontroller-freezes-the-ui
https://stackoverflow.com/questions/78089692/swiftui-selectable-stepper-in-view-that-presents-modally
https://stackoverflow.com/questions/78248735/cant-display-the-simplest-uitoolbar
https://stackoverflow.com/questions/78268523/how-do-i-resize-a-uicollectionviewlistcell-containing-a-uitextview.
https://stackoverflow.com/questions/78284030/swift-5-10-cannot-access-property-with-a-non-sendable-type-from-non-iso/78285030#78285030
In a nutshell: call signInAnonymouslyIfNecessary() in viewDidDisappear(): avoid in general dealing with class deinitializers.
But if you insist on calling signInAnonymouslyIfNecessary() in the deinitializer, you can:
Mark AuthController as @MainActor
Mark signInAnonymouslyIfNecessary as nonisolated
Wrap signInAnonymouslyIfNecessary in a Task:
@MainActor final class AuthController {
nonisolated func signInAnonymouslyIfNecessary() {
Task { @MainActor in
/// ...
}
}
}
https://stackoverflow.com/questions/78311570/how-do-i-update-a-collection-view-supplementary-view-without-giving-up-on-animat
At this time the answer is:
To directly update a supplementaryView you need to know its kind and section.
With your example, you could add a following didSet code to a footerText:
var footerText = "Initial footer text" {
didSet {
guard let footer = collectionView.supplementaryView(forElementKind: UICollectionView.elementKindSectionFooter, at: IndexPath(row: 0, section: 0)) as? UICollectionViewListCell else { return }
var contentConfiguration = UIListContentConfiguration.cell()
contentConfiguration.text = self.footerText
footer.contentConfiguration = contentConfiguration
}
}
This way each time you change footerText, your footer will be updated.
You could also move contentConfiguration update to a separate fuction, I've just copied it from your configureSupplementaryViewProvider
Make a custom cell:
class SwitchCell: UICollectionViewListCell {
let _switch = UISwitch()
override init(frame: CGRect) {
super.init(frame: frame)
accessories = [
.customView(configuration: .init(
customView: _switch,
placement: .trailing())
)
]
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
And edit cellRegistration accordingly:
let cellRegistration = UICollectionView.CellRegistration<SwitchCell, String> { [weak self] cell, indexPath, itemIdentifier in
guard let self else { return }
cell._switch.isOn = bool
cell._switch.addTarget(self, action: #selector(toggleBool), for: .valueChanged)
}
https://stackoverflow.com/questions/746670/how-to-lose-margin-padding-in-uitextview
I can't edit the post here anymore so go check out the stackoverflow.com post which is up to date: https://stackoverflow.com/questions/78373006/handle-keyboard-layout-in-ios-15-uikit-app-with-collection-view-using-the-moder
If you use cell registrations instead of supplementary registrations, the keyboard doesn't dismiss for any reason and you can also get rid of the dispatch blocks:
import UIKit
class ViewController: UIViewController {
let words = ["foo", "bar"]
var filteredWords = ["foo", "bar"] {
didSet {
dataSource.apply(self.snapshot)
}
}
var collectionView: UICollectionView!
var dataSource: UICollectionViewDiffableDataSource<String, String>!
var snapshot: NSDiffableDataSourceSnapshot<String, String> {
var snapshot = NSDiffableDataSourceSnapshot<String, String>()
snapshot.appendSections(["main"])
snapshot.appendItems(["search bar id"])
snapshot.appendItems(filteredWords)
return snapshot
}
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.rightBarButtonItem = .init(title: "Apply", style: .plain, target: self, action: #selector(apply))
configureHierarchy()
configureDataSource()
}
@objc func apply() {
dataSource.apply(self.snapshot)
}
func configureHierarchy() {
collectionView = .init(frame: .zero, collectionViewLayout: createLayout())
view.addSubview(collectionView)
collectionView.frame = view.bounds
collectionView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
}
func createLayout() -> UICollectionViewLayout {
UICollectionViewCompositionalLayout { section, layoutEnvironment in
var config = UICollectionLayoutListConfiguration(appearance: .insetGrouped)
config.headerMode = .firstItemInSection
return NSCollectionLayoutSection.list(using: config, layoutEnvironment: layoutEnvironment)
}
}
func configureDataSource() {
let cellRegistration = UICollectionView.CellRegistration<UICollectionViewListCell, String> { _, _, _ in }
let searchBarCellRegistration = UICollectionView.CellRegistration<SearchBarCell, String>{ cell, indexPath, itemIdentifier in
cell.searchBar.delegate = self
}
dataSource = .init(collectionView: collectionView) { collectionView, indexPath, itemIdentifier in
if indexPath.row == 0 {
collectionView.dequeueConfiguredReusableCell(using: searchBarCellRegistration, for: indexPath, item: itemIdentifier)
} else {
collectionView.dequeueConfiguredReusableCell(using: cellRegistration, for: indexPath, item: itemIdentifier)
}
}
dataSource.apply(self.snapshot, animatingDifferences: false)
}
}
extension ViewController: UISearchBarDelegate {
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
filteredWords = words.filter { $0.hasPrefix(searchText) }
}
func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
filteredWords = words
}
}
class SearchBarCell: UICollectionViewListCell {
let searchBar = UISearchBar()
override init(frame: CGRect) {
super.init(frame: frame)
contentView.addSubview(searchBar)
searchBar.pinToSuperview()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
extension UIView {
func pin(
to object: CanBePinnedTo,
top: CGFloat = 0,
bottom: CGFloat = 0,
leading: CGFloat = 0,
trailing: CGFloat = 0
) {
self.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
self.topAnchor.constraint(equalTo: object.topAnchor, constant: top),
self.bottomAnchor.constraint(equalTo: object.bottomAnchor, constant: bottom),
self.leadingAnchor.constraint(equalTo: object.leadingAnchor, constant: leading),
self.trailingAnchor.constraint(equalTo: object.trailingAnchor, constant: trailing),
])
}
func pinToSuperview(
top: CGFloat = 0,
bottom: CGFloat = 0,
leading: CGFloat = 0,
trailing: CGFloat = 0,
file: StaticString = #file,
line: UInt = #line
) {
guard let superview = self.superview else {
print(">> \(#function) failed in file: \(String.localFilePath(from: file)), at line: \(line): could not find \(Self.self).superView.")
return
}
self.pin(to: superview, top: top, bottom: bottom, leading: leading, trailing: trailing)
}
func pinToSuperview(constant c: CGFloat = 0, file: StaticString = #file, line: UInt = #line) {
self.pinToSuperview(top: c, bottom: -c, leading: c, trailing: -c, file: file, line: line)
}
}
@MainActor
protocol CanBePinnedTo {
var topAnchor: NSLayoutYAxisAnchor { get }
var bottomAnchor: NSLayoutYAxisAnchor { get }
var leadingAnchor: NSLayoutXAxisAnchor { get }
var trailingAnchor: NSLayoutXAxisAnchor { get }
}
extension UIView: CanBePinnedTo { }
extension UILayoutGuide: CanBePinnedTo { }
extension String {
static func localFilePath(from fullFilePath: StaticString = #file) -> Self {
URL(fileURLWithPath: "\(fullFilePath)").lastPathComponent
}
}
Basically don't use supplementary views unless absolutely necessary: it also seems that there's no declarative way to update them without losing animations (Apple's guided project "Modern Collection Views" doesn't seem to provide a solution, nor do these posts: https://stackoverflow.com/questions/78311570/how-do-i-update-a-collection-view-supplementary-view-without-giving-up-on-animat, https://forums.developer.apple.com/forums/thread/749847).
Use UIListContentConfiguration:
import UIKit
class ViewController: UIViewController {
var collectionView: UICollectionView!
var dataSource: UICollectionViewDiffableDataSource<String, String>!
override func viewDidLoad() {
super.viewDidLoad()
configureHierarchy()
configureDataSource()
}
func configureHierarchy() {
collectionView = .init(frame: .zero, collectionViewLayout: createLayout())
view.addSubview(collectionView)
collectionView.frame = view.bounds
}
func createLayout() -> UICollectionViewLayout {
UICollectionViewCompositionalLayout { section, layoutEnvironment in
let config = UICollectionLayoutListConfiguration(appearance: .insetGrouped)
return NSCollectionLayoutSection.list(using: config, layoutEnvironment: layoutEnvironment)
}
}
func configureDataSource() {
let cellRegistration = UICollectionView.CellRegistration<UICollectionViewListCell, String> { cell, indexPath, itemIdentifier in
var contentConfig = CustomListContentConfiguration()
contentConfig.placeholder = "Placeholder"
cell.contentConfiguration = contentConfig
}
dataSource = .init(collectionView: collectionView) { collectionView, indexPath, itemIdentifier in
collectionView.dequeueConfiguredReusableCell(using: cellRegistration, for: indexPath, item: itemIdentifier)
}
var snapshot = NSDiffableDataSourceSnapshot<String, String>()
snapshot.appendSections(["main"])
snapshot.appendItems(["demo"])
dataSource.apply(snapshot, animatingDifferences: false)
}
}
class CustomListContentConfiguration: UIContentConfiguration {
var placeholder: String?
func makeContentView() -> UIView & UIContentView {
return CustomListContentView(configuration: self)
}
func updated(for state: UIConfigurationState) -> Self {
// Not handling state changes in this example, so just return self
return self
}
}
class CustomListContentView: UIView, UIContentView {
var configuration: UIContentConfiguration
init(configuration: UIContentConfiguration) {
self.configuration = configuration
super.init(frame: .zero)
configureSubviews()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func configureSubviews() {
guard let config = configuration as? CustomListContentConfiguration else { return }
let leadingView = UIView()
leadingView.backgroundColor = .systemRed
let textField = UITextField()
textField.placeholder = config.placeholder
textField.font = .systemFont(ofSize: 100)
addSubview(leadingView)
addSubview(textField)
leadingView.translatesAutoresizingMaskIntoConstraints = false
textField.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
leadingView.centerYAnchor.constraint(equalTo: layoutMarginsGuide.centerYAnchor),
leadingView.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor),
leadingView.widthAnchor.constraint(equalTo: layoutMarginsGuide.heightAnchor),
leadingView.heightAnchor.constraint(equalTo: layoutMarginsGuide.heightAnchor),
textField.topAnchor.constraint(equalTo: topAnchor),
textField.bottomAnchor.constraint(equalTo: bottomAnchor),
textField.leadingAnchor.constraint(equalTo: leadingView.trailingAnchor, constant: 16),
textField.trailingAnchor.constraint(equalTo: layoutMarginsGuide.trailingAnchor),
textField.heightAnchor.constraint(greaterThanOrEqualToConstant: 44)
])
}
}