2

私はアップルでGUIのプログラミングを始めたばかりです(これまでのところフレームワークは問題ないようですが、ドキュメントは他のドキュメントよりもはるかに有益ではありません... Qt、.Net、javaなど)。

私が抱えていた問題の1つは、誰が何を所有しているかを理解することです。たとえば、CTLineRefCreateWithAttributedStringを呼び出すと、結果のCTLineRefは属性付きの文字列を所有しますか?属性付きの文字列が変更可能で、変更した場合はどうなりますか?これはCTLineRefを台無しにしますか?

ドキュメントは啓蒙的ではありませんでした。

CTLineRefのリファレンスには、この件に関する情報は含まれていません: https ://developer.apple.com/library/mac/#documentation/Carbon/Reference/CTLineRef/Reference/reference.html

いくつかの例では、文字列が解放されていません。これは、所有されていることを示すものです: https ://developer.apple.com/library/mac/#documentation/StringsTextFonts/Conceptual/CoreText_Programming/Operations/Operations.html

いくつかの例は文字列をリリースしますが、そうではないことを示唆しています: https ://developer.apple.com/library/mac/#samplecode/CoreAnimationText/Listings/VectorTextLayer_m.html

(これはリンゴではありませんが、彼は私にもっと情報を与えているようです) http://www.cocoanetics.com/2011/01/befriending-core-text/

それで、文字列はコピーされますか?CFMutableAttributedStringRefを使用する場合、それを変更することはできますか(後で新しいCTLineRefを作成する必要があると思います)?

これは具体的な例ですが、これは私が無数の場所で出くわした質問です。どんな助けでも大歓迎です。これらを支配するルールがいくつかあるに違いないと思いますが、それらのルールが何であるか、どこで見つけることができるかについては、少しもわかりません。

4

3 に答える 3

4

求める管理ルールは、CoreFoundationメモリ管理ガイドに記載されています。重要なポイントは、CTLineRefが属性付き文字列を所有しているかどうかを実際に知る必要がないということです。どのオブジェクトにも複数の所有者を含めることができます。あなたが心配する必要があるのは、あなたが弦を所有しているかどうかそしてあなたが所有権を放棄するのに最も適切な場所はどこにあるかということだけです。CTLineRefの作成後に完了した場合は、自由にリリースしてください。

残りの部分については、CTLineRefの実装の詳細を検討してください。CTLineRefがそのドキュメントに記載されているルールに従っていて(それが実行している)、属性付きの文字列を保持する必要がある場合、CTLineRefはそれを内部的に保持します。内部でコピーを作成する可能性もあり(これは可能性が高いです)、したがって、元のコピーを気にしなくなります。たぶん、それは火星のサーバーに文字列を送信し、後で必要になるたびにそれを照会します(可能性は低いです)。重要な点は、それが何をするかに関係なく、不要になった場合は安全に文字列を解放できるということです

可変性とコピー動作に関しては、もう少しあいまいです。ドキュメントが動作について明示されていないのは正しいです。ドキュメント、オブジェクトが不変であることを明示しています。つまり、実際に入力文字列をコピーする(またはその内容を別の文字列に解析する)ことがほぼ保証されているということですあなたが言及した正確な理由のために、オブジェクトは常に入力文字列のコピーを作成する必要があることは一般的に理解されているベストプラクティスです-実装は提供された文字列が実際に変更可能かどうかを知ることができません。実装を堅牢な状態に保つには、その内部状態を外部から変更できないようにする必要があります。その保証を行う唯一の方法は、文字列をコピーすることです。これは、可変クラスにも当てはまります。

于 2012-08-03T16:28:18.047 に答える
0

MutableStringのことは問題ではないはずです-CTLineドキュメントはそれが不変であると明確に述べています。したがって、作成後に変更する方法はありません。知っておく必要があるのはそれだけです。CTLineを作成した文字列をコピーするか、保持するか、または何をするかは関係ありません。これはフリーズされたオブジェクトです。

また、マットの優れた答えをサポートするためだけに、保持/解放の全体的なポイントは、オブジェクトが「所有されている」必要があるというひどい考えから逃れることです。このように考えることは役に立ちません。たとえば、オブジェクトを解放する責任はありません。オブジェクトの寿命は不明です。保持/解放は、単純なガベージコレクターのようなものです。

