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

mfuanj7w  于 2023-09-30  发布在  Swift
关注(0)|答案(2)|浏览(257)

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

  1. /*
  2. @param progressBlock
  3. Callback block to indicate the progress.
  4. Return true to continue, and return false to cancel the process.
  5. This block is called on a private serial queue on OS X 10.15, iOS 13, and later.
  6. */
  7. @available(iOS 6.0, *)
  8. public func CTFontDescriptorMatchFontDescriptorsWithProgressHandler(_ descriptors: CFArray, _ mandatoryAttributes: CFSet?, _ progressBlock: @escaping CTFontDescriptorProgressHandler) -> Bool

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

  1. let fontName = "STXingkai-SC-Light"
  2. let attributes = [kCTFontNameAttribute : fontName] as CFDictionary
  3. let fontDescription = CTFontDescriptorCreateWithAttributes(attributes)
  4. // create font font descriptor and add it in an array
  5. let descs = [fontDescription] as CFArray
  6. CTFontDescriptorMatchFontDescriptorsWithProgressHandler(descs, nil) { (state, progressParamater) -> Bool in
  7. let progressValue = (progressParamater as Dictionary)[kCTFontDescriptorMatchingPercentage]?.doubleValue
  8. switch state {
  9. case .didBegin: print("didBegin")
  10. case .didFinish: print("didFinish")
  11. case .willBeginDownloading: print("willBeginDownloading")
  12. case .didFinishDownloading:
  13. print("--> download finish")
  14. DispatchQueue.main.async {
  15. self.fontLabel.font = UIFont(name: self.fontName, size: 20)
  16. }
  17. case .downloading:
  18. print("downloading#####\(progressValue ?? 0.0)")
  19. DispatchQueue.main.async {
  20. self.progressView.progress = Float(progressValue ?? 0.0)
  21. }
  22. case .didFailWithError:
  23. if let error = (progressParamater as Dictionary)[kCTFontDescriptorMatchingError] as? NSError {
  24. print(error.description)
  25. } else {
  26. print("ERROR MESSAGE IS NOT AVAILABLE")
  27. }
  28. default: print(String(reflecting: state))
  29. }
  30. return true
  31. }

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

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

  1. didBegin
  2. __C.CTFontDescriptorMatchingState
  3. didFinish
  4. done
  5. "Error Domain=com.apple.CoreText.CTFontManagerErrorDomain Code=303 \"0
  6. font descriptors do not have information to specify a font file.\"
  7. UserInfo={NSLocalizedDescription=0
  8. font descriptors do not have information to specify a font file.

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

  1. done
  2. [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 applications bundle or an on-demand resource., CTFontManagerErrorFontURLs=(
  3. "http://iweslie.com/fonts/HanziPenSC-W3.ttf"
  4. ), NSLocalizedFailureReason=Font registration was unsuccessful.}]
  5. done

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

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

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

wpcxdonn

wpcxdonn1#

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

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

然后注册你的字体:

  1. CTFontManagerRegisterFontURLs([fontUrl] as CFArray, .persistent, true) { (errors, done) -> Bool in
  2. if(done) {
  3. print("Done")
  4. }
  5. print(errors as Array)
  6. return true
  7. }

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

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

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

展开查看全部
1rhkuytd

1rhkuytd2#

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

相关问题