Skip to content

Commit

Permalink
Convert NBSMockedApplication from Objc to Swift
Browse files Browse the repository at this point in the history
  • Loading branch information
dogo committed Sep 5, 2021
1 parent f8df3eb commit 2dabd9a
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 192 deletions.
12 changes: 4 additions & 8 deletions Nimble_Snapshots.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,8 @@
D47CB5FA1EC9973C00D5588D /* XCTestObservationCenter+CurrentTestCaseTracker.m in Sources */ = {isa = PBXBuildFile; fileRef = D47CB5F81EC9973C00D5588D /* XCTestObservationCenter+CurrentTestCaseTracker.m */; };
D4F7D47E1ED764CD00B4D2FE /* DynamicSizeSnapshot.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4F7D4781ED764CD00B4D2FE /* DynamicSizeSnapshot.swift */; };
D4F7D47F1ED764CD00B4D2FE /* HaveValidDynamicTypeSnapshot.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4F7D47A1ED764CD00B4D2FE /* HaveValidDynamicTypeSnapshot.swift */; };
D4F7D4801ED764CD00B4D2FE /* NBSMockedApplication.h in Headers */ = {isa = PBXBuildFile; fileRef = D4F7D47B1ED764CD00B4D2FE /* NBSMockedApplication.h */; settings = {ATTRIBUTES = (Public, ); }; };
D4F7D4811ED764CD00B4D2FE /* NBSMockedApplication.m in Sources */ = {isa = PBXBuildFile; fileRef = D4F7D47C1ED764CD00B4D2FE /* NBSMockedApplication.m */; };
D4F7D4821ED764CD00B4D2FE /* PrettyDynamicTypeSyntax.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4F7D47D1ED764CD00B4D2FE /* PrettyDynamicTypeSyntax.swift */; };
DD83832926E555BC0040266F /* NBSMockedApplication.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD83832826E555BC0040266F /* NBSMockedApplication.swift */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
Expand All @@ -35,9 +34,8 @@
D47CB5F81EC9973C00D5588D /* XCTestObservationCenter+CurrentTestCaseTracker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "XCTestObservationCenter+CurrentTestCaseTracker.m"; sourceTree = "<group>"; };
D4F7D4781ED764CD00B4D2FE /* DynamicSizeSnapshot.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DynamicSizeSnapshot.swift; sourceTree = "<group>"; };
D4F7D47A1ED764CD00B4D2FE /* HaveValidDynamicTypeSnapshot.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HaveValidDynamicTypeSnapshot.swift; sourceTree = "<group>"; };
D4F7D47B1ED764CD00B4D2FE /* NBSMockedApplication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NBSMockedApplication.h; sourceTree = "<group>"; };
D4F7D47C1ED764CD00B4D2FE /* NBSMockedApplication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NBSMockedApplication.m; sourceTree = "<group>"; };
D4F7D47D1ED764CD00B4D2FE /* PrettyDynamicTypeSyntax.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PrettyDynamicTypeSyntax.swift; sourceTree = "<group>"; };
DD83832826E555BC0040266F /* NBSMockedApplication.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NBSMockedApplication.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -98,9 +96,8 @@
D4F7D4791ED764CD00B4D2FE /* DynamicType */ = {
isa = PBXGroup;
children = (
DD83832826E555BC0040266F /* NBSMockedApplication.swift */,
D4F7D47A1ED764CD00B4D2FE /* HaveValidDynamicTypeSnapshot.swift */,
D4F7D47B1ED764CD00B4D2FE /* NBSMockedApplication.h */,
D4F7D47C1ED764CD00B4D2FE /* NBSMockedApplication.m */,
D4F7D47D1ED764CD00B4D2FE /* PrettyDynamicTypeSyntax.swift */,
);
path = DynamicType;
Expand All @@ -114,7 +111,6 @@
buildActionMask = 2147483647;
files = (
D47CB5F91EC9973C00D5588D /* XCTestObservationCenter+CurrentTestCaseTracker.h in Headers */,
D4F7D4801ED764CD00B4D2FE /* NBSMockedApplication.h in Headers */,
095B47711D4773F000880922 /* Nimble_Snapshots.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -207,13 +203,13 @@
buildActionMask = 2147483647;
files = (
095B47911D47794300880922 /* PrettySyntax.swift in Sources */,
D4F7D4811ED764CD00B4D2FE /* NBSMockedApplication.m in Sources */,
D47CB5FA1EC9973C00D5588D /* XCTestObservationCenter+CurrentTestCaseTracker.m in Sources */,
D4F7D47F1ED764CD00B4D2FE /* HaveValidDynamicTypeSnapshot.swift in Sources */,
095B478F1D47794300880922 /* HaveValidSnapshot.swift in Sources */,
095B47901D47794300880922 /* CurrentTestCaseTracker.swift in Sources */,
D4F7D4821ED764CD00B4D2FE /* PrettyDynamicTypeSyntax.swift in Sources */,
D4F7D47E1ED764CD00B4D2FE /* DynamicSizeSnapshot.swift in Sources */,
DD83832926E555BC0040266F /* NBSMockedApplication.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
13 changes: 0 additions & 13 deletions Nimble_Snapshots/DynamicType/NBSMockedApplication.h

This file was deleted.

160 changes: 0 additions & 160 deletions Nimble_Snapshots/DynamicType/NBSMockedApplication.m

This file was deleted.

150 changes: 150 additions & 0 deletions Nimble_Snapshots/DynamicType/NBSMockedApplication.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
import Foundation
import UIKit

public class NBSMockedApplication {

private var isSwizzled: Bool = false

public init() {}

deinit {
stopMockingPreferredContentSizeCategory()
}

/* On iOS 9, +[UIFont preferredFontForTextStyle:] uses -[UIApplication preferredContentSizeCategory]
to get the content size category. However, this changed on iOS 10. While I haven't found what UIFont uses to get
the current category, swizzling preferredFontForTextStyle: to use +[UIFont preferredFontForTextStyle: compatibleWithTraitCollection:]
(only available on iOS >= 10), passing an UITraitCollection with the desired contentSizeCategory.
*/
public func mockPreferredContentSizeCategory(_ category: UIContentSizeCategory) {

UIApplication.shared.nbs_preferredContentSizeCategory = category

if !isSwizzled {
UIApplication.nbs_swizzle()
UIFont.nbs_swizzle()
UITraitCollection.nbs_swizzle()
isSwizzled = true
}
NotificationCenter.default.post(name: UIContentSizeCategory.didChangeNotification,
object: UIApplication.shared,
userInfo: [UIContentSizeCategory.newValueUserInfoKey: category])
}

public func stopMockingPreferredContentSizeCategory() {
if isSwizzled {
UIApplication.nbs_swizzle()
UIFont.nbs_swizzle()
UITraitCollection.nbs_swizzle()
isSwizzled = false
}
}
}

extension UIFont {

static func nbs_swizzle() {
if !UITraitCollection.instancesRespond(to: #selector(getter: UIApplication.preferredContentSizeCategory)) {
return
}

let selector = #selector(UIFont.preferredFont(forTextStyle:))
let replacedSelector = #selector(nbs_preferredFont(for:))

let originalMethod = class_getClassMethod(self, selector)
let extendedMethod = class_getClassMethod(self, replacedSelector)
if let originalMethod = originalMethod, let extendedMethod = extendedMethod {
method_exchangeImplementations(originalMethod, extendedMethod)
}
}

@objc
static func nbs_preferredFont(for style: UIFont.TextStyle) -> UIFont? {
let category = UIApplication.shared.preferredContentSizeCategory

if #available(iOS 10.0, tvOS 10.0, *) {
let categoryTrait = UITraitCollection(preferredContentSizeCategory: category)
return UIFont.preferredFont(forTextStyle: style, compatibleWith: categoryTrait)
}
return UIFont.preferredFont(forTextStyle: style)
}
}

