2013-11-01 159 views
15

問題創建適用於iOS 7

文本編輯器我需要了解如何TextKit工作,我怎麼可以用它來建立一個文本編輯器。我需要弄清楚如何僅繪製最終用戶與可見文本進行交互,或確定如何僅將可用文本應用於可見文本而不將屬性應用於processEditing方法中整個已更改的文本範圍。

背景

的iOS 7推出了TextKit。我有一個完全實現TextKit的標記器和代碼(參考Apple的TextKitDemo項目 - 下面提供了一個鏈接)...並且它可以工作。但是,它真的很慢。當文本被解析時,NSTextStorage會要求您在processEditing方法中在同一個線程上着色編輯文本的整個範圍。將作業卸載到線程無濟於事。這太簡單了。我已經到了只能重新修改範圍的地步,但是如果範圍太大,這個過程會很慢。在某些情況下,整個文檔可能會在更改後失效。

以下是我的一些想法。請讓我知道,如果任何這些將工作或可能推動我在正確的方向。

1)多NSTextContainers

閱讀看來我可以在NSLayoutManager內添加多個NSTextContainers的文檔。我假設通過這樣做,我應該能夠定義不僅可以在NSTextContainer中繪製的行數,而且還應該能夠知道哪個NSTextContainer對最終用戶可見。我知道,如果我走這條路,我將需要投入很多時間才能看出這是否可行。初始測試表明您只需要一個NSTextContainer。所以我必須繼承NSLayout的子類,或者在佈局管理器確定哪些文本進入哪個文本容器時創建一個包裝器。呸。另外,我不知道TextKit如何讓我知道是時候繪製一個特定的NSTextContainer了......也許這不是它的工作原理!

2)無效範圍瓦特/ NSLayoutManager

使用invalidateLayoutForCharacterRange無效LayoutManager的:actualCharacterRange :.但是,這實際上做了什麼,它將如何減少文本歸因階段?它什麼時候讓我知道一個特定的文本需要突出顯示?另外,我看到NSLayoutManager將懶洋洋地畫出字形......怎麼樣?什麼時候?這對我有什麼幫助?我如何利用此調用,以便在實際佈置文本之前將背景字符串歸屬?

3)覆蓋NS​​LayoutManager drawGlyphsForGlyphRange:atPoint:方法。

我真的不想這樣做。也就是說,在Mac OS X中,NSAttributedStrings具有臨時屬性的概念,其中樣式信息僅用於演示。這加快了突出顯示的過程!問題是,它不存在於iOS 7 TextKit框架中(或者它在那裏,我只是不知道它)。我相信通過使用這種方法,它可以給我使用臨時屬性的相同類型的速度......因爲我可以用這種方法回答所有佈局,顏色和格式問題,而無需觸及NSTextStorage歸因串。唯一的問題是,我不知道該方法如何與NSLayoutManager類中提供的其他方法相關。它是否保持寬度和高度的狀態? NSTextContainer太小時會修改它的大小嗎?另外,它只爲在文本緩衝區中添加的字符繪製字形。它不會重新繪製整個屏幕。只有它的一小部分...而且非常好。我對如何使用這個工具有一些想法......但我真的沒有想要佈置字形的願望。這太方便了,我還沒有找到一個很好的例子。

我將不勝感激任何幫助,你必須提供。

作爲感謝,我列出了所有我已經使用在過去的幾年中幫助我去,我現在在哪裏,它們對您有幫助的希望的框架和參考。

語法高亮框架:

資源的速度更快:

大部分框架都是一樣的。它們或者不考慮上下文切換(或者你必須編寫包裝來提供上下文)範圍,或者它們不修改上下文範圍,因爲用戶修改了文本(如字符串,多行註釋等)。最後一項要求非常重要。因爲如果令牌生成器無法確定哪些範圍受到更改的影響,您最終必須再次解析並重新命名整個字符串。唯一的例外是Crimson編輯。這個標記器的問題是它在標記時不保存狀態。在繪製時間,算法使用標記來確定繪圖的狀態。它從文檔的頂部開始,一直到文本的可見範圍。不用說,我通過在文檔的某些部分緩存文檔的狀態來優化這一點。

另一個問題是,框架不遵循Apple所做的相同的MVC模式 - 這是可以預料的。具有完整工作編輯器的框架全部使用由它們構建的API(即GTK,Windows等)提供的鉤子,爲它們提供了何時以及何時繪製到屏幕的哪一部分的信息。在我的情況下,TextKit似乎要求您在processEditing中對整個更改的範圍進行歸因。

