Post

Replies

Boosts

Views

Activity

Operating System availability checks have incorrect behavior on iOSAppOnMac: #available(iOS 15, *) is always true, ProcessInfo().isOperatingSystemAtLeast works as expected
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.
1
0
1.1k
Sep ’21
How to use multiple AVPlayerLayers with one AVPlayer
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 } }
1
0
710
Aug ’21