iOS中忽略动态类型:辅助功能

14

有没有一种方法可以完全忽略iOS应用程序中的动态类型/字体大小设置? 我的意思是是否有一种像 plist 条目这样的方法,以便我可以完全禁用它。我知道我们可以观察通知并在设置更改时重新配置字体。 我正在寻找一个更简单的解决方案。我正在使用 iOS8。 谢谢。


动态类型是你必须积极实现的东西(或者至少在界面构建器中选择)。它不是“只是工作”。 - Fabio Poloni
1
如果我去更改手机设置应用程序中的字体大小,然后回到我的应用程序,字体就会改变。我没有为此做任何事情。 - sole007
你在 Interface Builder 中使用的字体是什么? - Fabio Poloni
没有使用界面构建器/故事板。已经在代码中将字体设置为某个浮点值。 - sole007
1
@FabioPoloni 是的,如果您使用默认的UITableViewCell标签,它会自动工作。 - Laszlo
显示剩余2条评论
4个回答

9
无需交换UIApplication。只需继承UIApplication并提供自己的preferredContentSizeCategory实现即可:
Swift:
class MyApplication: UIApplication {

    override var preferredContentSizeCategory: UIContentSizeCategory {
        get { return UIContentSizeCategory.large }
    }
}

UIApplicationMain(
    CommandLine.argc,
    CommandLine.unsafeArgv,
    NSStringFromClass(MyApplication.self),
    NSStringFromClass(AppDelegate.self)
)

Objective-C:

@interface MyApplication : UIApplication
@end

@implementation MyApplication

- (UIContentSizeCategory) preferredContentSizeCategory
{
    return UIContentSizeCategoryLarge;
}

@end

int main(int argc, char * argv[]) {
    @autoreleasepool {
        return UIApplicationMain(argc, argv, NSStringFromClass([MyApplication class]), NSStringFromClass([AppDelegate class]));
    }
}

1
适用于iOS 11。在实现这个过程中,我发现我一直在使用“更大的文本”滑块设置为UIContentSizeCategoryExtraLarge(比默认值高一个尺寸)在我的iPhone上进行所有开发工作。在设置中没有办法知道默认值或重置为默认值(除非使用新的模拟器)。即使关闭开关,“更大的文本”滑块也始终处于活动状态。当开关打开时,滑块具有更大的范围。 - Jeff
简短而有效。在iOS 13中对我起作用。 - DenNukem

5
在你的AppDelegate中添加以下内容:
#import <objc/runtime.h>

@implementation AppDelegate

NSString* swizzled_preferredContentSizeCategory(id self, SEL _cmd)
{
    return UIContentSizeCategoryLarge;  // Set category you prefer, Large being iOS' default.
}

- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
    Method method = class_getInstanceMethod([UIApplication class], @selector(preferredContentSizeCategory));
    method_setImplementation(method, (IMP)swizzled_preferredContentSizeCategory);

    ...
}

@zeeple 应该是可以的。我只有 Obj-C 版本。我试图快速转换为 Swift 2.2,但这需要解决各种典型的 Swift 选择器和类型相关问题;现在没有时间做这个。请用你的 Swift 版本发布一个答案。 - meaning-matters
这个解决方案只在首次启动应用程序时有效。如果用户偶然修改了字体大小并立即恢复应用程序,则此解决方案将无法覆盖该场景。 :( - Gabcvit

4

请给@gebirgsbärbel的回答提供Swift 4的修复方法。 在Objective-C中,“preferredContentSizeCategory”是一个方法,但在Swift中它是一个只读变量。所以在你的AppDelegate中应该像这样:

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    // MARK: - UIApplicationDelegate

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {

        UIApplication.classInit

        self.window = UIWindow(frame: UIScreen.main.bounds)
        ...
        self.window?.makeKeyAndVisible()
        return true
    }
}

// MARK: - Fix Dynamic Type

extension UIApplication {

    static let classInit: Void = {
        method_exchangeImplementations(
            class_getInstanceMethod(UIApplication.self, #selector(getter: fixedPreferredContentSizeCategory))!,
            class_getInstanceMethod(UIApplication.self, #selector(getter: preferredContentSizeCategory))!
        )
    }()

    @objc
    var fixedPreferredContentSizeCategory: UIContentSizeCategory {
        return .large
    }
}

3

@meaning-matters的答案在Swift中的等效写法如下:

在您的AppDelegate中:

@objc func swizzled_preferredContentSizeCategory() -> UIContentSizeCategory {
    return UIContentSizeCategory.small
}

open func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    let originalMethod = class_getInstanceMethod(UIApplication.self, #selector(preferredContentSizeCategory))
    let swizzledMethod = class_getInstanceMethod(UIApplication.self, #selector(swizzled_preferredContentSizeCategory))
    method_exchangeImplementations(originalMethod, swizzled_preferredContentSizeCategory)
}

当我尝试使用它时,我会得到编译器错误:Use of unresolved identifier 'preferredContentSizeCategory'。是否还需要其他东西才能使其正常工作? - John Montgomery
2
我的最佳猜测是将选择器更改为 getter: UIApplication.preferredContentSizeCategoryMyAppDelegate.swizzled_preferredContentSizeCategory,以及其他一些更改,这样可以清除编译器错误,但在运行时似乎没有任何作用。 - John Montgomery

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接