我正在创建的框架中的XCTest期间无法加载自定义字体

Rom*_*lTJ 3 fonts ios xctest swift ios9

我正在创建一个新的私有框架,其中包含与Cocoapods一起使用的应用程序之间的通用代码。我想在其中添加我们用于应用程序的字体。我以常规方式添加字体(创建了Resources文件夹,拖放并复制了字体,在Info.plist中添加了条目,将字体添加到了Font Book中),我可以在情节提要中看到并使用它们:

在此处输入图片说明

我的字体类如下所示:

import UIKit

class USDFont: UIFont {

    let name = "Texta-"

    //Font weights.
    enum USDFontWeight: Int {
        case Thin
        case Light
        case Book
        case Regular
        case Medium
        case Bold
        case Heavy
        case Black
    }

    //Font scales. Goes from -2 to 9.
    var USDFontScaleFactor: [String: CGFloat] =
        ["UIContentSizeCategoryExtraSmall": -2,
         "UIContentSizeCategorySmall": -1,
         "UIContentSizeCategoryMedium": 0,
         "UIContentSizeCategoryLarge": 1,
         "UIContentSizeCategoryExtraLarge": 2,
         "UIContentSizeCategoryExtraExtraLarge": 3,
         "UIContentSizeCategoryExtraExtraExtraLarge": 4,
         "UIContentSizeCategoryAccessibilityMedium": 5,
         "UIContentSizeCategoryAccessibilityLarge": 6,
         "UIContentSizeCategoryAccessibilityExtraLarge": 7,
         "UIContentSizeCategoryAccessibilityExtraExtraLarge": 8,
         "UIContentSizeCategoryAccessibilityExtraExtraExtraLarge": 9]

    func iconFontWithSize(fontSize: CGFloat, dynamic: Bool) -> UIFont? {
        let pointSize = fontSizeWithBaseFontSize(fontSize, dynamic: dynamic)
        return UIFont(name: "Insight-Icons", size: pointSize)
    }

    func fontWithFontSize(fontSize: CGFloat, weight fontWeight: USDFontWeight, italic: Bool) -> UIFont {
        var fontName: String = ""
        if italic {
           fontName = "\(name)\(fontWeight)It"
        } else {
            fontName = "\(name)\(fontWeight)"
        }

        return UIFont(name: fontName, size: fontSize)!
    }

    func fontWithBaseFontSize(baseFontSize: CGFloat, weight fontWeight: USDFontWeight, italic: Bool, dynamic: Bool) -> UIFont {
        let fontSize = fontSizeWithBaseFontSize(baseFontSize, dynamic: dynamic)
        return fontWithFontSize(fontSize, weight: fontWeight, italic: italic)
    }

    func fontSizeWithBaseFontSize(baseFontSize: CGFloat, dynamic: Bool) -> CGFloat {
        if dynamic {
            if let fontSizeFactor = USDFontScaleFactor[UIApplication.sharedApplication().preferredContentSizeCategory] {
                return baseFontSize + (fontSizeFactor * 0.8)
            }
        }
        return baseFontSize
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,在此框架的单元测试中,我进行了以下测试:

func testUSDFont() {
        let myFont = USDFont()

        //Check which fonts available
        for family: String in UIFont.familyNames()
        {
            print("\(family)")
            for names: String in UIFont.fontNamesForFamilyName(family)
            {
                print("== \(names)")
            }
        }

        let insightIcons = myFont.iconFontWithSize(20.0, dynamic: true)
        print("------ INSIGHT ICONS: \(insightIcons) ------")
        XCTAssert(true, "True")
    }
Run Code Online (Sandbox Code Playgroud)

在XCTest期间,我的Insight-Icons字体和Texta字体均不可用。当我尝试加载它们时,我得到零。当我尝试使用UIFont.familyNames()打印它们时,没有看到我的自定义字体。我想念什么?

Rom*_*lTJ 5

通过将字体文件作为数据加载,然后使用CGFontCreateWithDataProvider创建字体,我能够解决此问题。这是我的loadCustomFont方法:

func loadCustomFont(name: String, fontExtension: String) -> Bool {
    let fileManager = NSFileManager.defaultManager()
    let bundleURL = NSBundle(forClass: USDFont.self).bundleURL
    do {
        let contents = try fileManager.contentsOfDirectoryAtURL(bundleURL, includingPropertiesForKeys: [], options: .SkipsHiddenFiles)
        for url in contents {
            if url.pathExtension == fontExtension {
                let fontData = NSData(contentsOfURL: url)
                let provider = CGDataProviderCreateWithCFData(fontData)
                if let font = CGFontCreateWithDataProvider(provider) {
                    CTFontManagerRegisterGraphicsFont(font, nil)
                }
            }
        }
    } catch {
        print("error: \(error)")
    }
    return true
}
Run Code Online (Sandbox Code Playgroud)

以这种方式(而不是通常的Info.plist方式)加载字体后,便能够在XCTest期间加载字体。


Wla*_*ala 5

对于新手:我更新了Swift 4的Rommels答案,并包装到一个帮助器类中:

import UIKit

class FontLoader {

    @discardableResult
    class func loadCustomFonts(for fontExtension: String) -> Bool {
        let fileManager = FileManager.default
        let bundleURL = Bundle(for: FontLoader.self).bundleURL
        do {
            let contents = try fileManager.contentsOfDirectory(at: bundleURL, includingPropertiesForKeys: [], options: .skipsHiddenFiles)
            for url in contents {
                if url.pathExtension == fontExtension {
                    guard let fontData = NSData(contentsOf: url) else {
                        continue
                    }
                    let provider = CGDataProvider(data: fontData)
                    let font = CGFont(provider!)
                    CTFontManagerRegisterGraphicsFont(font, nil)
                }
            }
        } catch {
            print("error: \(error)")
        }
        return true
    }
}
Run Code Online (Sandbox Code Playgroud)