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

Introduce setupPredefinedEnvironmentListeners to allow setup build-in environment listener #3

Merged
Merged
Show file tree
Hide file tree
Changes from all 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
15 changes: 7 additions & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,15 @@ on:
workflow_dispatch:

jobs:
tests:
runs-on: macos-12
strategy:
matrix:
xcode: [13.3]
tests:
runs-on: macos-13
steps:
- uses: actions/checkout@v2
- name: install xcbeautify
run: brew install xcbeautify
- name: Select Xcode ${{ matrix.xcode }}
run: sudo xcode-select -s /Applications/Xcode_${{ matrix.xcode }}.app
- name: Select Xcode Version
uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: "15.2"
- name: Run tests
run: xcodebuild test -project ./XcodeProject/UIEnvironment.xcodeproj -destination platform="iOS Simulator,name=iPhone 11 Pro Max" -scheme "App" CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO | xcbeautify
run: xcodebuild test -project ./XcodeProject/UIEnvironment.xcodeproj -destination platform="iOS Simulator,name=iPhone 15 Pro Max" -scheme "App" CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO | xcbeautify
2 changes: 1 addition & 1 deletion .github/workflows/documentation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ on:

jobs:
build:
runs-on: macos-12
runs-on: macos-13
steps:
- name: Checkout Package
uses: actions/checkout@v2
Expand Down
23 changes: 23 additions & 0 deletions Package.resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"pins" : [
{
"identity" : "libffi",
"kind" : "remoteSourceControl",
"location" : "https://github.com/623637646/libffi.git",
"state" : {
"revision" : "bc1dac0c1b522539f21fc28fe1f7e07bb7c2fbd5",
"version" : "3.4.5"
}
},
{
"identity" : "swifthook",
"kind" : "remoteSourceControl",
"location" : "https://github.com/623637646/SwiftHook",
"state" : {
"revision" : "474f80132a3a4e74b3f8a5b87b707d74de387769",
"version" : "3.5.2"
}
}
],
"version" : 2
}
7 changes: 5 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,13 @@ let package = Package(
targets: ["UIEnvironment"]),
],
dependencies: [
.package(url: "https://github.com/623637646/SwiftHook", from: "3.5.2")
],
targets: [
.target(
name: "UIEnvironment",
dependencies: []),
dependencies: [
.product(name: "SwiftHook", package: "SwiftHook")
]),
]
)
)
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ extension UIEnvironmentValues {
set { self[LocaleEnvironmentKey.self] = newValue }
}

internal static let setupCurrentLocaleListener: Void = {
public static let setupCurrentLocaleListener: Void = {
NotificationCenter.default.addObserver(
forName: NSLocale.currentLocaleDidChangeNotification,
object: nil,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ extension UIEnvironmentValues {
set { self[SizeCategoryEnvironmentKey.self] = newValue }
}

internal static let setupSizeCategoryListener: Void = {
public static let setupSizeCategoryListener: Void = {
NotificationCenter.default.addObserver(
forName: UIContentSizeCategory.didChangeNotification,
object: nil,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,21 +90,19 @@ extension UIEnvironmentable {
}
}

extension UIScreen {
internal static let setupTraitCollectionListener: Void = {
guard let originalMethod = class_getInstanceMethod(
UIScreen.self,
#selector(traitCollectionDidChange(_:))
),
let swizzledMethod = class_getInstanceMethod(
UIScreen.self,
#selector(swizzled_traitCollectionDidChange(_:))
)
else {
return
}
import SwiftHook

method_exchangeImplementations(originalMethod, swizzledMethod)
extension UIScreen {
public static let setupTraitCollectionListener: Void = {
_ = try? hookBefore(
targetClass: UIScreen.self,
selector: #selector(UIScreen.traitCollectionDidChange(_:)),
closure: {
UIApplication.shared.forEachWindow {
$0.environment(\.userInterfaceStyle, UITraitCollection.current.userInterfaceStyle)
}
}
)
}()

@objc private func swizzled_traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
Expand All @@ -116,24 +114,13 @@ extension UIScreen {
}

extension UIWindow {
internal static let setupOverrideUserInterfaceListener: Void = {
guard let originalMethod = class_getInstanceMethod(
UIWindow.self,
#selector(setter: UIWindow.overrideUserInterfaceStyle)
),
let swizzledMethod = class_getInstanceMethod(
UIWindow.self,
#selector(UIWindow.swizzled_setOverrideUserInterfaceStyle(_:))
)
else {
return
}

method_exchangeImplementations(originalMethod, swizzledMethod)
public static let setupOverrideUserInterfaceListener: Void = {
_ = try? hookBefore(
targetClass: UIWindow.self,
selector: #selector(setter: UIWindow.overrideUserInterfaceStyle),
closure: { object, sel, style in
object.environment(\.userInterfaceStyle, style)
} as @convention(block) (UIWindow, Selector, UIUserInterfaceStyle) -> Void
)
}()

@objc private func swizzled_setOverrideUserInterfaceStyle(_ style: UIUserInterfaceStyle) {
swizzled_setOverrideUserInterfaceStyle(style)
environment(\.userInterfaceStyle, style)
}
}
7 changes: 3 additions & 4 deletions Sources/UIEnvironment/UIEnvironment.swift
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,9 @@ import UIKit
/// Creates an environment property to read the specified key path.
/// - Parameter keyPath: A key path to a specific resulting value.
public init(_ keyPath: KeyPath<UIEnvironmentValues, Value>) {
UIScreen.setupTraitCollectionListener
UIWindow.setupOverrideUserInterfaceListener
UIEnvironmentValues.setupCurrentLocaleListener
UIEnvironmentValues.setupSizeCategoryListener
if let setupPredefinedEnvironmentListeners = UIEnvironmentValues.setupPredefinedEnvironmentListeners(keyPath) {
setupPredefinedEnvironmentListeners()
}
self.keyPath = keyPath
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import Foundation
import UIKit

extension UIEnvironmentValues {
/// A closure that is called once for each instance of UIEnvironment passing it's `keyPath`.
/// As such, any setup or initialization that has to happens only once, has to be handled internally within this closure.
///
/// Use this property to disable or override default environment listeners.
///
public static var setupPredefinedEnvironmentListeners: (_ keyPath: AnyKeyPath) -> (() -> Void)? = { _ in
{
UIScreen.setupTraitCollectionListener
UIWindow.setupOverrideUserInterfaceListener
UIEnvironmentValues.setupCurrentLocaleListener
UIEnvironmentValues.setupSizeCategoryListener
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"pins" : [
{
"identity" : "libffi",
"kind" : "remoteSourceControl",
"location" : "https://github.com/623637646/libffi.git",
"state" : {
"revision" : "bc1dac0c1b522539f21fc28fe1f7e07bb7c2fbd5",
"version" : "3.4.5"
}
},
{
"identity" : "swifthook",
"kind" : "remoteSourceControl",
"location" : "https://github.com/623637646/SwiftHook",
"state" : {
"revision" : "474f80132a3a4e74b3f8a5b87b707d74de387769",
"version" : "3.5.2"
}
}
],
"version" : 2
}
Loading