Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Disabling Dynamic Type in Swift

I have a Sprite Kit based game that uses a UIView within one of the scenes, and I do that so that I can take advantage of the UITableViewController to present a game settings screen.

The difficulty I am running into is that when a user sets their iPad system accessibility settings to use (extra) large type, the text within the UITableView is too large for the cells and it looks just plain silly.

What I would like to do is straight up disable the dynamic type within the app so it always displays the same sized type in the cells.

I have found another similar posting (here) but the response offers an Objective-C response:

#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);

    ...
}

I need to do this in Swift.

What is the correct way to do this same thing in Swift in Xcode 7+ ?

like image 306
zeeple Avatar asked Aug 02 '16 03:08

zeeple


2 Answers

Thanks @zeeple for the solution. Here is the answer to the original question:

"preferredContentSizeCategory" in Objective-C is a method, but in Swift it is a read-only variable.

So in your AppDelegate is like this:

@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
    }
}
like image 80
LQ Ruan Avatar answered Oct 23 '22 03:10

LQ Ruan


Okay, first let me say this: while I am happy that I was able to quickly find a way to accommodate the dynamic text provided by the iOS accessibility settings (which I will show the code for in a sec) I think it is still important to get an answer to the original question.

That said, here is what I did to the table view code to respect the larger type that some users need. It was a two step process. First, add:

tableView.estimatedRowHeight = 44.0
tableView.rowHeight = UITableViewAutomaticDimension

to the viewDidLoad method. Then, in the cellForRowAtIndexPath method, add the following before you return the cell:

cell.textLabel!.numberOfLines = 0

Good luck folks, and please add an answer to the original question if you have one :)

like image 22
zeeple Avatar answered Oct 23 '22 03:10

zeeple