12

Objective-C は、Apple が Mac OS X および iPhone の開発に使用しているため、広く使用されています。Objective-C 言語のお気に入りの「隠れた」機能は何ですか?

  • 回答ごとに 1 つの機能。
  • ドキュメントへのリンクだけでなく、機能の例と簡単な説明を提供してください。
  • 最初の行としてタイトルを使用してフィーチャにラベルを付けます。
4

8 に答える 8

20

メソッドの入れ替え

基本的に、実行時にメソッドの 1 つの実装を別の実装に交換できます。

ここにコードを使用した説明があります。

巧妙な使用例の 1 つは、共有リソースの遅延ロードです。通常は、ロックを取得し、必要に応じsharedFooて を作成し、fooアドレスを取得してロックを解放し、 を返すことでメソッドを実装しfooます。これにより、fooが 1 回だけ作成されるようになりますが、その後のすべてのアクセスでは、不要になったロックで時間が浪費されます。

メソッドのスウィズリングを使用すると、以前と同じことができますが、fooが作成されたら、スウィズリングを使用して の最初の実装を、チェックを行わず、作成されたことがわかっている をsharedFoo返すだけの 2 番目の実装と交換します。foo

もちろん、メソッドの入れ替わりはトラブルに巻き込まれる可能性があり、上記の例が悪い考えである状況もあるかもしれませんが、ちょっと...それが隠された機能である理由です.

于 2008-10-18T05:23:30.930 に答える
16

ポージング

Objective-C では、クラスがアプリケーション内の別のクラスを完全に置き換えることができます。置換クラスは、ターゲット クラスの「ポーズ」と呼ばれます。ターゲット クラスに送信されたすべてのメッセージは、代わりにポージング クラスによって受信されます。クラスが課すことができるいくつかの制限があります。

  • クラスは、その直接的または間接的なスーパークラスの 1 つとしてのみポーズをとることができます
  • ポージング クラスは、ターゲット クラスに存在しない新しいインスタンス変数を定義してはなりません (ただし、メソッドを定義またはオーバーライドすることはできます)。
  • ポージングの前に、メッセージがターゲット クラスに送信されていてはなりません。

ポージングは​​、カテゴリと同様に、既存のクラスをグローバルに拡張できます。ポージングでは、カテゴリにない 2 つの機能が許可されます。

  • ポージング クラスは、スーパーを通じてオーバーライドされたメソッドを呼び出すことができるため、ターゲット クラスの実装を組み込むことができます。
  • ポージング クラスは、カテゴリで定義されたメソッドをオーバーライドできます。

例:

@interface CustomNSApplication : NSApplication
@end

@implementation CustomNSApplication
- (void) setMainMenu: (NSMenu*) menu
{
     // do something with menu
}
@end

class_poseAs ([CustomNSApplication class], [NSApplication class]);

これにより、setMainMenu から NSApplication へのすべての呼び出しがインターセプトされます。

于 2008-10-17T10:37:18.757 に答える
15

オブジェクトの転送/メソッドがありません

メソッドのないメッセージがオブジェクトに送信されると、ランタイム システムは、あきらめる前に呼び出しを処理する別の機会をオブジェクトに与えます。オブジェクトが -forward:: メソッドをサポートしている場合、ランタイムはこのメソッドを呼び出し、未処理の呼び出しに関する情報を渡します。転送された呼び出しからの戻り値は、メソッドの元の呼び出し元に伝播されます。

-(retval_t)forward:(SEL)sel :(arglist_t)args {
  if ([myDelegate respondsTo:sel])
 return [myDelegate performv:sel :args]
 else
 return [super forward:sel :args];
 }

Objective-C Pocket Reference の内容

これは非常に強力で、さまざまな DSL やレールなどのために Ruby コミュニティで頻繁に使用されています。Objective-C と Ruby の両方に影響を与えた Smalltalk で生まれました。

于 2008-10-18T02:45:43.543 に答える
11

ISA スイッチング

オブジェクトのすべての動作をオーバーライドする必要がありますか? 1 行のコードでアクティブなオブジェクトのクラスを実際に変更できます。

obj->isa = [NewClass class];

これは、そのオブジェクトのメソッド呼び出しを受け取るクラスのみを変更します。メモリ内のオブジェクトのレイアウトは変更されません。したがって、これは、同じ ivar (または他のサブセットを持つクラス) を持つクラスのセットがあり、それらを切り替えたい場合にのみ本当に役立ちます。

私が書いたコードの 1 つでは、これを遅延読み込みに使用しています。これは、 class のオブジェクトを割り当て、Aいくつかの重要な ivar (この場合は主にレコード番号) を埋め、isaポインターを に切り替えるLazyAreleaseandのような非常に小さなセット以外のメソッドretainが呼び出されると、LazyAディスクからすべてのデータがロードされ、ivar への入力が完了し、isaポインターが に戻りA、呼び出しが実際のクラスに転送されます。

于 2009-03-25T01:11:39.653 に答える
10
#include <Foundation/Debug.h>

そのヘッダー ファイル内のメモリ リーク、時期尚早の解放などを追跡するための多くのツール。

于 2008-10-17T15:39:05.650 に答える
10

カテゴリー

カテゴリを使用すると、サブクラス化せずに組み込みクラスにメソッドを追加できます。完全な参照

NSString や NSData など、一般的に使用されるクラスに便利なメソッドを追加すると便利です。

于 2008-10-22T20:15:07.493 に答える
4

Objective-Cランタイムリファレンス

Objective-CのシンタックスシュガーがObject-Cランタイムである通常のC関数呼び出しに変換されることを忘れがちです。ランタイムで実際に何かを調べて使用する必要はないでしょう。そのため、これを「隠し機能」と見なします。

ランタイムシステムを使用する方法を説明しましょう。

誰かがサードパーティによって使用される外部フレームワークAPIを設計しているとしましょう。そして、誰かがデータのパケットを抽象的に表すフレームワークでクラスを設計することを、私たちはそれと呼びますMLAbstractDataPacket。これで、フレームワークでサブクラスにリンクしMLAbstractDataPacket、サブクラスデータパケットを定義するのはアプリケーション次第です。すべてのサブクラスはメソッドをオーバーライドする必要があります+(BOOL)isMyKindOfDataPacket:(NSData *)data

その情報を念頭に置いて...

MLAbstractDataPacketの形式で提供されるデータのパケットに対して正しい初期化されたクラスを返す便利なメソッドが提供されていると便利です+(id)initWithDataPacket:(NSData *)data

ここでの問題は1つだけです。スーパークラスは、そのサブクラスについては知りません。したがって、ここでは、ランタイムメソッドobjc_getClassList()を一緒に使用しobjc_getSuperclass()て、MLAbstractDataPacketのサブクラスであるクラスを見つけることができます。サブクラスのリストを取得したら、サブクラス+isMyKindOfDataPacket:が見つかるか見つからなくなるまで、それぞれを試すことができます。

これに関するリファレンス情報は、http://developer.apple.com/documentation/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.htmlにあります。

于 2008-10-18T07:24:28.067 に答える
0

[myArray writeToFile:myPath atomically:YES]私は、すべての引数にラベルがある のような冗長なメソッド命名が好きです。

于 2008-10-22T20:23:43.407 に答える