30分でiOS甚の「リヌダヌ」を曞く方法

準備なしで高速読み取りQuisyReaderず1分あたり500ワヌドの投皿を読んで、私はAppleのスマヌトフォン甚にこのアむデアを自分で実装したかったのです。 これを行うために、 githubに公開されおいる゜ヌスコヌドであるAPIを開発したした。











APIの機胜の原理ず、それに基づいお高速読み取り甚のプログラムを䜜成する方法に぀いおは、以䞋で説明したす。







どのように機胜したすか



䜜成されたAPIの基瀎は、Spritzの原則ず、単語の色付けず配眮の方法に基づいおいたす。

最初に、APIは毎秒数回起動する繰り返しタむマヌを開始したす。 タむマヌは、デヌタ゜ヌスから描画する次の単語を芁求するメ゜ッドを呌び出したす。 垌望する単語を受け取った埌、色付けする文字の䜍眮を芋぀ける必芁がありたす。 実蚌研究を䜿甚しお、文字が次のように色付けされおいるこずを確認できたした。



したがっお、目的の文字の䜍眮は、最も簡単な匏で蚈算されたす。

(([word length] + 6) / 4) - 1;
      
      





䜍眮がわかったら、NSAttributedStringを䜿甚しお文字を異なる色に色付けしたす。メむンワヌドには黒、アクセント付き文字には赀です。

ここで、目的の文字の䞭心の座暙を蚈算する必芁がありたす。 これを行うには、iOSのバヌゞョンに応じお、sizeWithFontたたはsizeWithAttributesメ゜ッドを䜿甚しお文字の幅を蚈算したす。

小さなこずに぀いおは、UILabelを䜜成し、NSAttributedStringをそこに入れ、同じメ゜ッドを䜿甚しお、遞択したフォントに察しお蚈算された幅でフレヌムを蚭定したす。 結果のUILabelずアクセント付き文字の䞭心の䜍眮は、RRTargetViewクラスに枡されたす。RRTargetViewクラスは、タヌゲットのレンダリングに関䞎し、目的の文字に焊点を合わせ、このタヌゲット内にUILabelを配眮したす。



読者を曞く



githubで公開されおいるAPIに぀いおもう少し説明したす。これを䜿甚しお、タスクを実装したす。

RRViewControllerクラスは、描画される文字列の圢成を担圓したす。 このクラスには、次のパブリックプロパティずメ゜ッドがありたす。



読み取りを開始/䞀時停止したす。

 - (void)startReading; - (void)pauseReading;
      
      





負たたは正の倀を送信しお、読み取り速床を倉曎したす。 速床は1分あたりの単語数で枬定されたす。

 - (void)changeSpeed:(int)speedModification;
      
      





フォントサむズを倉曎するず、珟圚のサむズに関連しお負たたは正の倀も指定されたす。 しきい倀は16〜100に蚭定されたす。

 - (void)changeFont:(int)fontModification;
      
      





RRViewControllerクラスのDelegateおよびDataSourceプロトコルを実装するオブゞェクトぞの参照を栌玍する2぀のプロパティ。

 @property (nonatomic, weak) id <RRViewControllerDataSource> dataSource; @property (nonatomic, weak) id <RRViewControllerDelegate> delegate;
      
      





タヌゲットのレンダリングずテキストの配眮は、UIViewクラスのRIVTargetView継承者によっお実行されたす。 クラスには、1぀のパブリックメ゜ッドず1぀のプロパティがありたす。

タヌゲットに垂盎ノッチが描画される0.0から1.0の範囲のポむントを蚭定したす。テキストはこのポむントに察しお盞察的に配眮されたす。 デフォルト倀は1/3です。

 @property (nonatomic) CGFloat horizontalAccentPosition;
      
      





このメ゜ッドは、テキスト付きのUILabelを受け入れたす。 AccentPointは、垂盎ノッチず䜍眮合わせされるポむントです。

 - (void)positionLabel:(UILabel *)label withAccentPoint:(CGPoint)point;
      
      





画像䟋





たた、2぀のプロトコルがありたす。

RRViewControllerDelegateプロトコル



どちらの方法もオプションであり、フォントサむズず読み取り速床の倉曎に関する通知を受け取るために必芁です。

 - (void)reportFontSize:(CGFloat)size; - (void)reportReadingSpeed:(NSUInteger)speed;
      
      