簡単なルールに従う必要があります。ルールは、十分に文書化されているAppleのソースから直接学ぶのが最適です。これらの単純なルールは常に守られています。

したがって、いいえ、各機能のドキュメントに特定のメモリ管理ガイドラインは表示されません。本当に必要ありません。まだクリックされていない場合は、基本に戻る必要があります。

于 2012-08-03T18:36:55.187 に答える
0

あなたの質問に答えるために、CTLine. 文字列を変更する前と変更した後に、行の説明を表示することもできます。

CFMutableAttributedStringRef mas = CFAttributedStringCreateMutable(NULL, 0);
CFAttributedStringReplaceString(mas, CFRangeMake(0, 0), CFSTR("world"));
CTLineRef line = CTLineCreateWithAttributedString(mas);
NSLog(@"mas count = %ld", CFGetRetainCount(mas));
NSLog(@"line before change = %@", line);
CFAttributedStringReplaceString(mas, CFRangeMake(0, 0), CFSTR("hello "));
NSLog(@"line after change = %@", line);

多くの場合、オブジェクトの保持カウントを確認しても無駄ですが、この場合は有益です。

2012-08-03 12:11:10.717 coretext[44780:f803] count before creating line = 1
2012-08-03 12:11:10.720 coretext[44780:f803] count after creating line = 1

保持カウントは前後で 1 であり、私は参照をCFAttributedStringCreateMutable所有しているため (所有参照が与えられるため) CTLine、. そのCTLineため、文字列は保持されません。文字列への参照を保持せずに保持することはほとんどありません。

文字列を変更する前の行の説明は次のとおりです。

2012-08-03 12:11:10.721 coretext[44780:f803] line = CTLine: run count = 1, string range = (0, 5), width = 28.6758, A/D/L = 9.24023/2.75977/0, glyph count = 5
{
    CTRun: string range = (0, 5), characters = { 0x0077, 0x006f, 0x0072, 0x006c, 0x0064 }, attributes =
<CFBasicHash 0x6d69ce0 [0x1227b38]>{type = mutable dict, count = 1,
entries =>
    2 : <CFString 0xab1b0 [0x1227b38]>{contents = "NSFont"} = CTFont <name: Helvetica, size: 12.000000, matrix: 0x0>
CTFontDescriptor <attributes: <CFBasicHash 0xd345ed0 [0x1227b38]>{type = mutable dict, count = 1,
entries =>
    1 : <CFString 0xabbd0 [0x1227b38]>{contents = "NSFontNameAttribute"} = <CFString 0x6d69720 [0x1227b38]>{contents = "Helvetica"}
}
>
}
}

説明には文字列が含まれていませんが、文字の配列が含まれていることに気付きました。したがって、行はおそらく文字列のコピーも保持していません。文字列を解析して、独自の非公開表現を作成します。

文字列を変更した後の行の説明は次のとおりです。

2012-08-03 12:11:10.722 coretext[44780:f803] line = CTLine: run count = 1, string range = (0, 5), width = 28.6758, A/D/L = 9.24023/2.75977/0, glyph count = 5
{
    CTRun: string range = (0, 5), characters = { 0x0077, 0x006f, 0x0072, 0x006c, 0x0064 }, attributes =
<CFBasicHash 0x6d69ce0 [0x1227b38]>{type = mutable dict, count = 1,
entries =>
    2 : <CFString 0xab1b0 [0x1227b38]>{contents = "NSFont"} = CTFont <name: Helvetica, size: 12.000000, matrix: 0x0>
CTFontDescriptor <attributes: <CFBasicHash 0xd345ed0 [0x1227b38]>{type = mutable dict, count = 1,
entries =>
    1 : <CFString 0xabbd0 [0x1227b38]>{contents = "NSFontNameAttribute"} = <CFString 0x6d69720 [0x1227b38]>{contents = "Helvetica"}
}
>
}
}

行のグリフ数や文字配列が変更されていないことがわかります。このことから、文字列を変更しても線は変わらないと結論付けることができます。文字列を変更する前後に実際に線を引くことで、さらにテストできます。それは読者の練習問題として残しておきます。

于 2012-08-03T17:17:59.063 に答える