この章とこの本全体から、iOSプログラミングのほとんどの情報が公開フレームワークに含まれていることは明らかですが、SDKには含まれていません。 これに関するAppleの非公式のポリシーは単純です。これはすべて使用できますが、ご自身の危険とリスクがある場合に限ります。 次のファームウェア更新中にコードが破損する場合があります。 あなた自身がリスクと利益の妥協点を見つけなければなりません。
エリカ・サダン、iPhone開発者の料理本
オリジナルこの章および本書で説明したように、iPhoneプログラミングの最も優れた部分のいくつかは、公開のiPhoneフレームワークに含まれていますが、SDKには含まれていません。 これに関するAppleの非公式のポリシーは明確です:これらのアイテムはプログラムで使用できますが、使用するのは自己責任で行い、ファームウェアのリリースごとにコードが破損する可能性があります。 リスクと報酬のバランスをとるのはあなた次第です。
免責事項
- ここに示すコードは、通常のiPhone(4Sを含む)およびiPad(新しいiPadを含む)で動作し、ジェイルブレイクを必要としません。
- すべてのソリューションは、iOS 5で記述およびテストされています。すべてのソリューションは、iOS 4.3との互換性もテストされています。 特に明記しない限り、iOS 4で動作します。 この記事の主要部分はiOS 6のリリース前に書かれたため、これらのソリューションはiOS 6との互換性についてテストされていません。
- 文書化されていないAPIを使用すると、アプリケーションがAppStoreに許可されない可能性があります。 または多分そうではない:-)
AppleがプライベートAPIの使用をどのように定義するかに興味がある人のために: 「 Appleは、プライベートAPIを使用していることをどのように知っていますか?」
- Appleは、iOSの次のリリースで実装を変更する可能性があり、コードで何かが壊れます。 ただし、これは解決可能であり、文書化されたAPIの下位互換性の実装と基本的には異なりません。 以下では、この問題をさらに詳しく調べました。
- 私が見つけたAPIに副作用がないことを保証することはできません。 ご自身の責任で使用してください。
- Apple Developer Programライセンス契約は、iOSのリバースエンジニアリングを禁止しています。
- 記事は完成中です。 建設的な批判は大歓迎です!
SDKのクイック検索ガイド
公式文書の範囲を超える何かをする必要があるとしましょう。
たとえば、バックライトレベルを変更します(iOS 5より前は、これはSDKの文書化された部分にありませんでした)。 Appleプログラマーは通常、関数と変数に意味のある表現力豊かな名前を付けることが知られています。これはSDKの検索に使用します。 これを行うには、トピックに関連するいくつかの単語(明るさ、レベル、画面など)を選択します。 スクリプトLookSDKForSymbol.sh(これは
nm
ラッパーです。このスクリプトと使用される他のツールについては、「
ツール」セクションで後述し
ます )をキーワードとしてパラメーターとして実行します。 スクリプトは、オブジェクトファイルで見つかった文字(クラス、関数、変数の名前)を返します。 問題の例:
$ LookSDKForSymbol.shライトレベル
U _UIBacklightLevelChangedNotification
./System/Library/CoreServices/SpringBoard.app/SpringBoardにあります
001b43c4 t-[UIApplicationバックライトレベル]
001b4360 t-[UIApplication setBacklightLevel:]
0025ce54 t-[UIDevice _backlightLevel]
0025ce40 t-[UIDevice _setBacklightLevel:]
...さらに数十文字
たとえば、ほとんどの結果はすぐに破棄できます。たとえば、
-[UIApplication backlightLevel]
はバックライト値を返しますが、設定しません。
残りの数十個以下の場合は、Googleにフィードを試行できます。 誰かが既に見つかったキャラクターに関連するAPIを調査しており、この場合、問題が解決したと考えています。 より複雑なケースでは、リバースエンジニアリングを実行する必要があります。つまり、見つかった機能がどのように機能するか、見つかったアラートを使用する方法などを見つける必要があります。
ユーティリティによって発行される文字列は、次のカテゴリに分類されます。
- Objective-CおよびC ++の関数、クラス、構造など。 Objective-Cに関連するものにはすべて、角括弧([])またはドル記号($)が含まれています。 C ++関数は通常、いくつかの名前空間に含まれているため、名前には名前空間解決文字である2つのコロン(::)が含まれています。
- Objective-Cブロック。 これらの一般的な外観は次のとおりです。
___{}{ }_block_invoke_{2}
例:
___22-[AXSystemServer init]_block_invoke_0
- 純粋なC関数。
- Objective-Cアラート。
_SBMenuButtonPressedNotification
などの通知で終了します。 - キー/定数。 通常、kで始まります(例:_
kCFUserNotificationAlternateButtonTitleKey
。
以降のアクションは、シンボルのカテゴリによって異なります。
- このフレームワークのヘッダーファイルを生成します。
class-dump-z Foundation> $ / iOS_private_headers / Foundation.h
ほとんどの場合、生成されたヘッダーファイルで十分です。クラスの継承階層、構造、メソッドなどは十分に説明する必要があります。そのため、少し時間を割いてAPIを把握し、提案で使用できます。
残念ながら、ヘッダーファイルに含まれる情報ではコードを機能させるのに十分でない場合があり、otoolで生成されたアセンブラコードを分析する必要があります。
Objective-Cコードを逆アセンブルするためのヒント:ほぼ確実に、objc_msgSend(オブジェクトへのメッセージの送信)などの関数呼び出しが発生します。 最初のパラメーターは常にオブジェクトへのポインターであり、2番目のパラメーターはセレクターへのポインターです。 メソッドの名前である文字列へのポインタ(「通常の」引数の残りは3番目、4番目などの引数です)。 この場合に送信されるメッセージのhexdump
を判断するには、 hexdump
が役立ちます。
- すぐに忘れることができます。 ブロックは(通常)ローカルであり、コードから呼び出すことはできません。
- 最も難しいオプション。 最も単純なケースでは、関数のシグネチャを選択できますが、それ以外の場合は逆アセンブリのみです。 この詳細については、 「不明な関数のシグネチャを見つける方法」セクションをご覧ください。
- 3つの主要なアラートセンター(Local、Darwin、およびCoreTelephony)のいずれかでアラートをキャッチしようとすることから始めましょう。 このタイプのアラートが届かない場合、次の2つのいずれかがあります。
-このタイプのアラートは、別の特別なアラートセンターに送られます。 見つかったアラートが属する同じフレームワークで、そのような通知センターのトレースを検索する必要があります。
-アラート配信は無効です。 このタイプのアラートの配信を有効にするメカニズムを見つけてください。
- この場合、ほとんどの場合、この定数をパラメーターとして受け入れる関数、またはこの定数をキーとする辞書があります。 いずれにしても、名前が同じ単語で始まる関数またはメソッドを探す必要があります(例:constant
kLockdownDeviceColorKey
> function lockdown_copy_value(...)
;
未知の関数のシグネチャを見つける方法は?
1.インターネット上で検索します。これは一般的ではありません。 私は非常に頻繁に中国のサイトに出くわしました、非常に有用な情報を持つ韓国語と日本語のサイトがありました。 通常、コード自体は、何が起こっているのか、この関数、このクラスなどがどのように使用されるのかを理解するのに十分です。 Objective-Cの冗長性と表現力に感謝します!
2.多くの単純な関数では、署名を推測することができます。
注意 、これは非常に危険です。
GSEventSetBackLightLevelなどのいくつかの単純な関数の使用は自明です。
void GSEventSetBackLightLevel(floatレベル);
他の多くの場合、次のトリックを使用しました(SBGetRingerSwitchState関数の例を使用)。
SInt32 ret = 5, out1 = 1, out2 = 2, out3 = 3, out4 = 4; void *libHandle = dlopen(SPRINGBOARD_SERVICES_PATH, RTLD_LAZY); SInt32 (*SBGetRingerSwitchState)(SInt32*,SInt32*,SInt32*,SInt32*) = dlsym(libHandle, "SBGetRingerSwitchState"); ret = SBGetRingerSwitchState(&out1, &out2, &out3, &out4); NSLog(@"%x %x %x %x %x", ret, out1, out2, out3, out4);
このコードの結果、次のことが判明しました
1)関数は、スイッチの実際の位置に
0x10000003
、
0x10000003
値を返しました。
2)変数
out2
はその値をselfに変更しました。 戻り値もスイッチに依存しません。
3)残りの変数は値を変更していません。
1)から、0x10000003はMACH_SEND_INVALID_
DEST
システムエラーに対応しているため、関数は
kern_return_t
型の値を返すと結論付けました。 どうやら、エラーは間違ったポートを指していた[この場合、ポートはマッハカーネル(マッハカーネル)の抽象化であり、プロセスの権利と優先度を特徴づけています]。 原則として、関数呼び出しでポート番号が使用される場合、それは最初の引数です。 2)から、2番目の引数を通じて、関数は参照によって特定の値を返します。
これらの単純なアクションの結果として、次の署名が取得されます。
kern_return_t SBGetRingerSwitchState(mach_port_t port, SInt32 *state);
ところで、getという名前にgetという単語が含まれている場合、Objective-Cの命名規則に従って、この関数は参照によって値を返す必要があります。 これは上記の例からも明らかです。
3.分解。 同じSBGetRingerSwitchStateの例。 otoolを使用します。
$ otool -p _SBGetRingerSwitchState -tV -arch armv6 SpringBoardServices | 少ない
000038cc b5f0 push {r4、r5、r6、r7、lr}
000038ce af03 add r7、sp、#12
000038d0 b092 sub sp、#72
000038d2 aa06 add r2、sp、#24 //レジスタr2の値が上書きされます
000038d4 9205 str r2、[sp、#20]
000038d6 ac08 add r4、sp、#32 // ...およびレジスタr4
000038d8 ab0f add r3、sp、#60 // ...およびr3
000038da 9304 str r3、[sp、#16]
000038dc 9103 str r1、[sp、#12] // r1の値はスタックに保存されます
000038de 4925 ldr r1、[pc、#148](0x3974)
000038e0 6011 str r1、[r2、#0]
000038e2 6020 str r0、[r4、#0] // r0の値もスタックに保存されます
...
このコードから、アームアセンブラの表面的な知識さえ使用して、関数が単語型の2つの引数を受け入れると仮定できます。
関数には2つの引数があることがわかります。 さらに最後まで行きます。
...
00003964 9e04 ldr r6、[sp、#16]
00003966 6836 ldr r6、[r6、#0]
00003968 9903 ldr r1、[sp、#12]
0000396a 600e str r6、[r1、#0]
//ほぼ対応します(C言語の観点から):* r1 = r6; つまり r1に保存されているアドレスに、r6の値が書き込まれます。
//これは、関数が参照によって値を返すことを意味します
0000396c 462e mov r6、r5
0000396e 4630 mov r0、r6
//関数の結果はr0に配置されます
00003970 b012 SPを追加、#72
00003972 bdf0 pop {r4、r5、r6、r7、pc}
...
一番下の行は次のとおりです。
int SBGetRingerSwitchState(int arg1, int* arg2);
このアセンブリコードの分析を続け、型を明確にして最終バージョンに到達します。
kern_return_t SBGetRingerSwitchState(mach_port_t port, SInt32 *state);
異なるファームウェアと異なるデバイス:何が壊れるか、どのように修正するか?
文書化されていないAPIがすべてのデバイスで必ずしも同じように機能するわけではないことは明らかです。 私の経験では、ほとんどの場合何も変わらず、APIはすべてのデバイスとすべてのファームウェアで同じように機能します。 したがって、たとえば、
UIDevice-IOKitExtensions拡張機能のすべての機能(IMEIの定義を除く)は、すべてのデバイスおよびすべてのファームウェアで同等に機能します。 iOSの更新時にどのような変更が発生しますか?
以下に実用的なオプションを示します。
互換性の問題を回避するために、単純なルールに従います:関数(たとえば
-[NSObject respondsToSelector:]
を使用)をチェックし、クラス(
SomeClass
場合
SomeClass
NSClassFromString(@"SomeClass")
は
nil
を返します)など。また、APIが欠落している場合にプログラムが何をすべきかを事前に考えてください。 ライブラリライブラリの動的リンクを使用する場合は、dlsym(...)およびdlopen(...)の戻り値でNULLが等しいかどうかも常に確認する必要があります。
例
例1:
サイドバイブレーションスイッチ(別名リング/サイレントスイッチ、ミュートスイッチ)の位置の決定
私が直面したタスクの1つは、サイドスイッチの位置を決定することでした。これは、元々はリング/サイレントスイッチと呼ばれていました。 このスイッチは、iPhoneおよびiPadで「静か」モードと通常/「大音量」モードを切り替えるために使用されます。 StackOverflowを検索すると、解決策が得られました。
#import <AudioToolbox/AudioToolbox.h> ... /* : 0: 1: */ int switchState() { // ... // , // kAudioSessionCategoryAmbient // ... UInt32 size = sizeof(CFStringRef)); CFStringRef route; AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &size, &route); // CFIndex len = CFStringGetLength(route); return (len > 0); // - , "" }
ただし、これはiOS 5では機能しません。新しいAPI(kAudioSessionProperty_AudioRouteDescription)を使用しても、オーディオ入力およびオーディオ出力に関する拡張情報が提供されるため、機能しませんでした。 (オーディオルート)
StackOverflowをさらに検索して、
この投稿を見つけました。 ライブラリ関数AudioServicesAddSystemSoundCompletion()について説明します。この関数の非標準的な動作は、開発者によってバグと見なされていました。
#import <AudioToolbox/AudioToolbox.h> ... void playSound() { AudioServicesAddSystemSoundCompletion(MySoundId, NULL, NULL, MyAudioServicesSystemSoundCompletionProc, AudioServicesPlaySystemSound(MySoundId); } void MyAudioServicesSystemSoundCompletionProc (SystemSoundID ssID, void *clientData) { // NSLog(@"Playback has been finished"); }
非標準の動作では、MyAudioServicesSystemSoundCompletionProcコールバックは、通常モードでのサウンド再生の最後に呼び出されますが、「サイレント」モードでAudioServicesPlaySystemSoundを呼び出した直後に呼び出されます。 これにより、スイッチの現在の状態を判断するための抜け穴が作成されます。 たとえば、再生するオーディオファイルの長さが1秒の場合、サイレントモードとラウドモードでMyAudioServicesSystemSoundCompletionProc()を呼び出す間の時間差は1秒です。 これに基づいて、サイドスイッチの位置を決定するための2番目の非同期ソリューションを構築しました。 ここにあります:
#import <AudioToolbox/AudioToolbox.h> #import "MuteSwitchTet.h" ... enum MuteSwitchStates { kMuteSwitchUndefined = -1, kSoundless = 0, kSound = 1 }; @implementation MuteSwitchTest ... void MyAudioServicesSystemSoundCompletionProc (SystemSoundID ssID, void *clientData) { // "" MuteSwitchTest *self = (MuteSwitchTest*)clientData; [NSObject cancelPreviousPerformRequestsWithTarget:self]; self.muteSwitchState = kSoundless; } - (void) cancelSystemSoundCompletion { // "" AudioServicesRemoveSystemSoundCompletion(SoundID); self.muteSwitchState = kSound; } - (void) startPlayback { AudioServicesAddSystemSoundCompletion(SoundID, NULL, NULL, MyAudioServicesSystemSoundCompletionProc, self); AudioServicesPlaySystemSound(SoundID); [self performSelector:@selector(cancelSystemSoundCompletion) withObject:nil afterDelay:0.1]; } ... @end
この新しいソリューションは機能していましたが、いくつかの理由で私には向いていませんでした。 まず、非同期であり、顕著な遅延(約1/10秒)で動作しました。 遅延を減らすと、誤検知が発生しました。 第二に、副作用がありました-再生された音自体が、ユーザーを混乱させるほど大きな音でした。 その後、オーディオエディタで人為的に音量をゼロに変えました。 第三に、それはすでに汚いハックのようにあまりにも多かったが、これは、例えば、
VSSilentSwitchの作成者が
ソリューションを販売することを妨げなかったが、明らかに同じ効果に基づいている。
約1か月後、この問題に戻りました。 nmコマンドを使用してオブジェクトファイル内の文字を検索し始め、それに基づいて単純なシェルスクリプトを作成しました。そのリストは、以下の「ツール」セクションにあります。 スクリプトは、それぞれがキーワードを表す1つ、2つ、または3つのパラメーターで実行されます。
$ sh〜/ドキュメント/ LookSDKForSymbol.sh RingerSwitch
#結果の一部が省略されています
0000d738 S _kGSRingerSwitchCapability
./System/Library/PrivateFrameworks/GraphicsServices.framework/GraphicsServicesにあります
000038cc T _SBGetRingerSwitchState
0000370c T _SBGetRingerSwitchState
./System/Library/PrivateFrameworks/SpringBoardServices.framework/SpringBoardServicesにあります
SBGetRingerSwitchState
と呼ばれる
SBGetRingerSwitchState
は有望に見えました。
目的のポートを取得するために、関数が使用されました:
mach_port_t SBSSpringBoardServerPort();
同じフレームワークから。
結果は次のとおりです。
@implementation MuteSwitchTest ... - (int) switchState {
例2:
IMEI定義
IMEI(International Mobile Equipment Identity)-一意の識別
各電話機に割り当てられたコードは、電話機の一種のMACアドレスです(ただし、電話機にはMACアドレスもあります)
Erica Sadunの
uidevice-extensionプロジェクトからどのように出てきたか覚えていませんが、それを扱っているうちに、ある種のプログラマーの「金鉱」のように思えました。
カテゴリの1つであるUIDevie(IOKit_Extensions)には、IMEIを定義するための関数が含まれています。 iOS 5.1を搭載したiPhone 4とiOS 4.3を搭載したiPadでこれらの機能をテストしましたが、すべて機能し、他のタスクに移りました。 しかし、ベータテストでは、IMEIを決定する機能が新しいデバイス(iPad 2、新しいiPad、iPhone 4S)で機能しないことが判明しました。 理由を見つけるために、私はStackOverflowに行きました。そこで、私の懸念が確認されました。 検索により、CoreTelephonyと呼ばれるフレームワークに導かれました。
$ nm -g ./CoreTelephony | grep -i imei
U _kCFAbsoluteTimeIntervalSince1970
00053b28 S _kCTMobileEquipmentInfoIMEI
00053ad4 S _kCTPostponementInfoInfoIMEI
00053ac4 S _kCTPostponementStatusErrorDefaultIMEI
$ nm -g ./CoreTelephony | grep MobileEquipment
000260e4 T __CTServerConnectionCopyMobileEquipmentInfo
00053b34 S _kCTMobileEquipmentInfo1xIMSI
00053b20 S _kCTMobileEquipmentInfoCurrentMobileId
00053b24 S _kCTMobileEquipmentInfoCurrentSubscriberId
00053b40 S _kCTMobileEquipmentInfoERIVersion
00053b2c S _kCTMobileEquipmentInfoICCID
00053b28 S _kCTMobileEquipmentInfoIMEI
00053b30 S _kCTMobileEquipmentInfoIMSI
00053b38 S _kCTMobileEquipmentInfoMEID
00053b44 S _kCTMobileEquipmentInfoMIN
00053b3c S _kCTMobileEquipmentInfoPRLVersion
関数(_CTServerConnectionCopyMobileEquipmentInfo(...))は、kCTMobileEquipmentInfo *という形式のキーとそれに対応する値を持つ辞書(CFDictionaryRef)を返すと想定できます。 幸いなことに、今回は署名を復元する必要はありませんでした。 Googleで_CTServerConnectionCopyMobileEquipmentInfoを検索すると、
このページが表示され 、すぐにIMEIを決定する機能の準備が整いました。
このIMEI検出方法は、すべてのデバイスで機能します。
その後、IMEIを決定する別の方法を見つけました(lockdownd経由)。
例3:
文書化されていないアラートの使用:ボリュームボタン。
当初、「Notification」で終わる文字定数はシステムアラートの名前であり、[NSNotificationCenter defaultCenter]を使用してオブザーバーを登録するだけで使用できると単純に信じていました。
$ sh〜/ドキュメント/ LookSDKForSymbol.sh通知$ボリュームの変更
001dbe60 S _MPAVControllerVolumeDidChangeNotification
001dbe64 S _MPAVControllerVolumeMutedDidChangeNotification
001dc4f8 S _MPMusicPlayerControllerVolumeDidChangeNotification
001dc314 S _MPVolumeViewRouteButtonChangedNotification
001dc310 S _MPVolumeViewVisibilityChangedNotification
./System/Library/Frameworks/MediaPlayer.framework/MediaPlayerにあります
000d6d24 D _AVController_EffectiveVolumeDidChangeNotification
000d6d60 D _AVController_VolumeDidChangeNotification
000d6fec D _AVSystemController_CurrentRouteHasVolumeControlDidChangeNotification
000d6ffc D _AVSystemController_EffectiveVolumeDidChangeNotification
000d6fdc D _AVSystemController_SystemVolumeDidChangeNotification
./System/Library/PrivateFrameworks/Celestial.framework/Celestialにあります
...そして、他のフレームワークからさらに十数個
テストプログラムを作成した後、ボリュームキーを押したときにどのアラートが発生したかを確認し始めました。
私が編集した通知のかなり大きなリストから、これらの2つだけが来ました。
AVController_EffectiveVolumeDidChangeNotification
AVController_VolumeDidChangeNotification
これらのアラートの欠点は、
1)2つのボタンのどちらが押されたかを直接判断することはできません
2)各ボタンが押されたときと、
私は他のキーワードを探しています:
$ sh〜/ Documents / LookSDKForSymbol.shボリュームボタン
001b221c t-[UIApplication setWantsVolumeButtonEvents:]
003cce5c t _SBSetWantsVolumeButtonEvents $ shim
0054478c S __UIApplicationVolumeDownButtonDownNotification
00544 790 S __UIApplicationVolumeDownButtonUpNotification
00544784 S __UIApplicationVolumeUpButtonDownNotification
00544788 S __UIApplicationVolumeUpButtonUpNotification
./System/Library/Frameworks/UIKit.framework/UIKitにあります
...そして、さまざまなフレームワークからさらに数十個
UIKitからの4つのアラートはすぐには機能しませんでした。それらに関連するコマンドを発行する必要がありました。
[[UIApplication sharedApplication] setWantsVolumeButtonEvents: YES];
その後、対応するボタンを押すことに関する通知が来始めました。
副作用:この関数を呼び出すと、音量ボタンで音量を制御できなくなります。そのため、ボタンの操作が終了したら、呼び出す必要があります。
[[UIApplication sharedApplication] setWantsVolumeButtonEvents: NO];
例4:
文書化されていないアラートの使用:SIMステータスの追跡
実績のあるスキームに従って作業します。
$ sh〜/ドキュメント/ LookSDKForSymbol.sh notification $ SIM
...
00052560 S _kCTSIMSupportSIMInsertionNotification
00052564 S _kCTSIMSupportSIMStatusChangeNotification
...
000525bc S _kCTSIMSupportSIMTrayStatusNotification
...
./System/Library/Frameworks/CoreTelephony.framework/CoreTelephonyにあります
...
./System/Library/PrivateFrameworks/FTServices.framework/FTServicesにあります
$
最も適切なアラートは、名前の下で私に思われました:
1)kCTSIMSupportSIMInsertionNotification
2)kCTSIMSupportSIMStatusChangeNotification
3)kCTSIMSupportSIMTrayStatusNotification
最も簡単なテストプログラムでは、(1)と呼ばれるアラートはSIMカードを挿入したときにのみ発生する(名前で以前に推測できた)、(2)必要なときに正確に(挿入および削除するときに)、通知(3 )まったく来ませんでした。 その後、アラート(3)がCTTelephonyCenterと呼ばれる特別なアラートセンターに属していることを知りました。 CTTelephonyCenterの使用については、
こちらをご覧
ください 。
SIMステータスアラート:
#include "CoreTelephony.h" - (void) notificationCallback:(NSNotification)notification { ... } - (void) startUpdateSIMStatus { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notificationCallback:) name:kCTSIMSupportSIMStatusChangeNotification object:nil ]; } - (void) stopUpdateSIMStatus { [[NSNotificationCenter defaultCenter] removeObserver:self name:kCTSIMSupportSIMStatusChangeNotification object:nil]; }
1.
www.iphonedevwiki.net/index.php/AudioServices — SystemSoundID (< 30) , . , 1000 .
:
- (void) playDefaultRingTone { NSURL *defaultRingTone = [NSURL URLWithString:@"/System/Library/CoreServices/SpringBoard.app/ring.m4r"]; AVAudioPlayer *player = [[AVAudioPlayer alloc] initWithContentsOfURL:defaultRingTone error:nil]; [player play]; }
2. UIView
, UIView (superview) (subviews). ( , ) () UIWindow. ? : , UIWindow.
____
+ [UIWindow allWindowsIncludingInternalWindows: onlyVisibleWindows:]
! (UIWindow)
1)
2) - ( — [UIApplication statusBarWindow] )
3) UIAlertView ( UIAlertView).
4) .
?
, , .
, :
— UIAlertView, , ..
— -, .
— : , , , .
, . .
@interface UIStatusBarSignalStrengthItemView : UIStatusBarItemView { @private int _signalStrengthRaw; int _signalStrengthBars; BOOL _enableRSSI; BOOL _showRSSI; } -(id)_stringForRSSI; -(float)extraRightPadding; -(void)touchesEnded:(id)ended withEvent:(id)event; -(id)contentsImageForStyle:(int)style; -(BOOL)updateForNewData:(id)newData actions:(int)actions; @end
, , UIStatusBarSignalStrengthItemView RSSI ( ) , .
, . [UIView completeDescription]:
@interface UIView (RecursiveDescription) - (void) recursiveDescription; + (void) completeDescription @end @implementation UIView (RecursiveDescription) - (void) recursiveDescription { NSLog(@"______________________________________"); NSLog(@"%@", self); NSArray *subviews_ = [self subviews]; if ([subviews_ count] > 0) { for (UIView *subview_ in subviews_) { [subview_ recursiveDescription]; } } } - (void)completeDescription { NSArray *windows = [UIWindow allWindowsIncludingInternalWindows:YES onlyVisibleWindows:NO]; for (UIView *view in windows) { [view recursiveDescription]; } } @end
3. iOS
MIG (MIG-subsystem, Mach Interface Generator) — ( «Mach kernel»). MIG-subsystem Mac OS X - :
www.opensource.apple.com/source/xnu/xnu-1228.0.2/libsyscall/mach . :
www.iphonedevwiki.net/index.php/MIG_subsystem .
IORegistry, I/O registry — -; , iPhone . IORegistry (.
UIDevice-IOKitExtensions ).
ツール
nm — UNIX-, .
nm ( ) bash-, iOS SDK.
LookSDKForSymbol.sh:
c++filt — (
demangling ) . ++; objective-C .
otool — .
hexdump — :-)
class-dump-z — . . , , , , , .
Google Code — .
Hex-Rays ARM Decompiler — HEX-Rays IDA, ARM .
.— , , .
,
Wiki
www.iphonedevwiki.netwiki, jailbreak .
(iOS 3.x, iOS 4.x),
.
人
1. (Jay Freeman, saurik)
www.saurik.com2. (Erica Sadun) — «The iPhone Developer's CookBook» «The iOS 5 Developer's Cookbook: Core Concepts and Essential Recipes for iOS Programmers», . .
ericasadun.com:
github.com/erica/iOS-5-Cookbookgithub.com/erica/iphone-3.0-cookbook-github.com/erica/uidevice-extension3. KennyTM / networkpx — class-dump-z, StackOverflow.com , API
networkpx.blogspot.comcode.google.com/p/networkpxgithub.com/kennytmstackoverflow.com/users/224671/kennytmgithub.com/kennytm/iphone-private-frameworks(iOS 3).
本
«The iPhone Developer's CookBook» ( «The iOS 5 Developer's Cookbook: Core Concepts and Essential Recipes for iOS Programmers») — iOS, iOS.
:
translated.by/you/iphone-developers-cookbook-development-native-applications-for-the-iphone/into-ru/trans