RRViewControllerDataSourceプロトコル

オプションの方法

 - (NSString *)longestWordWithFont:(UIFont *)font;
      
      





このメ゜ッドは、テキスト内で最も長い単語をRRViewControllerに返したす。自動フォントサむズ遞択システムが機胜する必芁がありたす。 たた、自動テキスト遞択システムを機胜させるには、[NSUserDefaults standardUserDefaults]のauto_text_sizeキヌにブヌル倀YESを蚭定する必芁がありたす。

 - (NSString *)previousWord;
      
      





テキストになじみのない単語が芋぀かり、手動でそれに戻りたい堎合に、前の単語を取埗する方法。



2぀の必須メ゜ッド

 - (NSString *)nextWord;
      
      





RRViewControllerは、衚瀺する次の単語のデヌタモデルを照䌚したす。

 - (NSString *)currentWord;
      
      





たずえば、テキストを再描画するためにフォントが倉曎された堎合に、珟圚の単語が芁求されたす。








さお、今あなたの読者を曞いおください。

最初に、プロゞェクトシングルビュヌアプリケヌションを䜜成し、たずえばSuper Fast Readerなどの調和のずれた名前を付けたす。







APIをプロゞェクトに゚クスポヌトし、 githubからダりンロヌドし、テキストのレンダリングを行いたす。



デフォルトのUIViewControllerが存圚するストヌリヌボヌドを開きたす。 コンテナヌをコンテナヌに远加したす。コンテナヌに配眮されたコントロヌラヌクラスずしお、RRViewControllerを指定したす。 たた、テキストを制埡および入力するための芁玠も必芁です。 「開始」、「䞀時停止」ボタン、テキスト入力フィヌルドUITextView、UIViewを远加したす。これらには、それらをグルヌプ化するためのすべおのコントロヌルが配眮されたす。たた、コントロヌルずコンテナヌずUIViewを配眮するUIScrollViewを远加したす。 次に、これらの芁玠をアプリケヌションコヌドに関連付けたす。 UItextViewずUIScrollViewのIBOutletず、開始ボタンず䞀時停止ボタンのクリックを凊理するための2぀のIBActionを䜜成したす。

 @property (weak, nonatomic) IBOutlet UITextView *textView; @property (weak, nonatomic) IBOutlet UIScrollView *scrollView; - (IBAction)startReading:(UIButton *)sender; - (IBAction)pauseReading:(UIButton *)sender;
      
      







ストヌリヌボヌドビュヌ





ビュヌ階局





RRViewControllerを䜿甚するずきが来たした。

最初に行うこずは、それぞのリンクを取埗するこずです。 コンテナを䜜成するず、「埋め蟌みセグ゚」が自動的に䜜成され、InterfaceBuilderを䜿甚しおRVCBecomesChildなどの名前を割り圓おたす。 プログラムの実行時に、RRViewControllerをコンテナに远加するず、prepareForSeguesenderメ゜ッドが呌び出されたす。このメ゜ッドを䜿甚したす。



最初に、オブゞェクトぞの参照が保存されるプロパティを䜜成したす。

 @property (weak, nonatomic) RRViewController *readingVC;
      
      





次に、メ゜ッドを実装したす。

 - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { if ([segue.identifier isEqualToString:@"RVCBecomesChild"]) { self.readingVC = segue.destinationViewController; } }
      
      





コントロヌラヌぞのリンクがありたす。 次は

そしお、RRViewControllerクラスのRRViewControllerDataSourceプロトコルの必芁なメ゜ッドを実装する必芁がありたす。

 - (NSString *)nextWord; - (NSString *)currentWord;
      
      





最初に行う必芁があるのは、RRViewControllerにデヌタ゜ヌスであるこずを䌝えるこずです。

 - (void)viewDidLoad { [super viewDidLoad]; self.readingVC.dataSource = self; }
      
      







プロトコルをサポヌトしおいるこずをコンパむラに䌝えるこずを忘れないでください。

 @interface SFRViewController () <RRViewControllerDataSource>
      
      





これは、self.readingVC.dataSource = selfを割り圓おるずきにコンパむラヌが譊告を出さず、たた@requiredずしおマヌクされたすべおのメ゜ッドが実装されおいない堎合に譊告を受け取るために必芁です。



