swift iOS 13自定义字体下载和安装

mfuanj7w  于 9个月前  发布在  Swift
关注(0)|答案(2)|浏览(151)

我想使用CoreText API下载字体,但它在iOS 12中工作,在iOS 13上不可用。
2013年苹果推出了demo project。但它使用的API似乎从iOS 13开始就是私有的。

/*     
    @param      progressBlock
Callback block to indicate the progress.
Return true to continue, and return false to cancel the process.
This block is called on a private serial queue on OS X 10.15, iOS 13, and later.
     
*/

@available(iOS 6.0, *)
public func CTFontDescriptorMatchFontDescriptorsWithProgressHandler(_ descriptors: CFArray, _ mandatoryAttributes: CFSet?, _ progressBlock: @escaping CTFontDescriptorProgressHandler) -> Bool

正如文件所声明的:
在OS X 10.15、iOS 13和更高版本上,此块在私有串行队列上调用。
下面是我的字体下载代码:

let fontName = "STXingkai-SC-Light"
let attributes = [kCTFontNameAttribute : fontName] as CFDictionary
let fontDescription = CTFontDescriptorCreateWithAttributes(attributes)
// create font font descriptor and add it in an array
let descs = [fontDescription] as CFArray
CTFontDescriptorMatchFontDescriptorsWithProgressHandler(descs, nil) { (state, progressParamater) -> Bool in
    let progressValue = (progressParamater as Dictionary)[kCTFontDescriptorMatchingPercentage]?.doubleValue
    
    switch state {
    case .didBegin: print("didBegin")
    case .didFinish: print("didFinish")
    case .willBeginDownloading: print("willBeginDownloading")
    case .didFinishDownloading:
        print("--> download finish")
        DispatchQueue.main.async {
            self.fontLabel.font = UIFont(name: self.fontName, size: 20)
        }
    case .downloading:
        print("downloading#####\(progressValue ?? 0.0)")
        DispatchQueue.main.async {
            self.progressView.progress = Float(progressValue ?? 0.0)
        }
    case .didFailWithError:
        if let error = (progressParamater as Dictionary)[kCTFontDescriptorMatchingError] as? NSError {
            print(error.description)
        } else {
            print("ERROR MESSAGE IS NOT AVAILABLE")
        }
        
    default: print(String(reflecting: state))
    }
    
    return true
    
}

我在iOS 12和Xcode 10上尝试了这个API,一切正常,我可以下载一个字体,提供fontName

但是,当我在Xcode 11 Version 11.0 beta 6 (11M392q)macOS Catalina 10.15 Beta (19A526h)上使用这个方法时,出现了问题,该方法不再有效。我得到了一些输出:

didBegin
__C.CTFontDescriptorMatchingState
didFinish
done
"Error Domain=com.apple.CoreText.CTFontManagerErrorDomain Code=303 \"0 
font descriptors do not have information to specify a font file.\"
UserInfo={NSLocalizedDescription=0 
font descriptors do not have information to specify a font file.

0字体描述符没有指定字体文件的信息
状态将只有didBegin和didFinish,而不调用downloading。
WWDC19 seeesion 227已经宣布CTFontManagerRegisterFontDescriptors(fontDescriptors:scope:enabled:registrationHandler:)可用,并提供有关字体管理的信息。但从会话PDF的源代码是不清楚,我已经尝试过,得到了其他错误:

done
[Error Domain=com.apple.CoreText.CTFontManagerErrorDomain Code=306 "The file is not in an allowed location. It must be either in the application’s bundle or an on-demand resource." UserInfo={NSLocalizedDescription=The file is not in an allowed location. It must be either in the application’s bundle or an on-demand resource., CTFontManagerErrorFontURLs=(
    "http://iweslie.com/fonts/HanziPenSC-W3.ttf"
), NSLocalizedFailureReason=Font registration was unsuccessful.}]
done

以下是我的代码引用自WWDC19会话227:

let urlString = "http://iweslie.com/fonts/HanziPenSC-W3.ttf"
let url = URL(string: urlString)! as CFURL
let fontURLArray = [url] as CFArray
CTFontManagerRegisterFontURLs(fontURLArray, .persistent, true) { (errors, done) -> Bool in
    if done {
        print("done")
    }
    print(errors as Array)
    return true
}

并得到错误:
错误域=com.apple.CoreText.CTFontManagerErrorDomain Code=306
“文件不在允许的位置。它必须在应用程序的捆绑包中或在按需资源中。”

wpcxdonn

wpcxdonn1#

对于其他寻找iOS 13解决方案的人最简单的方法可能是使用Apple Bundle和“新”CTFontManagerRegisterFontURLs API。只需使用Bundle.main.url将所有URL收集在列表中:

let fontUrl = Bundle.main.url(forResource: fileName, withExtension: "ttf")

然后注册你的字体:

CTFontManagerRegisterFontURLs([fontUrl] as CFArray, .persistent, true) { (errors, done) -> Bool in
        if(done) {
            print("Done")
        }
        print(errors as Array)
        return true
    }

如果你使用的是其他的解决方案,并且字体名称有问题,那可能是xcode的问题。我在另一个线程中看到的一个提示,用于弄清楚xcode命名你的字体是什么:

for family in UIFont.familyNames.sorted() {
        let names = UIFont.fontNames(forFamilyName: family)
        print("Family: \(family) Font names: \(names)")
    }

另外,请记住在项目设置中的“签名和功能”下启用“安装字体”功能。

1rhkuytd

1rhkuytd2#

我也面临着同样的问题。我终于找到了这个
https://juejin.im/post/5aebd428f265da0ba266d897
问题是你使用了错误的postscriptname字体。正确的字体名称是“STXingkaiSC-Light”。
我已经在xcode 12,iOS 13模拟器上测试过了。
您可以使用“Font BooK.app”找到正确的字体后记名称。

相关问题