Apple Silicon computers support running iOS apps. The property iOSAppOnMac of ProcessInfo is true for these apps. Checks like #available(iOS 15, *) are used to only access new APIs on operating systems that support them.
For iOSAppOnMac apps on Big Sur #available(iOS 15, *) evaluates to true despite ProcessInfo().isOperatingSystemAtLeast(.init(majorVersion: 15, minorVersion: 0, patchVersion: 0) evaluating to false. So without an additional check code like the example below crashes with an unrecognized selector exception.
Steps to reproduce:
Use an API only available for iOS 15 e.g. UITabBar.scrollEdgeAppearance
Use #available(iOS 15, *) as condition
Code compiles, but crashes at runtime due to unrecognized selector on an iOSAppOnMac Big Sur device
Workaround:
Add ProcessInfo().isOperatingSystemAtLeast(.init(majorVersion: 15, minorVersion: 0, patchVersion: 0)) as condition.
Code sample from our app:
if
#available(iOS 15, *),
ProcessInfo().isOperatingSystemAtLeast(.init(majorVersion: 15, minorVersion: 0, patchVersion: 0))
{
let tabBarScrollEdgeAppearance = tabBar.standardAppearance
// ...
tabBar.scrollEdgeAppearance = tabBarScrollEdgeAppearance
}
Expectation:
I expect #available(iOS 15, *) to evaluate to false on iOSAppOnMac processes running Big Sur. Or in general, if the operating system major version returned by ProcessInfo is x then #available(iOS x+1, *) should be false.
Actual behavior:
#available(iOS x, *) always evaluates to true on iOSAppOnMac processes potentially causing crashing by using unavailable APIs.
Post
Replies
Boosts
Views
Activity
When using multiple AVPlayerLayer instances connected to one AVPlayer instance in different view controllers the video freezes on simulators. Unless each AVPlayerLayer that becomes "invisible" after a view controller transition (e.g. viewDidDisappear) is detached from the player. This approach without detaching works fine on iOS devices.
Steps:
Download the sample project from https://github.com/KaiOelfke/MultiplePlayerLayers
Run on an iOS simulator
Switch to the second tab
Expectation: Video is playing.
Actual results: Video frame is frozen. Audio plays. Switching tabs results in a few frames being played before freezing again.
Run on an iOS device
Switch to the second tab
Switch tabs a few times
The app behaves as expected. Both player views play the video normally.
The different behavior on the simulator can be fixed by detaching the player from the AVPlayerLayer in ViewController.viewDidDisappear(). It seems that, if at least one attached player view is regarded as "invisible" by iOS the video stops to play on the simulator.
The usecase is an app with multiple tabs and a miniplayer bar (including a small video layer) on top of the tab bar similar to the Apple Music app plus a modally shown full screen player view. Each tab has its own miniplayer AVPlayerLayer.
Is this a simulator bug?
What's the recommended way to implement multiple AVPlayerLayer instances in various parts of the view hierarchy?
// ViewController.swift
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// as soon as the second VC becomes visible and the player view is attached the issue occurs
VideoController.shared.attachPlayerView(playerView)
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
// detaching here solves the issue
// VideoController.shared.detachPlayerView(playerView)
}
//VideoController.swift
func attachPlayerView(_ playerView: PlayerView) {
playerView.player = player
}
func detachPlayerView(_ playerView: PlayerView) {
playerView.player = nil
}
//PlayerView.swift
var player: AVPlayer? {
get {
playerLayer?.player
}
set {
playerLayer?.player = newValue
}
}