2012-01-24 54 views
1

我發佈了一個關於使用Python來做同樣的事情的類似問題,但我使用objective-c和Cocoa重寫了這個小程序並得到了相同的結果。下面是我的其他堆棧溢出問題:https://stackoverflow.com/questions/8980677/polling-nsfontmanager-sharedfontmanager-in-python再次提交問題的目的是與Objective-C和Cocoa專家聯繫,誰知道,可能答案是不同的。所以在這裏。在可可中激活字體時從NSFontManager獲取更新的可用字體

我試圖寫一個小小的終端程序,它將獲得OS X認爲是活動的字體列表,並報告一段時間內有多少活動的字體。例如,在程序運行時,如果我有120個字體激活,它應該報告120個激活的字體,然後如果我在程序運行時再激活10個字體,它應該報告130個激活的字體。我遇到的問題是它似乎不像sharedFontManager實例正在我的for循環中更新。這裏是我正在使用的代碼:

#import <Foundation/Foundation.h> 
#import <AppKit/AppKit.h> 

int main (int argc, const char * argv[]) 
{ 

    @autoreleasepool { 
     for(int y=0; y < 5; y++){ 

     NSArray *sysFonts; 
     NSFontManager *manager = [NSFontManager sharedFontManager]; 
     sysFonts = [manager availableFonts]; 

     NSLog(@"Number of active fonts: %lu", [sysFonts count]); 
     sleep(5); 
     sysFonts = nil; 
     } 

    } 
return 0; 
} 

所以如果你想測試這個,你需要幾百個字體來激活和停用。從停用字體開始(選擇字體,右鍵單擊,選擇「禁用字體」)。運行該程序。當看到終端彈出「活動字體數量:」彈出回字體書單時,右鍵單擊所選字體並點擊「啓用字體」(隨意將睡眠(5)改爲更長或更短的時間。以秒爲單位),它將重複循環5次(再次,您也可以更改此數字)。

結果我總是以相同數量的激活字體,但我知道這是不準確的,因爲如果您激活了大量字體(大約500字體的某處),您有足夠的時間重新運行該程序,並看到數量已經減少或增加了上次運行程序的時間,具體取決於您是否激活或停用了大量的字體。換句話說,我知道字體激活正在發生,我期望看到字體數量的變化。

任何幫助或指導將不勝感激。

+0

這是一個非常好的問題。我完全可以在這裏重現這個問題,我不知道爲什麼字體管理器不更新。我可以在調用'[manager availableFonts]'之前調用私有方法'-_reactToFontSetChange'來更新它,但這並不理想。 –

+0

感謝您花時間研究@RobKeniger!如果你碰巧找到了一種方法來做我想做的事,讓我知道。你提到你可以通過調用私有方法'_reactToFontSetChange'來更新它,並且我相信它不是理想的,但是如果它是唯一的方法,你是否介意讓我知道我將如何調用私有方法?我對編程有點新鮮,但我很快就熟悉了。 :) – Semibeard

+0

最簡單的方法是調用'[manager performSelector:@selector(_reactToFontSetChange)]'。 –

回答

3

您可以運行NSRunLoop並使用NSFontSetChangedNotification機制更新sharedFontManager實例!

/* 

Getting updated availableFonts from NSFontManager while activating fonts in Cocoa 
http://stackoverflow.com/questions/8995017/getting-updated-availablefonts-from-nsfontmanager-while-activating-fonts-in-coco 

references: 
- NSFontAttributeExplorer 
    https://developer.apple.com/library/mac/#samplecode/NSFontAttributeExplorer/Introduction/Intro.html%23//apple_ref/doc/uid/DTS10003960 
    https://developer.apple.com/library/mac/samplecode/NSFontAttributeExplorer/NSFontAttributeExplorer.zip 
- NSFontManager Class Reference 
    https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/NSFontManager_Class/Reference/Reference.html 
- http://stackoverflow.com/questions/8336693/on-nsrunloop-clarification-needed 
- /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSFont.h 


compile with: 
gcc -Wall -Wextra -x objective-c -framework AppKit -o getfonts getfonts.m 

usage: 

./getfonts 

(./getfonts > font.log) & 
pid=$! 
# kill -HUP $pid 


# play around with "Disable selected fonts" & "Enable selected fonts" button 
open -a 'Font Book' 

*/ 


#import <AppKit/AppKit.h> 


// create a counter to avoid createFontList() being called twice for a single font adding/removing event 
// Is there any alternative? 
static int counter = 0; 


@interface FontLogger : NSObject 
{ 
    NSFontManager *mysharedFontManager; 
} 
- (id)init; 
-(void)createFontList; 
@end 


@implementation FontLogger 

- (id)init 
{ 
    if ((self = [super init])) 
    { 
     mysharedFontManager = [NSFontManager sharedFontManager]; 
     [self createFontList]; 
    } 
    return self; 
} 


-(void) setNSFontSetChangedNotification 
{ 
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(fontSetChanged:) name: NSFontSetChangedNotification object: nil]; 
} 

-(void)createFontList 
{ 

    counter = counter + 1; 

    if (counter == 1) 
    { 
     NSString *name = NULL; 
     NSArray *fontarray = [mysharedFontManager availableFonts]; 
     NSEnumerator *nameEnum = [fontarray objectEnumerator]; 

     int i = 0; 
     while ((name = [nameEnum nextObject])) 
     { 
     //NSLog(@"font: %@", name); 
     printf("%s\n", [name UTF8String]); 
     i = i + 1; 
     } 
     printf("Number of available fonts: %i\n\n", i); 
     fflush(stdout); 

    }else { 
     counter = 0; 
    } 

} 

- (void)fontSetChanged:(NSNotification *)notification 
{ 

    if ([[notification name] isEqualToString:@"NSFontSetChangedNotification"]) 
    { 
     [self createFontList]; 
     //NSLog (@"Successfully received notification!"); 
    } 

} 

@end 


int main (void) 
{ 

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 

    FontLogger *getAvailableFonts = [[[FontLogger alloc] init] autorelease]; 

    [getAvailableFonts setNSFontSetChangedNotification]; 

    BOOL terminated = NO; 

    while(!terminated && [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]); 

    [pool release]; 

    return 0; 

}