2017-06-18 7 views
3

経由で登録したフォントのリストを取得する:iOSのCoreTextは、私は、次の経由で動的にフォントを登録していますCTFontManagerRegisterGraphicsFont

- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation{ 

    if ([url isFileURL]) 
    { 
     // Handle file being passed in 
     NSLog(@"handleOpenURL: %@",url.absoluteString); 


     NSData *inData = [NSData dataWithContentsOfURL:url]; 
     CFErrorRef error; 
     CGDataProviderRef provider = CGDataProviderCreateWithCFData((CFDataRef)inData); 
     CGFontRef fontRef = CGFontCreateWithDataProvider(provider); 

     UIFont *font; 
     if (!CTFontManagerRegisterGraphicsFont(fontRef, &error)) { 
      CFStringRef errorDescription = CFErrorCopyDescription(error); 
      NSLog(@"Failed to load font: %@", error); 
      CFRelease(errorDescription); 
     } else { 
      CFStringRef fontNameRef = CGFontCopyPostScriptName(fontRef); 
      NSLog(@"fontNameRef: %@",fontNameRef); 
      font = [UIFont fontWithName:(__bridge NSString *)fontNameRef size:80]; 
      [self.arrayOfFonts addObject:(__bridge NSString *)fontNameRef]; 
      [[NSNotificationCenter defaultCenter] postNotificationName:@"refreshFont" object:nil]; 
      CFRelease(fontNameRef); 
     } 
     CFRelease(fontRef); 
     CFRelease(provider); 
     return YES; 
    } 
    else 
    { 
     return NO; 
    } 
} 

それは細かい初めての作品。アプリを閉じてもう一度同じフォントを登録しようとすると、(予想される)エラーが表示されるようです。"Failed to load font: Error Domain=com.apple.CoreText.CTFontManagerErrorDomain Code=105 "Could not register the CGFont '<CGFont (0x1c00f5980): NeuropolXRg-Regular>'" UserInfo={NSDescription=Could not register the CGFont '<CGFont (0x1c00f5980): NeuropolXRg-Regular>', CTFailedCGFont=<CGFont (0x1c00f5980): NeuropolXRg-Regular>}"

これはフォントが既に登録されているためです。 CTFontManagerRegisterGraphicsFontのドキュメントには、

"フォントマネージャーで登録されたフォントが登録されています。登録されているフォントは、フォント記述子の照合によって検出可能です。すでに登録されているフォントは失敗します。

「フォント記述子のマッチング」を正確に行う方法

CTFontManagerRegisterGraphicsFontメソッドで登録されたすべてのフォントのリストを取得するには、どうすれば登録前に登録を解除できますか?

EDIT:

私はCTFontManagerCopyAvailablePostScriptNamesCTFontManagerCopyAvailableFontFamilyNamesメソッドを使用してみましたが、両方の唯一のiOSですでに利用可能なフォントの名前をプリントアウトしてきました。私はCTFontManagerRegisterGraphicsFont

NOTE経由で登録されたものではない:は、私は[UIFont familyNames]を反復処理によって記載されていることができるのiOSで利用できる、すでにフォントについて尋ねていません。

- (void)getInstalledFonts { 
    NSDictionary *descriptorOptions = @{(id)kCTFontDownloadableAttribute : @YES}; 
    CTFontDescriptorRef descriptor = CTFontDescriptorCreateWithAttributes((CFDictionaryRef)descriptorOptions); 
    CFArrayRef fontDescriptors = CTFontDescriptorCreateMatchingFontDescriptors(descriptor, NULL); 
    [self showExistingFonts:(NSArray *)CFBridgingRelease(fontDescriptors)]; 
    CFRelease(descriptor); 
} 

- (void)showExistingFonts:(NSArray *)fontList { 
    NSMutableDictionary *fontFamilies = [NSMutableDictionary new]; 
    for(UIFontDescriptor *descriptor in fontList) { 
     NSString *fontFamilyName = [descriptor objectForKey:UIFontDescriptorFamilyAttribute]; 
     NSMutableArray *fontDescriptors = [fontFamilies objectForKey:fontFamilyName]; 
     if(!fontDescriptors) { 
      fontDescriptors = [NSMutableArray new]; 
      [fontFamilies setObject:fontDescriptors forKey:fontFamilyName]; 
     } 

     [fontDescriptors addObject:descriptor]; 
    } 

} 

から撮影:あなたが使用する必要がありますどのような

+0

誰かが私を助けてくれますか? –

+0

「アプリを閉じる」とまったく同じ意味ですか? –

+0

