I have a sheet thats being presented in SwiftUI and the first time it's opened it automatically dismisses itself half a second later. Reopening it from then on works properly. Has anyone else experienced this and perhaps come up with a solution?
Stack Overflow post: https://stackoverflow.com/questions/62722308/swiftui-sheet-automatically-dismisses-itself
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView:
NavigationView{
List{
ForEach(0..<10){ value in
Text("Hello, World \(value)")
}
}
NavigationLink(destination: Test()) {
Text("Details")
}
}
)
self.window = window
window.makeKeyAndVisible()
}
}
}
struct Test : View{
@State var show = false
var body : some View{
Text("Details")
.sheet(isPresented: $show, content: {
Color.blue
})
.toolbar{
ToolbarItem(placement: .navigationBarTrailing) {
Button("Show Sheet"){
show.toggle()
}
}
}
}
}
Post
Replies
Boosts
Views
Activity
The new UISheetPresentationControllerDetents look great but only the medium size is new. Many applications would benefit from a small or extra small detent that only takes up 1/4th or 1/8th of the screen. Google maps is a good example.
Is there anyway to add custom detents or specify a specific sheet height?
Using the App Store Connect API how can you get the release date for an app? I've been able to use this endpoint to list a bunch of information, however the release date is not included.
As you can see in the JSON response posted below, it does have a "createdDate" but this corresponds to when the version was made in App Store Connect (Prepare for Submission), not when it was released to the store. This can be verified by looking in App Store connect.
JSON Response:
https://api.appstoreconnect.apple.com/v1/apps/395389919/appStoreVersions?limit=1
{
"data": [
{
"type": "appStoreVersions",
"id": "a75acc6e-9429-4539-a282-eadef235169e",
"attributes": {
"platform": "IOS",
"versionString": "5.9.0",
"appStoreState": "READY_FOR_SALE",
"copyright": "InterPro Solutions, LLC",
"releaseType": "MANUAL",
"earliestReleaseDate": null,
"usesIdfa": null,
"downloadable": true,
"createdDate": "2021-10-11T08:37:22-07:00"
},
"relationships": {
"ageRatingDeclaration": {
"links": {
"self": "https://api.appstoreconnect.apple.com/v1/appStoreVersions/a75acc6e-9429-4539-a282-eadef235169e/relationships/ageRatingDeclaration",
"related": "https://api.appstoreconnect.apple.com/v1/appStoreVersions/a75acc6e-9429-4539-a282-eadef235169e/ageRatingDeclaration"
}
},
"appStoreVersionLocalizations": {
"links": {
"self": "https://api.appstoreconnect.apple.com/v1/appStoreVersions/a75acc6e-9429-4539-a282-eadef235169e/relationships/appStoreVersionLocalizations",
"related": "https://api.appstoreconnect.apple.com/v1/appStoreVersions/a75acc6e-9429-4539-a282-eadef235169e/appStoreVersionLocalizations"
}
},
"build": {
"links": {
"self": "https://api.appstoreconnect.apple.com/v1/appStoreVersions/a75acc6e-9429-4539-a282-eadef235169e/relationships/build",
"related": "https://api.appstoreconnect.apple.com/v1/appStoreVersions/a75acc6e-9429-4539-a282-eadef235169e/build"
}
},
"appStoreVersionPhasedRelease": {
"links": {
"self": "https://api.appstoreconnect.apple.com/v1/appStoreVersions/a75acc6e-9429-4539-a282-eadef235169e/relationships/appStoreVersionPhasedRelease",
"related": "https://api.appstoreconnect.apple.com/v1/appStoreVersions/a75acc6e-9429-4539-a282-eadef235169e/appStoreVersionPhasedRelease"
}
},
"routingAppCoverage": {
"links": {
"self": "https://api.appstoreconnect.apple.com/v1/appStoreVersions/a75acc6e-9429-4539-a282-eadef235169e/relationships/routingAppCoverage",
"related": "https://api.appstoreconnect.apple.com/v1/appStoreVersions/a75acc6e-9429-4539-a282-eadef235169e/routingAppCoverage"
}
},
"appStoreReviewDetail": {
"links": {
"self": "https://api.appstoreconnect.apple.com/v1/appStoreVersions/a75acc6e-9429-4539-a282-eadef235169e/relationships/appStoreReviewDetail",
"related": "https://api.appstoreconnect.apple.com/v1/appStoreVersions/a75acc6e-9429-4539-a282-eadef235169e/appStoreReviewDetail"
}
},
"appStoreVersionSubmission": {
"links": {
"self": "https://api.appstoreconnect.apple.com/v1/appStoreVersions/a75acc6e-9429-4539-a282-eadef235169e/relationships/appStoreVersionSubmission",
"related": "https://api.appstoreconnect.apple.com/v1/appStoreVersions/a75acc6e-9429-4539-a282-eadef235169e/appStoreVersionSubmission"
}
},
"idfaDeclaration": {
"links": {
"self": "https://api.appstoreconnect.apple.com/v1/appStoreVersions/a75acc6e-9429-4539-a282-eadef235169e/relationships/idfaDeclaration",
"related": "https://api.appstoreconnect.apple.com/v1/appStoreVersions/a75acc6e-9429-4539-a282-eadef235169e/idfaDeclaration"
}
},
"appClipDefaultExperience": {
"links": {
"self": "https://api.appstoreconnect.apple.com/v1/appStoreVersions/a75acc6e-9429-4539-a282-eadef235169e/relationships/appClipDefaultExperience",
"related": "https://api.appstoreconnect.apple.com/v1/appStoreVersions/a75acc6e-9429-4539-a282-eadef235169e/appClipDefaultExperience"
}
}
},
"links": {
"self": "https://api.appstoreconnect.apple.com/v1/appStoreVersions/a75acc6e-9429-4539-a282-eadef235169e"
}
}
],
"links": {
"self": "https://api.appstoreconnect.apple.com/v1/apps/395389919/appStoreVersions?limit=1",
"next": "https://api.appstoreconnect.apple.com/v1/apps/395389919/appStoreVersions?cursor=AQ.ANZyDDk&limit=1"
},
"meta": {
"paging": {
"total": 68,
"limit": 1
}
}
}
I have a UICollectionViewLayout grid with three columns. Each item in the column has a cell full of text. I would like all the columns to be the same height as the tallest item in the group. Using UICollectionViewCompositionalLayout I'm having a hard time getting the desired results.
I created a EqualHeightsUICollectionViewCompositionalLayout subcalss to check the cell attributes in layoutAttributesForElements and stores the largest cell height in a row. This seems to work good intially, but when the collectionview invalidates, the cell sizes are not always correct. How can I fix this?
Here is an example project, and here is a stack overflow post
class EqualHeightsUICollectionViewCompositionalLayout: UICollectionViewCompositionalLayout{
var largestDict: [Int: CGFloat] = [:]
let columns = 3
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
let attributes = super.layoutAttributesForElements(in: rect)
if let attributes = attributes {
for attribute in attributes {
let height = attribute.frame.height
let row = attribute.indexPath.row / columns
if height > 1 {
self.largestDict[row] = max(height, largestDict[row] ?? 0)
}
}
}
return attributes
}
override func invalidateLayout() {
super.invalidateLayout()
largestDict.removeAll()
}
}
class TextCell: UICollectionViewCell {
let label = UILabel()
let bottomLabel = UILabel()
let container = UIView()
weak var collectionView: UICollectionView?
override init(frame: CGRect) {
super.init(frame: frame)
configure()
}
required init?(coder: NSCoder) {
fatalError("not implemented")
}
override func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes {
let attribute = super.preferredLayoutAttributesFitting(layoutAttributes)
if let layout = collectionView?.collectionViewLayout as? EqualHeightsUICollectionViewCompositionalLayout{
let row = attribute.indexPath.row / layout.columns
if let height = layout.largestDict[row] {
attribute.frame = .init(origin: attribute.frame.origin, size: .init(width: attribute.frame.width, height: height))
}
}
return attribute
}
private func configure() {
label.numberOfLines = 0
label.font = UIFont.preferredFont(forTextStyle: .title1)
label.backgroundColor = .systemPurple
label.textColor = .white
label.translatesAutoresizingMaskIntoConstraints = false
label.setContentHuggingPriority(.defaultHigh, for: .vertical)
bottomLabel.numberOfLines = 0
bottomLabel.font = UIFont.preferredFont(forTextStyle: .title1)
bottomLabel.text = "Bottom of cell"
bottomLabel.backgroundColor = .systemRed
bottomLabel.textColor = .white
bottomLabel.translatesAutoresizingMaskIntoConstraints = false
bottomLabel.setContentHuggingPriority(.defaultLow, for: .vertical)
contentView.addSubview(label)
contentView.addSubview(bottomLabel)
backgroundColor = .systemBlue.withAlphaComponent(0.75)
let inset = CGFloat(0)
NSLayoutConstraint.activate([
label.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: inset),
label.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -inset),
label.topAnchor.constraint(equalTo: contentView.topAnchor, constant: inset),
bottomLabel.leadingAnchor.constraint(equalTo: label.leadingAnchor),
bottomLabel.trailingAnchor.constraint(equalTo: label.trailingAnchor),
bottomLabel.topAnchor.constraint(equalTo: label.bottomAnchor, constant: inset),
bottomLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -inset),
])
}
}
func createLayout() -> UICollectionViewLayout {
let spacing = CGFloat(10)
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0),
heightDimension: .estimated(1))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0),
heightDimension: .estimated(1))
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitem: item, count: 3)
group.interItemSpacing = .fixed(spacing)
let section = NSCollectionLayoutSection(group: group)
section.interGroupSpacing = spacing
section.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 10, bottom: 0, trailing: 10)
return EqualHeightsUICollectionViewCompositionalLayout(section: section)
}
Is there anyway to hide the details view controller of a UISplitviewController in all circumstances? I have this requirement where the details VC needs to be hidden (or absent) at first and then slide in from the right when an initial selection is made. This needs to be the case even when a large iPad is in full screen mode.
I know I can simply create my own version of this using a view controller with two child view controllers embed and manipulating constraints, however then I lose the push and pop functionally that you automatically get when in a compact size class.
I have a full screen list and want to use the new keyboardLayoutGuide constraint, but by default it uses the safe area inset. How can I disable this so my list goes all the way to the bottom of the screen when the keyboard is not shown?
NSLayoutConstraint.activate([
collectionView.topAnchor.constraint(equalTo: view.topAnchor),
collectionView.bottomAnchor.constraint(equalTo: view.keyboardLayoutGuide.topAnchor),
collectionView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
collectionView.trailingAnchor.constraint(equalTo: view.trailingAnchor)
])
I have a simple UIKit application that has a UITextView in a UICollectionViewCell. The app is designed for iOS/iPadOS and works just fine on those platforms. However, when run on Mac (Designed for iPad) as soon as I start scrolling the collectionview, the cpu usage spikes to ~85% and stays there indefinitely. The only way to lower the cpu is to click outside of the application window, but once it comes to the foreground again, the cpu usage jumps right back up. I've tried running on Mac in Catalyst mode too, but the same problem occurs with slightly less cpu usage (~45%).
Additionally the debugger constantly spits out [API] cannot add handler to 3 from 3 - dropping while scrolling.
Does anyone have an explanation or solutions for this?
I’m using Xcode Version 14.1 (14B47b) on macOS Ventura 13.0 (22A380).
class ViewController: UIViewController {
var dataSource: UICollectionViewDiffableDataSource<Section, String>! = nil
var collectionView: UICollectionView! = nil
var items = Array(0...100).map{"Item \($0)"}
enum Section: String {
case main
}
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.title = "List"
configureCollectionView()
configureDataSource()
applyInitialSnapshot()
}
private func createLayout() -> UICollectionViewLayout {
return UICollectionViewCompositionalLayout { sectionIndex, layoutEnvironment in
let size = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .estimated(100))
let item = NSCollectionLayoutItem(layoutSize: size)
let group = NSCollectionLayoutGroup.horizontal(layoutSize: size, subitems: [item])
return NSCollectionLayoutSection(group: group)
}
}
private func configureCollectionView() {
collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: createLayout())
collectionView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
collectionView.backgroundColor = .systemBackground
view.addSubview(collectionView)
}
private func configureDataSource() {
let cellRegistration = UICollectionView.CellRegistration<TestCell, String> { (cell, indexPath, item) in
cell.configure(title: item, row: indexPath.item)
}
dataSource = UICollectionViewDiffableDataSource<Section, String>(collectionView: collectionView) {
(collectionView, indexPath, identifier) -> UICollectionViewCell? in
return collectionView.dequeueConfiguredReusableCell(using: cellRegistration, for: indexPath, item: identifier)
}
}
private func applyInitialSnapshot() {
var snapshot = NSDiffableDataSourceSnapshot<Section, String>()
snapshot.appendSections([.main])
snapshot.appendItems(items)
dataSource.apply(snapshot, animatingDifferences: false)
}
}
class TestCell: UICollectionViewCell {
private let annotationsTextView = UITextView()
override init(frame: CGRect) {
super.init(frame: frame)
addViews()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func configure(title: String, row: Int) {
annotationsTextView.attributedText = .init(string: "Row: \(row) Item: \(title)", attributes: [.font: UIFont.preferredFont(forTextStyle: .title1)])
}
private func addViews() {
annotationsTextView.isScrollEnabled = false
annotationsTextView.isEditable = false
annotationsTextView.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(annotationsTextView)
NSLayoutConstraint.activate([
annotationsTextView.topAnchor.constraint(equalTo: contentView.topAnchor),
annotationsTextView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor),
annotationsTextView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
annotationsTextView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
])
}
}
When using .accessibilityElement(children: .contain) on a SwiftUI Button, the children do not show up in the accessibility inspector. Instead, the Button is the only element shown and its identifier is a combination of all the children. How can I make only the children identifiers show?
Button {
} label: {
VStack {
Image(systemName: "star")
.accessibilityIdentifier("logo_image")
Text("Subtitle")
.accessibilityIdentifier("subtitle_text")
}
}
.accessibilityElement(children: .contain)
If I remove the button and only use the VStack the elements appear individually. This is what I am trying to achieve while using the Button.
VStack {
Image(systemName: "star")
.accessibilityIdentifier("logo_image")
Text("Subtitle")
.accessibilityIdentifier("subtitle_text")
}
MPMusicPlayerControllers nowPlayingItem no longer seems to be able to change a song. The code use to work but seems to be broken on iOS 16, 17 and now the iOS 18 beta.
When newSong is triggered, the song restarts but it does not change songs. Instead I get the following error: Failed to set now playing item error=<MPMusicPlayerControllerErrorDomain.5 "Unable to play item <MPConcreteMediaItem: 0x9e9f0ef70> 206357861099970620" {}>.
The documentation seems to indicate I’m doing things correctly.
class MusicPlayer {
var songTwo: MPMediaItem?
let player = MPMusicPlayerController.applicationMusicPlayer
func start() async {
await MPMediaLibrary.requestAuthorization()
let myPlaylistsQuery = MPMediaQuery.playlists()
let playlists = myPlaylistsQuery.collections!.filter { $0.items.count > 2}
let playlist = playlists.first!
let songOne = playlist.items.first!
songTwo = playlist.items[1]
player.setQueue(with: playlist)
play(songOne)
}
func newSong() {
guard let songTwo else { return }
play(songTwo)
}
private func play(_ song: MPMediaItem) {
player.stop()
player.nowPlayingItem = song
player.prepareToPlay()
player.play()
}
}
I'm displaying a GKGameCenterViewController after successfully authenticating and on iOS 18.0 and 18.1, I get a black screen. As a sanity check GKLocalPlayer.local.isAuthenticated is also returning true. The same code works just fine on iOS 17. Is there something that needs to be done on iOS 18 and above?