extension UIApplication {

struct AssociatedKeys {
static var contentSizeCategory: UInt8 = 0
}

@objc var nbs_preferredContentSizeCategory: UIContentSizeCategory? {
get {
return objc_getAssociatedObject(self, &AssociatedKeys.contentSizeCategory) as? UIContentSizeCategory
}
set {
objc_setAssociatedObject(self, &AssociatedKeys.contentSizeCategory, newValue, .OBJC_ASSOCIATION_COPY_NONATOMIC)
}
}

static func nbs_swizzle() {
let selector = #selector(getter: UIApplication.preferredContentSizeCategory)
let replacedSelector = #selector(getter: self.nbs_preferredContentSizeCategory)

let originalMethod = class_getInstanceMethod(self, selector)
let extendedMethod = class_getInstanceMethod(self, replacedSelector)
if let originalMethod = originalMethod, let extendedMethod = extendedMethod {
method_exchangeImplementations(originalMethod, extendedMethod)
}
}
}

extension UITraitCollection {

@objc
func nbs_preferredContentSizeCategory() -> UIContentSizeCategory {
return UIApplication.shared.preferredContentSizeCategory
}

@objc
func nbs__changedContentSizeCategory(fromTraitCollection arg: Any?) -> Bool {
return true
}

static func nbs_swizzlePreferredContentSizeCategory() {
let selector = #selector(getter: UIApplication.preferredContentSizeCategory)

if !self.instancesRespond(to: selector) {
return
}

let replacedSelector = #selector(getter: UIApplication.nbs_preferredContentSizeCategory)

let originalMethod = class_getInstanceMethod(self, selector)
let extendedMethod = class_getInstanceMethod(self, replacedSelector)

if let originalMethod = originalMethod, let extendedMethod = extendedMethod {
method_exchangeImplementations(originalMethod, extendedMethod)
}
}

static func nbs_swizzleChangedContentSizeCategoryFromTraitCollection() {
let selector = sel_registerName("_changedContentSizeCategoryFromTraitCollection:")

if !self.instancesRespond(to: selector) {
return
}

let replacedSelector = #selector(nbs__changedContentSizeCategory(fromTraitCollection:))

let originalMethod = class_getInstanceMethod(self, selector)
let extendedMethod = class_getInstanceMethod(self, replacedSelector)

if let originalMethod = originalMethod, let extendedMethod = extendedMethod {
method_exchangeImplementations(originalMethod, extendedMethod)
}
}

static func nbs_swizzle() {
nbs_swizzlePreferredContentSizeCategory()
nbs_swizzleChangedContentSizeCategoryFromTraitCollection()
}
}
Loading

0 comments on commit 2dabd9a

Please sign in to comment.