また、['CTFontManagerCopyAvailablePostScriptNames'](https://developer.apple.com/documentation/coretext/1499516-ctfontmanagercopyavailablepostsc)を試しましたか? –

答えて

3
私はアップルDTS(開発者向け技術サポート)でチケットをログに記録

と彼らは言った:

"CTFontManagerRegisterGraphicsFontから返されたエラーコードkCTFontManagerErrorAlreadyRegisteredは、あなたが登録したフォントを自分自身で追跡する必要があります。既にフォントを登録している場合。あなたのフォントがインストールされているかどうかを発見するためにフォント記述子マッチングを使用することは、おそらく、システムが欠落しているフォントのフォント置換を実行することを選ぶかもしれないので、良い方法ではありません。 CTFontManagerRegisterGraphicsFontを使用してフォントをインストールするだけで、アプリを使用できるようになります。インストールされたフォントを検出するためのクエリサービスではありません。それがあなたの好みに十分でない場合は、受け取る機能を求める機能要求を提出することを検討することをお勧めします。」

したがって、基本的には、我々は自分自身を登録フォント私が使用して終了回避策

ソリューション/:。。

は現在、私のアプリは、これと同じユーザーがフォントファイルのボタンをAction Sheet's「MYAPPにコピー」を使用してフォントを追加することができますソリューションは、自分のサーバーからダウンロードしたフォントファイルに対しても機能します。これは私のアプリはで表示することができます

<key>CFBundleDocumentTypes</key> 
    <array> 
     <dict> 
      <key>CFBundleTypeIconFiles</key> 
      <array/> 
      <key>CFBundleTypeName</key> 
      <string>Font</string> 
      <key>LSItemContentTypes</key> 
      <array> 
       <string>public.opentype-font</string> 
       <string>public.truetype-ttf-font</string> 
      </array> 
     </dict> 
    </array> 

:私のアプリは、私のアプリのInfo.plistに、.ttf.otfファイルに対してアクションシートに記載されていることにするためには

は、私は新しいドキュメントタイプを追加しました任意のフォントファイルのaction sheetそのため、ユーザーは、ドロップボックス、Googleドライブ、または他のファイル共有アプリにフォントファイルを置くことができます。その後、そこから私のアプリにフォントをインポートすることができます。インポート後、一時ファイルtmpinboxからフォントファイルをDocumentsfontsディレクトリに移動する必要があります。 fontsディレクトリには、すべてのカスタムフォントが保持されます。その後、このカスタムフォントを登録し、self.arrayOfFonts配列に名前を追加します。これはすべての私のフォントのリストを含む配列です。

また、CTFontManagerRegisterGraphicsFontはセッションのみに表示されます。したがって、アプリケーションがApp Switcherから閉じられて再起動されると、そのフォントは登録されなくなります。だから起動するたびに、私は自分のdocuments/fontsフォルダを通り、すべてのフォントを再登録し、その名前をself.arrayOfFontsアレイに追加します。

- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation{ 

    if ([url isFileURL]) 
    { 
     // Handle file being passed in 
     NSLog(@"handleOpenURL: %@, extension: %@",url.absoluteString,url.pathExtension); 
     [self moveFontFrom:url]; 
     return YES; 
    } 
    else 
    { 
     return NO; 
    } 
} 

-(void)moveFontFrom:(NSURL*)fromurl{ 
    NSString *stringPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)objectAtIndex:0] stringByAppendingPathComponent:@"fonts"]; 
    // New Folder is your folder name 
    NSError *error1 = nil; 
    if (![[NSFileManager defaultManager] fileExistsAtPath:stringPath]){ 
     [[NSFileManager defaultManager] createDirectoryAtPath:stringPath withIntermediateDirectories:NO attributes:nil error:&error1]; 
    } 
    NSLog(@"error1: %@", error1.debugDescription); 
    NSURL *tourl = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/%@",stringPath,[[fromurl absoluteString] lastPathComponent]] isDirectory:NO]; 

    NSLog(@"Trying to move from:\n\n%@\n\nto:\n\n%@\n\n", fromurl.absoluteString,tourl.absoluteString); 

    NSError* error2; 
    if ([[NSFileManager defaultManager] fileExistsAtPath:tourl.path]){ 
     [[NSFileManager defaultManager] removeItemAtPath:tourl.path error:&error2]; 
     NSLog(@"Deleting old existing file at %@ error2: %@", tourl.path,error2.debugDescription); 
    } 


    NSError* error3; 
    [[NSFileManager defaultManager] moveItemAtURL:fromurl toURL:tourl error:&error3]; 
    NSLog(@"error3: %@", error3.debugDescription); 

    if (!error3) { 
     NSString *fontName = [self registerFont:tourl checkIfNotify:YES]; 
     if (fontName) { 
      if (![self.arrayOfFonts containsObject:fontName]) { 
       [self.arrayOfFonts addObject:fontName]; 
       [self.arrayOfFonts sortUsingSelector:@selector(localizedCaseInsensitiveCompare:)]; 
       [[NSNotificationCenter defaultCenter] postNotificationName:@"refreshFont" object:nil userInfo:@{@"font":fontName}]; 
      } 
     } 
    } 
} 

