The app I’m developing downloads custom fonts from on-demand resources and registers them with the system. These fonts appear on your device in Settings > General > Fonts. And the UIFontPickerViewController allows you to use the font in other productivity apps like Freeform.
This app worked fine until iOS 16. Starting with iOS 17, occasionally, but not always, the name of the font selected using UIFontPickerViewController will be displayed as “Helvetica”. Also, the design of the selected font is not displayed on the screen. Additionally, it has been discovered that fonts that were normally displayed are not displayed in UIFontPickerViewController.
I confirmed that the fonts were installed properly on my system. What else should I try?
Here is the code that downloads the font from an on-demand resource and registers it with the system.
<code>func installFont(_ font : Font, completion:@escaping((Bool, Error?)->())) {
self.requestFont(font:font, onSuccess: {[weak self] in
self?.registerFont(font) { (errs, success) in
let err = errs.debugDescription
completion(true, Error(code:err.code, message: err))
completion(false, Error())
}}, progress: { (fraction) in
SCLog.debug("downloading (fraction)")
case NSBundleOnDemandResourceOutOfSpaceError:
msg = "You don't have enough space available to download this resource."
case NSBundleOnDemandResourceExceededMaximumSizeError:
msg = "The bundle resource was too big."
case NSBundleOnDemandResourceInvalidTagError:
msg = "The requested tag does not exist."
completion(false, Error(code: error.code, message: msg))
func requestFont(font: Font,
onSuccess: @escaping () -> Void,
progress: @escaping (Double) -> Void,
onFailure: @escaping (NSError) -> Void) -> NSBundleResourceRequest? {
let request = NSBundleResourceRequest(tags: [tag])
request.conditionallyBeginAccessingResources { (available) in
request.beginAccessingResources { (error: Error?) in
onFailure(error as NSError)
font.isFontAvailable = true
let _ = request.progress.observe(.fractionCompleted, changeHandler: { (req, change) in
progress(request.progress.fractionCompleted)
func registerFont(_ font : Font, completion:@escaping((CFArray?, Bool)->())) {
let urls = font.fonts.map {($0.fontURL ?? URL(fileURLWithPath: ""))}
CTFontManagerRegisterFontURLs(urls as CFArray, .persistent, true) { [weak self]
(errors, success) -> Bool in
if let errs = errors as? NSArray {
completion(errors, false)
completion(errors, false)
<code>func installFont(_ font : Font, completion:@escaping((Bool, Error?)->())) {
self.requestFont(font:font, onSuccess: {[weak self] in
self?.registerFont(font) { (errs, success) in
if success {
if errs != nil {
let err = errs.debugDescription
completion(true, Error(code:err.code, message: err))
}
else
{
completion(true, nil)
}
} else {
completion(false, Error())
}
}}, progress: { (fraction) in
SCLog.debug("downloading (fraction)")
}) { (error) in
var msg = ""
switch error.code {
case NSBundleOnDemandResourceOutOfSpaceError:
msg = "You don't have enough space available to download this resource."
case NSBundleOnDemandResourceExceededMaximumSizeError:
msg = "The bundle resource was too big."
case NSBundleOnDemandResourceInvalidTagError:
msg = "The requested tag does not exist."
default:
msg = "download failed"
}
completion(false, Error(code: error.code, message: msg))
}
}
func requestFont(font: Font,
onSuccess: @escaping () -> Void,
progress: @escaping (Double) -> Void,
onFailure: @escaping (NSError) -> Void) -> NSBundleResourceRequest? {
let tag = font.tag
let request = NSBundleResourceRequest(tags: [tag])
request.conditionallyBeginAccessingResources { (available) in
if available {
onSuccess()
} else {
request.beginAccessingResources { (error: Error?) in
if let error = error {
onFailure(error as NSError)
return
}
font.isFontAvailable = true
onSuccess()
}
let _ = request.progress.observe(.fractionCompleted, changeHandler: { (req, change) in
progress(request.progress.fractionCompleted)
})
}
}
return request
}
func registerFont(_ font : Font, completion:@escaping((CFArray?, Bool)->())) {
let urls = font.fonts.map {($0.fontURL ?? URL(fileURLWithPath: ""))}
CTFontManagerRegisterFontURLs(urls as CFArray, .persistent, true) { [weak self]
(errors, success) -> Bool in
if success {
if let errs = errors as? NSArray {
completion(errors, false)
return false
}
else
{
completion(nil, true)
}
return true
}
else
{
completion(errors, false)
return false
}
}
}
</code>
func installFont(_ font : Font, completion:@escaping((Bool, Error?)->())) {
self.requestFont(font:font, onSuccess: {[weak self] in
self?.registerFont(font) { (errs, success) in
if success {
if errs != nil {
let err = errs.debugDescription
completion(true, Error(code:err.code, message: err))
}
else
{
completion(true, nil)
}
} else {
completion(false, Error())
}
}}, progress: { (fraction) in
SCLog.debug("downloading (fraction)")
}) { (error) in
var msg = ""
switch error.code {
case NSBundleOnDemandResourceOutOfSpaceError:
msg = "You don't have enough space available to download this resource."
case NSBundleOnDemandResourceExceededMaximumSizeError:
msg = "The bundle resource was too big."
case NSBundleOnDemandResourceInvalidTagError:
msg = "The requested tag does not exist."
default:
msg = "download failed"
}
completion(false, Error(code: error.code, message: msg))
}
}
func requestFont(font: Font,
onSuccess: @escaping () -> Void,
progress: @escaping (Double) -> Void,
onFailure: @escaping (NSError) -> Void) -> NSBundleResourceRequest? {
let tag = font.tag
let request = NSBundleResourceRequest(tags: [tag])
request.conditionallyBeginAccessingResources { (available) in
if available {
onSuccess()
} else {
request.beginAccessingResources { (error: Error?) in
if let error = error {
onFailure(error as NSError)
return
}
font.isFontAvailable = true
onSuccess()
}
let _ = request.progress.observe(.fractionCompleted, changeHandler: { (req, change) in
progress(request.progress.fractionCompleted)
})
}
}
return request
}
func registerFont(_ font : Font, completion:@escaping((CFArray?, Bool)->())) {
let urls = font.fonts.map {($0.fontURL ?? URL(fileURLWithPath: ""))}
CTFontManagerRegisterFontURLs(urls as CFArray, .persistent, true) { [weak self]
(errors, success) -> Bool in
if success {
if let errs = errors as? NSArray {
completion(errors, false)
return false
}
else
{
completion(nil, true)
}
return true
}
else
{
completion(errors, false)
return false
}
}
}