2012-12-27 10 views
13

Wiele razy widziałem to pytanie i odpowiadałem, ale nie widziałem prawdziwej odpowiedzi. Typowe "rozwiązania" to:Jak dynamicznie ładować czcionkę pod iOS. (na prawdę)

  • Dodaj czcionkę do pakietu aplikacji i zarejestruj ją w pliku info.plist.
  • Użyj niestandardowej parsowania czcionek i biblioteki renderowania (np. FontLabel Zynga).
  • Nie można tego zrobić.

Więc pytanie brzmi: Jak dynamicznie załadować czcionkę pod iOS? Ładowanie czcionki "dynamicznie" oznacza ładowanie dowolnej czcionki, która nie jest znana w momencie kompilacji aplikacji.

+0

spojrzał 'CTFontManagerCreateFontDescriptorsFromURL'? – Bejmax

+0

Zobacz http://stackoverflow.com/a/12497630/724514. Właśnie wypróbowałem to i byłem w stanie załadować i użyć czcionki. W celu "wczytania dowolnej czcionki nieznanej w czasie kompilacji aplikacji" można pobrać czcionkę i zapisać ją w katalogu Dokumenty, a następnie postępować zgodnie z przykładem w kodzie. – bobnoble

Odpowiedz

22

Czcionki można łatwo ładować dynamicznie z dowolnego miejsca lub dowolnego strumienia bajtów. Zobacz artykuł tutaj: http://www.marco.org/2012/12/21/ios-dynamic-font-loading

NSData *inData = /* your font-file data */; 
CFErrorRef error; 
CGDataProviderRef provider = CGDataProviderCreateWithCFData((CFDataRef)inData); 
CGFontRef font = CGFontCreateWithDataProvider(provider); 
if (! CTFontManagerRegisterGraphicsFont(font, &error)) { 
    CFStringRef errorDescription = CFErrorCopyDescription(error) 
    NSLog(@"Failed to load font: %@", errorDescription); 
    CFRelease(errorDescription); 
} 
CFRelease(font); 
CFRelease(provider); 
  • Nie trzeba umieścić czcionki w pakiecie.
  • Nie musisz jawnie rejestrować czcionki w pliku info.plist.

Zobacz także: https://developer.apple.com/library/mac/#documentation/Carbon/Reference/CoreText_FontManager_Ref/Reference/reference.html#//apple_ref/doc/uid/TP40008278

https://developer.apple.com/library/mac/#documentation/GraphicsImaging/Reference/CGFont/Reference/reference.html#//apple_ref/c/func/CGFontCreateWithDataProvider

+0

czy można podać nazwę, aby zarejestrować czcionkę podczas ładowania? – user102008

+0

@ user102008 Nie wydaje się to możliwe. –

+0

@ user102008 * pobierz * nazwę z obiektu 'CGFontRef' zamiast -' CGFontCopyFullName'. – adib

8

Wielki czas na niedawnym poście od Marco zatytułowany Loading iOS fonts dynamically.

NSData *inData = /* your decrypted font-file data */; 
CFErrorRef error; 
CGDataProviderRef provider = CGDataProviderCreateWithCFData((CFDataRef)inData); 
CGFontRef font = CGFontCreateWithDataProvider(provider); 
if (! CTFontManagerRegisterGraphicsFont(font, &error)) { 
    CFStringRef errorDescription = CFErrorCopyDescription(error) 
    NSLog(@"Failed to load font: %@", errorDescription); 
    CFRelease(errorDescription); 
} 
CFRelease(font); 
CFRelease(provider); 
+2