也許我的觀察是錯誤的。 (我希望他們是!!)也許,例如ParseKit會爲我需要它做的工作,我根本不知道如何使用它。如果是這樣,請讓我知道!並再次感謝!

+0

如果有人試圖實現上述建議,你會讓我知道它是怎麼回事?我很想聽聽你的發現!謝謝! – PeqNP

+0

我忘了補充一件事。我也試着覆蓋NSLayoutManager attributesAtIndex:effectiveRange :.我假設這返回一個NSDictionary與鍵/值對組成的NSForegroundColorAttributeName/UIColor等,但是,每次我試圖返回一個_basic_字典與此鍵/值對,程序掛起...但是,這可能成爲我可以潛在地提供屬性的地方......這是假設屬性被懶惰地查詢。我只能猜測,我需要使已更改的文本範圍無效,以使其正常工作。 – PeqNP

+0

我想我可能會擁有它;如果我可以確定用戶可見的文本範圍,我可以將屬性僅應用於processEditing中的該範圍,並在可見文本之前和之後標記無效範圍,並使用自定義屬性(或NSRanges列表, )。然後,我會在一個單獨的過程中卸載剩餘的工作,僅用於無效的文本。 – PeqNP

回答

9

我想通了。我沒有使用上述任何建議。這就是說,我現在得到的表現簡直令人難以置信。請記住YMMV。標記和緩存關於字符串的元數據的方式可能與我不同。但是,我能夠輸入1400行的PHP文件,並且只需0.015秒即可完成任何一項更改。簡直難以置信。

這裏是我採取的方法:

我的UIViewController是一個委託UITextViewDelegate和UIScrollViewDelegate。

當調用UITextViewDelegate.textViewDidChange:時,我確定當前最終用戶可以看到哪個範圍的文本。我這樣做是利用我現有的子類的UITextView並添加這個方法吧:

- (NSRange)visibleRangeOfText 
{ 
    CGRect bounds = self.bounds; 
    UITextPosition *start = [self characterRangeAtPoint:bounds.origin].start; 
    UITextPosition *end = [self characterRangeAtPoint:CGPointMake(CGRectGetMaxX(bounds), CGRectGetMaxY(bounds))].end; 
    return NSMakeRange([self offsetFromPosition:self.beginningOfDocument toPosition:start], 
        [self offsetFromPosition:start toPosition:end]); 
} 

在那之後,我傳遞的範圍內,以一個子類NSTextStorage對象,它會再執行魔術以確定哪些線路需要突出顯示。

UIScollViewDelegate方法調用也是如此。根據視圖的哪一部分被查看,我將可見範圍傳遞給我的子類NSTextStorage調用,並確定這些行是否已被歸因等。

我知道我要留給讀者很多東西。我最終使用了我現在的東西,並對它進行了一些修改,以適應上述實現。

我想分享一些我的發現,我發現有趣而實現這一點:

1)如果你試圖突出高於目前的線路,將光標顯示靜止的任何文字,你可能會看到光標在視圖內「跳」起來,然後回到最初的位置。我幾乎肯定這是由NSTextStorage.processEditing方法調用引起的。我能夠得到它的系統只突出顯示修改過的行......所以這個問題現在已經消失了。

2)本來我這樣做是爲了防止光標從跳來跳去:

NSRange selectedRange = [textView selectedTextRange]; 
[textView setScrollEnabled:NO]; 
NSRange visibleRange = [textView visibleRangeOfText]; 
[textStorage applyAttributesToRange:visibleRange]; 
[textView setScrollEnabled:YES]; 

它的工作...但[TextView的setScrollEnabled:NO]呼叫作出了巨大打擊性能。這個命令僅用了將近3/4秒就完成了1400行文件。我不確定是什麼導致它變慢,但我認爲這值得一提。

+0

+1分享:) –

+0

!無恥的插件警報!如果任何人有興趣,我已經創建了一個框架,提供語法高亮和一個接近完整的編輯器,你可以很容易地集成到你自己的名爲SchemeKit的iOS應用程序。你可以購買它在http://www.binpress.com/app/schemekit/1981?ad=31477 – PeqNP

+0

我正在實施一個類似的語法突出textview,我想知道你是否可以幫助我。現在一切正常,除了e佈局管理器需要很長時間才能加載。你做了什麼阻止了這個?你是如何確定已經歸因於什麼的?謝謝!另外,你的圖書館是否仍然可用? – Jacob

相關問題