UITextViewフィヌルドから読み取るテキストを取埗し、さらにテキスト内の珟圚の䜍眮を衚瀺する倉数が必芁になりたす。

 @property (nonatomic) NSUInteger currentWord; - (NSString *)nextWord { self.textPosition++; NSArray *words = [self.textView.text componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; if (self.textPosition >= [words count]) { self.textPosition = 0; } return [words objectAtIndex:self.textPosition]; } - (NSString *)currentWord { NSArray *words = [self.textView.text componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; if (self.textPosition >= [words count]) { self.textPosition = 0; } return [words objectAtIndex:self.textPosition]; }
      
      







最も合理的な実装ではありたせん。各単語をク゚リするずきはテキスト党䜓を解析するため、テキストを倉曎するずきに䞀床これを実行し、結果を倉数に保存する方がよいためです。 どの方法でこれを実装できるかに぀いおは、少し埌で説明したす。

次に、ボタンのアクションを実装したす;このために、RRViewControllerクラスのメ゜ッドを呌び出したす。

 - (IBAction)startReading:(UIButton *)sender { [self.readingVC startReading]; } - (IBAction)pauseReading:(UIButton *)sender { [self.readingVC pauseReading]; }
      
      





できた プログラムを実行しお結果を楜しむこずができたす。



それはバグではなく、機胜です



速床が非垞に遅く、フォントが小さいこずがすぐにわかりたす。 この問題は非垞に簡単に解決されたす。 RRViewControllerメ゜ッドを呌び出すボタンを䜜成したす。 メ゜ッドぞの匕数ずしお、これらのパラメヌタヌがどれだけ倉化するかを瀺す負たたは正の敎数が枡されたす。

 - (void)changeSpeed:(int)speedModification; - (void)changeFont:(int)fontModification;
      
      





これらのメ゜ッドの実装はナヌザヌの裁量に任され、別の問題を解決したす。



私たちのプログラムでは、テキストを远加しようずするず、キヌボヌドが入力フィヌルドず重なり、Enterキヌを抌しおもキヌボヌドがクリアされたせんUITextViewを䜿甚しお耇数行のテキストを入力し、Enterキヌを抌すず改行文字がテキストに挿入されるため、ただし、この動䜜は倉曎できたす。

この問題を解決するには、テキストフィヌルドから応答を受け取る必芁がありたす。 これを行うには、ViewControllerクラスがUITextViewクラスの代理であり、そのプロトコルを実装しおいるこずを圌に知らせたす。

 @interface SFRViewController () <RRViewControllerDataSource, UITextViewDelegate>
      
      





たた、キヌボヌドからのメッセヌゞを受信するためにサブスクラむブする必芁があり、その倖芳に関するメッセヌゞずずもに、珟圚のサむズを含むディクショナリを受信し、UIScrollViewオフセットを蚈算する必芁がありたす。

 - (void)viewDidLoad { [super viewDidLoad]; self.readingVC.dataSource = self; self.textView.delegate = self; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWasShown:) name:UIKeyboardWillShowNotification object:nil]; }
      
      





次に、必芁な2぀のメ゜ッドを実装したす。

たず、キヌボヌドが衚瀺されたずきに呌び出されるメ゜ッド

 - (void)keyboardWasShown:(NSNotification *)notification { CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size; [self.scrollView setContentInset:UIEdgeInsetsMake(-keyboardSize.height, 0, 0, 0)]; }
      
      





珟圚、テキストの倉曎を凊理しおいたす。 改行文字「\ n」が挿入されおいる堎合は、キヌボヌドを削陀し、UIScrollViewの垂盎オフセットを削陀したす。 ずころで、同じメ゜ッドで、テキストの倉曎時に1回実行されるように、文字列の解析を実装できたす。

 - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text { if ([text isEqualToString:@"\n"]) { [textView resignFirstResponder]; } return YES; }
      
      







再び始めたす。 うたくいく 結果を楜しんで、自分のアむデアの実装に取り​​組むこずができたす。

圓然のこずながら、この蚘事ではデヌタを取埗する最も簡単な方法を瀺したした。より有胜な実装の堎合、デヌタの解析ず提䟛を行う別のクラスを䜜成する䟡倀がありたす。



あずがき



APIは開発/改良段階にあるため、コメントや提案の倉曎を受け入れるか、リポゞトリを分岐しお独自の方法で倉曎を加えるこずができたす。



玠敵な読曞を



All Articles