Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
500 views
in Technique[技术] by (71.8m points)

xamarin - iOS UIFont.ByName Exception (Value cannot be null. Parameter name: value)

In a custom Xamarin Forms iOS renderer I am loading fonts from files and when I get to UIFont.FromName it thorws the exception shown below. The font var is a valid CGFont instance and fontsize is a valid nfloat. Any ideas?

var font = CGFont.CreateFromProvider(fontDataProvider);
Control.Font = UIFont.FromName(font.FullName, (nfloat)e.NewElement.FontSize);

stacktrace:

System.ArgumentNullException: Value cannot be null.
Parameter name: value
  at UIKit.UILabel.set_Font (UIKit.UIFont value) [0x00011] in /Users/builder/data/lanes/1381/3afb4af5/source/maccore/src/build/ios/native/UIKit/UILabel.g.cs:337 
  at DecryptRenderFont.iOS.DecryptRenderControlRenderer.OnElementChanged (Xamarin.Forms.Platform.iOS.ElementChangedEventArgs`1[TElement] e) [0x00215] 
  at Xamarin.Forms.Platform.iOS.VisualElementRenderer`1[TElement].SetElement (TElement element) [0x00118] in <filename unknown>:0 
  at Xamarin.Forms.Platform.iOS.VisualElementRenderer`1[TElement].Xamarin.Forms.Platform.iOS.IVisualElementRenderer.SetElement (Xamarin.Forms.VisualElement element) [0x00000] in <filename unknown>:0 
  at Xamarin.Forms.Platform.iOS.Platform.CreateRenderer (Xamarin.Forms.VisualElement element) [0x0001b] in <filename unknown>:0 
  at Xamarin.Forms.Platform.iOS.VisualElementPackager.OnChildAdded (Xamarin.Forms.VisualElement view) [0x00000] in <filename unknown>:0 
  at Xamarin.Forms.Platform.iOS.VisualElementPackager.Load () [0x00023] in <filename unknown>:0 
  at Xamarin.Forms.Platform.iOS.VisualElementRenderer`1[TElement].SetElement (TElement element) [0x000cc] in <filename unknown>:0 
  at Xamarin.Forms.Platform.iOS.VisualElementRenderer`1[TElement].Xamarin.Forms.Platform.iOS.IVisualElementRenderer.SetElement (Xamarin.Forms.VisualElement element) [0x00000] in <filename unknown>:0 
  at Xamarin.Forms.Platform.iOS.Platform.CreateRenderer (Xamarin.Forms.VisualElement element) [0x0001b] in <filename unknown>:0 
  at Xamarin.Forms.Platform.iOS.VisualElementPackager.OnChildAdded (Xamarin.Forms.VisualElement view) [0x00000] in <filename unknown>:0 
  at Xamarin.Forms.Platform.iOS.VisualElementPackager.Load () [0x00023] in <filename unknown>:0 
  at Xamarin.Forms.Platform.iOS.PageRenderer.ViewDidLoad () [0x0007d] in <filename unknown>:0 
  at (wrapper managed-to-native) ObjCRuntime.Messaging:IntPtr_objc_msgSendSuper (intptr,intptr)
  at UIKit.UIViewController.get_View () [0x00030] in /Users/builder/data/lanes/1381/3afb4af5/source/maccore/src/build/ios/native/UIKit/UIViewController.g.cs:2667 
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

1 ) I am going to assume the exception stack you are seeing is not showing the actual underlaying error as it is coming from the Xamarin.iOS generated UILabel.g.cs file (that is a auto-generated wrapper within https://github.com/xamarin/xamarin-macios) and I personally have had a few issues tracing certain low-level OS exceptions/throws and thus the shown exception is a little (a lot?) misleading.

2) Again I am going to assume since you said you are "loading fonts from files" that these fonts are not registered. Assuming you are loading these fonts via a CGFont.CreateFromProvider from files in your app bundle (or dynimically downloaded) and since they do not exist in the info.plist under the UIAppFonts key, they are not auto-registered to iOS. You need to do that step yourself:

NSError error;
if (!CTFontManager.RegisterGraphicsFont(customFont, out error))
{
   // error occurred, checkout the contents of the NSError var
}

After registering the CGFont with the iOS font manager (CTFontManager) you can actually use them within UIKit, otherwise internally there is an exception within iOS code... Would need to write some ObjC/Swift to check it out in Xcode to see what the actual error being thrown is...

Are your fonts registered or not:

Somewhere before the exception but after your CreateFromProvider, you can do the following:

foreach (var familyNames in UIFont.FamilyNames.OrderBy(c => c).ToList())
{
    D.WriteLine(" * " + familyNames);
    foreach (var familyName in UIFont.FontNamesForFamilyName(familyNames).OrderBy(c => c).ToList())
    {
        D.WriteLine(" *-- " + familyName);
    }
}

Note: D is just using D = System.Diagnostics.Debug;

I would bet that your font is not in the list, but after a call to CTFontManager.RegisterGraphicsFont it will be in that list and valid to be consumed by UIKit.

Update:

Interesting note in that using a Swift-based app and not registering the font does not cause a app crash. The font is not shown of course, but referencing it via UIFont(name: "XXXXX", size: 35) is just a silent failure.

So I'd just recommend some defensive try{} catch{} around any use of your custom font to be safe.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...