TextKit學習(一)可以調整字體大小的FontResizeDemo

昨天看完了蘋果官方的IntroduceToTextKit這個Demo,瞭解了有關TextKit的一些新特性,TextKit的出現的確使得文字的處理變得更加便利和多功能化。個人覺得最有趣的是ExclusionPath這個部分。


之後參照這個Demo我寫了FontResizeDemo,顧名思義就是當用戶在Settings的Text Size中調整字體大小時,本程序的字體相應地做出調整。

先說說Xcode 5-DP2的一些使用感想:

1.操作便利性沒有改進:

在iOS7之前,如果在程序中導入新的框架,必須在Building Phases中的Link Binary with Libraries選項中手動添加對應的框架文件,這種方式的確非常麻煩。Xcode 5則解決了手動添加的麻煩,只需要在代碼中添加就可以直接使用。所以在WWDC2013中的關於Obj-C新特性的視頻中,說完這一特性以後可以清楚聽到下面的鼓掌歡呼聲。

但是,昨天使用Xcode 5才發現,爲了在自己新建的類中使用框架等文件時,必須要在Building Phases中的Compile Sources中手動添加類文件,如果不這麼做(即使在類文件中導入了<UIKit/UIKit.h>),最明顯的結果就是在寫代碼時如UIView這樣的名詞都不會顯示代碼高亮狀態。同樣地,如果要使用外部資源中的內容(如book.txt電子書中的內容),也必須手動在Copy Bundle Resources中添加這些資源文件。如果不這樣做,那麼在程序運行時如果使用了資源中的內容(如在控制檯輸出電子書中的內容),內容將返回結果null。添加文件後入下圖所示:


這樣比較下來,必須手動在編譯源(Compile Sources)和資源(Bundle Resources)中添加文件,整個開發過程將變得更加麻煩。

2.iOS7 Simulator存在問題

如果使用iOS7模擬器反覆調試或退出模擬器重新run一遍,將發現程序在運行開始時卡住,即使在Debug area中點擊continue也沒有作用。必須關閉程序重新打開工程文件才能在模擬器中正常運行程序。不知道是模擬器存在bug還是我沒找對調試的方法。

另外i7模擬器的外觀也放棄了i6模擬器的iPhone外觀,在明顯的就是Home鍵沒有了,要按Home鍵只能按Command+Shift+H快捷鍵或者在模擬器的硬件菜單中選擇。如果要打開後臺,必須連續按兩次Command+Shift+H快捷鍵。在模擬器的使用上,個人覺得還是iOS6的使用更爲便利。


回到Demo中來。這個Demo我只寫了一個FontResizeViewController類,下面來看看該類的實現文件:

  1. #import "FontResizeViewController.h"  
  2. #import "UITextView+TextKitDemo.h"  
  3. #import "UIFont+TextKitDemo.h"  
  4. #import "UIFontDescriptor+TextKitDemo.h"  
  5.   
  6. @interface FontResizeViewController ()  
  7. @property (nonatomic, strong) NSMutableAttributedString *content; // 文本內容  
  8. @end  
  9.   
  10. @implementation FontResizeViewController  
  11.   
  12. - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil  
  13. {  
  14.     self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];  
  15.     if (self) {  
  16.         // Custom initialization  
  17.     }  
  18.     return self;  
  19. }  
  20.   
  21. - (void)viewDidLoad  
  22. {  
  23.     [super viewDidLoad];  
  24.       
  25.     self.textView = [[UITextView alloc] initWithFrame:CGRectMake(0.0, 30.0, 320.0, 520.0)];  
  26.     [self.view addSubview:self.textView];  
  27.       
  28.     NSURL *url = nil;  
  29.     // url = [[NSBundle mainBundle] URLForResource:@"Basic Interaction.rtf" withExtension:nil];  
  30.     url = [[NSBundle mainBundle] URLForResource:@"book.txt" withExtension:nil];  
  31.     NSMutableAttributedString *attributedTextHolder = [[NSMutableAttributedString alloc] initWithFileURL:url options:@{} documentAttributes:nil error:nil];  
  32.     [attributedTextHolder addAttribute:NSFontAttributeName value:[UIFont preferredFontForTextStyle:UIFontTextStyleBody] range:NSMakeRange(0, attributedTextHolder.length)];  
  33.     // NSLog(@"%@", attributedTextHolder);  
  34.     self.content = [attributedTextHolder copy];  
  35.      
  36.     self.textView.attributedText = self.content;  
  37.     self.textView.editable = NO;  
  38.       
  39.     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(preferredContentSizeChanged:) name:UIContentSizeCategoryDidChangeNotification object:nil]; // 當不同類別的字體大小發生變化時發送消息給self  
  40. }  
  41.   
  42. -(void)preferredContentSizeChanged:(NSNotification *)noti  
  43. {  
  44.     static const CGFloat textScaleFactor = .8;  
  45.     NSString *textStyle = [self.textView tkd_textStyle]; // 先設置樣式  
  46.     UIFont *font = [UIFont tkd_preferredFontWithTextStyle:textStyle scale:textScaleFactor]; //後設置字體(包括樣式和大小)  
  47.       
  48.     self.textView.font = font;  
  49. }  
  50.   
  51. - (void)viewDidUnload  
  52. {  
  53.     [[NSNotificationCenter defaultCenter] removeObserver:self];  
  54.       
  55.     [super viewDidUnload];  
  56. }  
  57.   
  58. - (void)dealloc  
  59. {  
  60.     [[NSNotificationCenter defaultCenter] removeObserver:self];  
  61. }  
  62.   
  63. - (void)didReceiveMemoryWarning  
  64. {  
  65.     [super didReceiveMemoryWarning];  
  66.     // Dispose of any resources that can be recreated.  
  67. }  
  68.   
  69. @end  

