Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove iOS 15 support #2042

Merged
merged 4 commits into from
Jun 7, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion MicrosoftFluentUI.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Pod::Spec.new do |s|

# iOS

s.ios.deployment_target = "15.0"
s.ios.deployment_target = "16.0"

s.subspec 'Avatar_ios' do |avatar_ios|
avatar_ios.platform = :ios
Expand Down
6 changes: 3 additions & 3 deletions ios/FluentUI.Demo/FluentUI.Demo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1087,7 +1087,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DOGFOOD;
Expand Down Expand Up @@ -1187,7 +1187,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
Expand Down Expand Up @@ -1247,7 +1247,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,29 +25,15 @@ struct AliasColorTokensDemoView: View {
@Environment(\.fluentTheme) var fluentTheme: FluentTheme

var body: some View {
if #available(iOS 16.0, *) {
formContent.scrollContentBackground(.hidden)
} else {
formContent.onAppear {
UITableView.appearance().backgroundColor = .clear
}
.onDisappear {
UITableView.appearance().backgroundColor = .systemGroupedBackground
}
}
}

@ViewBuilder
var formContent: some View {
Form {
FluentList {
ForEach(AliasColorTokensDemoSection.allCases, id: \.self) { demoSection in
// No need for SwiftUI section in SwiftUI demo!
if demoSection != .swiftUI {
colorSection(demoSection)
}
}
}
.background(fluentTheme.swiftUIColor(.backgroundCanvas))
.fluentListStyle(.insetGrouped)
}

@ViewBuilder
Expand Down
2 changes: 1 addition & 1 deletion ios/FluentUI/Core/ControlHostingView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ open class ControlHostingView: UIView {
/// - Parameter controlView: An `AnyView`-wrapped component to host.
public init(_ controlView: AnyView) {
hostingController = FluentThemedHostingController.init(rootView: controlView)
hostingController.disableSafeAreaInsets()
hostingController.sizingOptions = [.intrinsicContentSize]
super.init(frame: .zero)

self.configureHostedView()
Expand Down
72 changes: 1 addition & 71 deletions ios/FluentUI/Core/FluentThemedHostingController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,41 +6,8 @@
import UIKit
import SwiftUI

extension UIView {

/// Associated keys created for the added UIView stored properties.
struct AssociatedKeys {
static var shouldUseZeroEdgeInsets: UInt8 = 0
}

/// Adds a stored property to the UIView that defines whether the UIView should return UIEdgeInsets.zero from its safeAreaInsets property.
/// This property is intended to be used by the UIHostingView class, which is a private subclass of UIView in the SwiftUI Framework.
var shouldUseZeroEdgeInsets: Bool {
get {
return objc_getAssociatedObject(self, &AssociatedKeys.shouldUseZeroEdgeInsets) as? Bool ?? false
}
set {
objc_setAssociatedObject(self, &AssociatedKeys.shouldUseZeroEdgeInsets, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}

/// Computed property that will be swizzled with UIView.safeAreaInsets by exchange of implementations.
/// This swizzling is meant to be used in UIHostingView instances which are private in the SwiftUI framework.
/// Do not call this property getter directly.
@objc var customSafeAreaInsets: UIEdgeInsets {
if shouldUseZeroEdgeInsets {
return .zero
}

// Because this property will be swizzled with UIView.safeAreaInsets by exchanging
// implementations, this call makes sure to call it by this property's name which
// will contain the original implementation of UIView.safeAreaInsets.
return self.customSafeAreaInsets
}
}

/// FluentUI specific implementation of the UIHostingController. This is primarily useful for adding `FluentTheme` observation
/// to any wrapped Fluent controls. Additionally, this class adds a workaround for disabling safeAreaInsets for its view on iOS 15.
/// to any wrapped Fluent controls.
open class FluentThemedHostingController: UIHostingController<AnyView> {

@MainActor required dynamic public override init(rootView: AnyView) {
Expand Down Expand Up @@ -68,13 +35,6 @@ open class FluentThemedHostingController: UIHostingController<AnyView> {
}
}

/// iOS 15.0 fix for UIHostingController that does not automatically resize to hug subviews
open override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()

view.setNeedsUpdateConstraints()
}

// MARK: - Theme management

@objc private func themeDidChange(_ notification: Notification) {
Expand All @@ -101,33 +61,3 @@ open class FluentThemedHostingController: UIHostingController<AnyView> {

private var controlView: AnyView
}

// MARK: - Safe Area Inset swizzling

extension FluentThemedHostingController {
/// Static constant that will be guaranteed to have its initialization executed only once during the lifetime of the application.
private static let swizzleSafeAreaInsetsOnce: Void = {
// A FluentUIHostingController instance needs to be created so that the class type for the private UIHostingViewwe can be retrived.
let hostingControllerViewClass: AnyClass = FluentThemedHostingController(rootView: AnyView(EmptyView())).view.classForCoder

guard let originalMethod = class_getInstanceMethod(hostingControllerViewClass, #selector(getter: UIView.safeAreaInsets)),
let swizzledMethod = class_getInstanceMethod(hostingControllerViewClass, #selector(getter: UIView.customSafeAreaInsets)) else {
preconditionFailure("UIHostingController zeroSafeAreaInsets swizzling failed.")
}

method_exchangeImplementations(originalMethod, swizzledMethod)
}()

/// Disables the UIHostingController's view safe area insets by swizzling the UIView.safeAreaInsets property and returning UIEdgeInsets.zero if the UIView.shouldUseZeroEdgeInsets is true.
/// This is a known issue and it's currently tracked by Radar bug FB8176223 - https://openradar.appspot.com/FB8176223
func disableSafeAreaInsets() {
// We no longer need the workarounds from `FluentUIHostingController` in
// iOS 16, but we still need it for 14 and 15.
if #unavailable(iOS 16) {
view.shouldUseZeroEdgeInsets = true
_ = FluentThemedHostingController.swizzleSafeAreaInsetsOnce
} else {
sizingOptions = [.intrinsicContentSize]
}
}
}
3 changes: 3 additions & 0 deletions ios/FluentUI/List/FluentList.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,14 @@ public struct FluentList<ListContent: View>: View {
case .insetGrouped:
list
.listStyle(.insetGrouped)
.scrollContentBackground(.hidden)
mischreiber marked this conversation as resolved.
Show resolved Hide resolved
// TODO: Directly use `FluentList` token set instead of `ListItem`
.background(ListItem.listBackgroundColor(for: .grouped))
.listStyling_iOS17()
case .plain:
list
.listStyle(.plain)
.scrollContentBackground(.hidden)
// TODO: Directly use `FluentList` token set instead of `ListItem`
.background(ListItem.listBackgroundColor(for: .plain))
}
Expand All @@ -66,6 +68,7 @@ public struct FluentList<ListContent: View>: View {
/// Content to render inside the list
private var content: () -> ListContent

@Environment(\.fluentTheme) private var fluentTheme: FluentTheme
}

// MARK: - Environment
Expand Down
1 change: 0 additions & 1 deletion ios/FluentUI/Pill Button Bar/PillButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,6 @@ open class PillButton: UIButton, TokenizedControlInternal {
updateAttributedTitle()
}

@available(iOS 15, *)
private func updateAttributedTitle() {
let itemTitle = pillBarItem.title
var attributedTitle = AttributedString(itemTitle)
Expand Down
2 changes: 1 addition & 1 deletion ios/xcode/FluentUI_common.xcconfig
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ GCC_WARN_UNDECLARED_SELECTOR = YES
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE
GCC_WARN_UNUSED_FUNCTION = YES
GCC_WARN_UNUSED_VARIABLE = YES
IPHONEOS_DEPLOYMENT_TARGET = 15.0
IPHONEOS_DEPLOYMENT_TARGET = 16.0
SDKROOT = iphoneos
SUPPORTED_PLATFORMS = iphoneos iphonesimulator xros xrsimulator
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO
Expand Down
Loading