-(void)startupLoadFontsInDocuments{ 

    self.arrayOfFonts = [NSMutableArray new]; 
    NSString *location = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)objectAtIndex:0] stringByAppendingPathComponent:@"fonts"]; 
    NSArray *directoryContent = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:location error:NULL]; 
    for (NSInteger count = 0; count < [directoryContent count]; count++) 
    { 
     NSLog(@"File %ld: %@/%@", (count + 1), location,[directoryContent objectAtIndex:count]); 
     NSString *fontName = [self registerFont:[NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/%@",location,[directoryContent objectAtIndex:count]] isDirectory:NO] checkIfNotify:NO]; 
     if (fontName) { 
      if (![self.arrayOfFonts containsObject:fontName]) { 
       [self.arrayOfFonts addObject:fontName]; 
      } 
     } 
    } 
    [self.arrayOfFonts sortUsingSelector:@selector(localizedCaseInsensitiveCompare:)]; 
} 

-(NSString*)registerFont:(NSURL *)url checkIfNotify:(BOOL)checkIfNotify{ 
    NSData *inData = [NSData dataWithContentsOfURL:url]; 
    CFErrorRef registererror; 
    CGDataProviderRef provider = CGDataProviderCreateWithCFData((CFDataRef)inData); 
    CGFontRef fontRef = CGFontCreateWithDataProvider(provider); 
    NSString *fontName = (__bridge NSString *)CGFontCopyPostScriptName(fontRef); 
    BOOL registerFontStatus = CTFontManagerRegisterGraphicsFont(fontRef, &registererror); 
    if (!registerFontStatus) { 
     CFStringRef errorDescription = CFErrorCopyDescription(registererror); 
     NSError *registererr = (__bridge NSError*)registererror; 
     if ([registererr code]==kCTFontManagerErrorAlreadyRegistered) { 
      NSLog(@"Font is already registered!"); 
     } 
     NSLog(@"Failed to load font: %@", registererror); 
     CFRelease(errorDescription); 

     /*CFErrorRef unregistererror; 
    BOOL unregisterFont = CTFontManagerUnregisterGraphicsFont(fontRef, &unregistererror); 
    NSLog(@"Font unregister status: %d",unregisterFont); 
    CFStringRef unregistererrorDescription = CFErrorCopyDescription(unregistererror); 
    NSError *unregistererr = (__bridge NSError*)unregistererror; 
    NSInteger code = [unregistererr code]; 

    NSLog(@"Failed to unregister font: %@", unregistererr); 
    CFRelease(unregistererrorDescription);*/ 

     if (checkIfNotify) { 
      UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Already added" message:@"That font is already added to the app. Please select it from the fonts list." preferredStyle:UIAlertControllerStyleAlert]; 
      [alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { 

      }]]; 
      [[self.window rootViewController] presentViewController:alert animated:YES completion:nil]; 
     } 
    } else { 
     CFStringRef fontNameRef = CGFontCopyPostScriptName(fontRef); 
     fontName = (__bridge NSString*)fontNameRef; 
     CFRelease(fontNameRef); 

     NSLog(@"fontName: %@",fontName); 
    } 
    CFRelease(fontRef); 
    CFRelease(provider); 
    return fontName; 
} 

注:あなたが気づいれるように、私はCTFontManagerUnregisterGraphicsFontをコメントアウトしている私のアプリのコードの

残りはこの作業を取得します。 CTFontManagerUnregisterGraphicsFontフォントの登録解除に使用されていると、フォントが使用中であることを示すエラーが表示され、登録を解除できないため、私にとってはうまくいかないようです。だからフォントを削除する必要があるときは、単にself.arrayOfFonts配列と私のdocuments/fontsフォルダから削除するだけです。

1
+0

私はこれを試して、 'fontFamilyName'の' NSLog'を行いました。私は3つのカスタムフォントでテストしましたが、どれもリストされていませんでした。私は '[UIFont familyNames] 'を介して得ることができるすべての名前を印刷しましたが、' CTFontManagerRegisterGraphicsFont'で登録した私のカスタムフォントを印刷しませんでした。 –

+0

他のdescriptorオプションを使用してみてください。 https://developer.apple.com/documentation/coretext/core_text_constants – Lefteris

+0

私は 'kCTFontDownloadedAttribute'、' kCTFontDownloadableAttribute'を試しました。私はApple DTSに連絡して、彼らは自分自身のフォントを自分で追跡する必要があると言いました。「フォントがインストールされているかどうかを知るためにフォント記述子のマッチングを使用するのは、おそらくシステムが行方不明のフォント置換フォント。 " 私がここで共有した回避策を使用して終了しました。 https://stackoverflow.com/a/45284412/1634905 –

関連する問題