To bardzo zabawna sytuacja. Odkryłem post Marco i poszedłem napisać ten sam kod jako odpowiedź na kilka pytań na SO. Ale wtedy pomyślałem, że lepiej byłoby stworzyć pytanie, które odpowie na siebie, aby odpowiedź była łatwiejsza do wykrycia. Następnie moderator usunął moją własną odpowiedź na moje własne pytanie z tym samym kodem = ( –

+0

czy można podać nazwę, aby zarejestrować czcionkę podczas ładowania? – user102008

+0

potrzebujesz '#import ' – MrTristan

2
// Note : add "CoreText.framework" into your project to support following code 

// Put loadCustomFont function inside app delegate or any shared class to access any where in code... 

    -(void)loadCustomFont:(NSMutableArray *)customFontFilePaths{ 

     for(NSString *fontFilePath in customFontFilePaths){ 

      if([[NSFileManager defaultManager] fileExistsAtPath:fontFilePath]){ 

       NSData *inData = [NSData dataWithContentsOfFile:fontFilePath]; 
       CFErrorRef error; 
       CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)inData); 
       CGFontRef font = CGFontCreateWithDataProvider(provider); 
       // NSString *fontName = (__bridge NSString *)CGFontCopyFullName(font); 
       if (!CTFontManagerRegisterGraphicsFont(font, &error)) { 
        CFStringRef errorDescription = CFErrorCopyDescription(error); 
        NSLog(@"Failed to load font: %@", errorDescription); 
        CFRelease(errorDescription); 
       } 
       CFRelease(font); 
       CFRelease(provider); 
      } 
     } 
    } 

    // Use as follow inside your view controller... 

    - (void)viewDidLoad 
    { 
     [super viewDidLoad]; 

     // pass all font files name into array which you want to load dynamically... 
     NSMutableArray *customFontsPath = [[NSMutableArray alloc] init]; 
     NSArray *fontFileNameArray = [NSArray arrayWithObjects:@"elbow_v001.ttf",@"GothamRnd-MedItal.otf", nil]; 

     for(NSString *fontFileName in fontFileNameArray){ 

      NSString *fileName = [fontFileName stringByDeletingPathExtension]; 
      NSString *fileExtension = [fontFileName pathExtension]; 
      [customFontsPath addObject:[[NSBundle mainBundle] pathForResource:fileName ofType:fileExtension]]; 
     } 


     AppDelegate *appDel = (AppDelegate *)[[UIApplication sharedApplication] delegate]; 
     // load custom font into memory... 
     [appDel loadCustomFont:customFontsPath]; 

     // Use font as below 
     [lblName setFont:[UIFont fontWithName:@"Elbow v100" size:15.0]]; 
     [lblName2 setFont:[UIFont fontWithName:@"Gotham Rounded" size:20.0]]; 
    } 
+2

jeśli chcesz to zrobić, dlaczego nie użyć 'CTFontManagerRegisterFontsForURL()'? – user102008

+0

@ user102008, ponieważ nie będziesz w stanie dowiedzieć się, jaka czcionka została zarejestrowana pod tym adresem URL. Przechodzenie przez 'CGFontRef' pozwala uzyskać nazwij i użyj normalnych metod 'UIFont' po. – adib

+0

Jeśli aplikacja się zawiesza, użyj tego: http://stackoverflow.com/questions/24900979/cgfontcreatewithdataprowidera-hangs-in-programu samolotowego – pegpeg

0

Tutaj szybka wersja:

let inData: NSData = /* your font-file data */; 
let error: UnsafeMutablePointer<Unmanaged<CFError>?> = nil 
let provider = CGDataProviderCreateWithCFData(inData) 
if let font = CGFontCreateWithDataProvider(provider) { 
    if (!CTFontManagerRegisterGraphicsFont(font, error)) { 
     if let unmanagedError = error.memory { 
      let errorDescription = CFErrorCopyDescription(unmanagedError.takeUnretainedValue()) 
      NSLog("Failed to load font: \(errorDescription)"); 
     } 
    } 
} 
1

Pobieranie pliku TTF z serwera?

Jeśli pobierasz plik TTF wtedy można zrobić następujące czynności, aby zarejestrować swoje własne czcionki z Menedżera iOS czcionki, ten kawałek kodu dba również o pliku TTF aktualizacje (aktualizacje czcionki):

+(void)registerFontsAtPath:(NSString *)ttfFilePath 
{ 
    NSFileManager * fileManager = [NSFileManager defaultManager]; 

    if ([fileManager fileExistsAtPath:ttfFilePath] == YES) 
    { 
     [UIFont familyNames];//This is here for a bug where font registration API hangs for forever. 

     //In case of TTF file update : Fonts are already registered, first de-register them from Font Manager 
     CFErrorRef cfDe_RegisterError; 
     bool fontsDeregistered = CTFontManagerUnregisterFontsForURL((__bridge CFURLRef)[NSURL fileURLWithPath:ttfFilePath], kCTFontManagerScopeNone, &cfDe_RegisterError); 


     //finally register the fonts with Font Manager, 
     CFErrorRef cfRegisterError; 
     bool fontsRegistered= CTFontManagerRegisterFontsForURL((__bridge CFURLRef)[NSURL fileURLWithPath:ttfFilePath], kCTFontManagerScopeNone, &cfRegisterError); 
} 
0

Oto uaktualniony odpowiedź @ mt81 dla Swift 3:

guard 
    let path = "Path to some font file", 
    let fontFile = NSData(contentsOfFile: path) 
else { 
    print "Font file not found?" 
} 

guard let provider = CGDataProvider(data: fontFile) 
else { 
    print "Failed to create DataProvider" 
} 

let font = CGFont(provider) 
let error: UnsafeMutablePointer<Unmanaged<CFError>?>? = nil 

guard CTFontManagerRegisterGraphicsFont(font, error) else { 
    guard 
     let unError = error?.pointee?.takeUnretainedValue(), 
     let description = CFErrorCopyDescription(unError) 
    else { 
     print "Unknown error" 
    } 
    print description 
} 
Powiązane problemy