非常簡單,關鍵就是在控制器中添加一個事件觀察者來接收消息:

  1. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(preferredContentSizeChanged:) name:UIContentSizeCategoryDidChangeNotification object:nil]; // 當不同類別的字體大小發生變化時發送消息給self  

另外要注意的是如果以self.content = @"abcdefghijklmnopqrstuvwxyz"的方式簡單初始化self.content的內容,那麼在調整完文字大小回到程序時self.content的內容可能已經被回收,可以看到文字內容顯示爲空。因此在將self.content賦值給self.textView.attributedText前,self.content必須要retain一次,也就是self.content必須要以init或者copy等方式獲得:

  1. NSURL *url = nil;  
  2.    // url = [[NSBundle mainBundle] URLForResource:@"Basic Interaction.rtf" withExtension:nil];  
  3.    url = [[NSBundle mainBundle] URLForResource:@"book.txt" withExtension:nil];  
  4.    NSMutableAttributedString *attributedTextHolder = [[NSMutableAttributedString alloc] initWithFileURL:url options:@{} documentAttributes:nil error:nil];  
  5.    [attributedTextHolder addAttribute:NSFontAttributeName value:[UIFont preferredFontForTextStyle:UIFontTextStyleBody] range:NSMakeRange(0, attributedTextHolder.length)];  
  6.    // NSLog(@"%@", attributedTextHolder);  
  7.    self.content = [attributedTextHolder copy];  

必須重寫viewDidUnload和dealloc方法來移除事件觀察者:

  1. - (void)viewDidUnload  
  2. {  
  3.     [[NSNotificationCenter defaultCenter] removeObserver:self];  
  4.       
  5.     [super viewDidUnload];  
  6. }  
  7.   
  8. - (void)dealloc  
  9. {  
  10.     [[NSNotificationCenter defaultCenter] removeObserver:self];  
  11. }  

重點看看收到消息後調整字體大小的方法:

  1. -(void)preferredContentSizeChanged:(NSNotification *)noti  
  2. {  
  3.     static const CGFloat textScaleFactor = .8;  
  4.     NSString *textStyle = [self.textView tkd_textStyle]; // 先設置樣式  
  5.     UIFont *font = [UIFont tkd_preferredFontWithTextStyle:textStyle scale:textScaleFactor]; //後設置字體(包括樣式和大小)  
  6.       
  7.     self.textView.font = font;  
  8. }  

在這裏用到的tkd_textStyle和tkd_preferredFontWithTextStyle:scale:是調整字體樣式和大小關鍵。在這裏使用了IntroduceTextKitDemo中的Categories中的類別和方法:

下面來看看取得字體樣式的整個流程:
(1)在FontResizeViewController.m中調用UITextView類別的tkd_textStyle方法。
  1. NSString *textStyle = [self.textView tkd_textStyle]; // 先設置樣式  
(2)在UITextView+TextKitDemo.m中的tkd_textStyle方法調用UIFont類別的tkd_textStyle方法。
  1. - (NSString *)tkd_textStyle  
  2. {  
  3.     return [self.font tkd_textStyle];  
  4. }  
(3)在UIFont+TextKitDemo.m中的tkd_textStyle方法中調用UIFontDecsriptor類別的tkd_textStyle方法。
  1. - (NSString *)tkd_textStyle  
  2. {  
  3.     return [self.fontDescriptor tkd_textStyle];  
  4. }  
(4)在UIFontDescriptor+TextKitDemo.m的tkd_textStyle方法中回調字體樣式結果。
  1. - (NSString *)tkd_textStyle  
  2. {  
  3.     return [self objectForKey:@"NSCTFontUIUsageAttribute"];  
  4. }  


在設置後字體樣式後調用tkd_preferredFontWithTextStyle:scale:方法來設置字體,textStyle的參數使用了以上獲得的tkd_textStyle,scale的參數則使用了textScaleFactor。整個方法的工作流程是相似的:
(1)FontResizeViewController.m
  1. UIFont *font = [UIFont tkd_preferredFontWithTextStyle:textStyle scale:textScaleFactor]; //後設置字體(包括樣式和大小)  
(2)UIFont+TextKitDemo.m
  1. + (UIFont *)tkd_preferredFontWithTextStyle:(NSString *)aTextStyle scale:(CGFloat)aScale  
  2. {  
  3.     UIFontDescriptor *newFontDescriptor = [UIFontDescriptor tkd_preferredFontDescriptorWithTextStyle:aTextStyle scale:aScale];  
  4.   
  5.     return [UIFont fontWithDescriptor:newFontDescriptor size:newFontDescriptor.pointSize];  
  6. }  
(3)UIFontDescriptor+TextKitDemo.m
  1. + (UIFontDescriptor *)tkd_preferredFontDescriptorWithTextStyle:(NSString *)aTextStyle scale:(CGFloat)aScale  
  2. {  
  3.     UIFontDescriptor *newBaseDescriptor = [self preferredFontDescriptorWithTextStyle:aTextStyle];  
  4.   
  5.     return [newBaseDescriptor fontDescriptorWithSize:lrint([newBaseDescriptor pointSize] * aScale)];  
  6. }  


這就是整個程序的工作過程,主要還是參照和使用了IntroduceToTextKit這個Demo。
最後看看程序運行結果:
調整字體前:


調整Text Size到最大:

調整後的文本:

 

轉自:http://blog.csdn.net/iunion/article/details/12184983

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章