1

私が言ったように、Objective-C はまったく新しいものです。私はプログラミングの経験が数年ありますが、すぐに習得できます。

一般的な問題: 別のファイル内の変数をリッスンし、その変数への変更に応じて特定のアクションを実行したい。

特定の問題: iPhone が WiFi 信号を表示する方法を変更したいと考えています。現在4州ですが、 8州にしたいと思っています。私の希望は、何らかの方法で変数をリッスン (または定期的に読み取り) してからwifiSignalStrengthRaw表示SBStatusBarDataManager.hすることです。

質問: その変数を読み取る、または聞くための最善の方法は何ですか?

編集:二次的な質問: Obj-C で既にコンパイルされたコードを分析する方法はありますか?

4

5 に答える 5

3

本当に欲しいのはKey-Value Observingです。NSNotificationcenter などでハックする必要はありません...

于 2012-07-27T21:12:48.123 に答える
2

Key Value Observing は優れた機能ですが、この特定の問題を (直接的に) 解決することはできません。彼が言及しているクラスに慣れていない人のために説明すると、これは iOS SpringBoard 自体に含まれるプライベート クラスです。そのため、関心のあるデータを公開する方法を制御することはできません。

古いデータだけを観察することはできません。Key Value Observing (KVO) に準拠するようにコーディングする必要があります。SBStatusBarDataManager.hを見ると(これは iOS 4 バージョンです... で必要なものを生成しますclass-dump) ... そのようにコーディングされていないことがわかります :(

ただし、何らかの動的な Objective-C ランタイム機能を使用して、とにかくデータを取得することができます。プライベート/保護されたインスタンス変数を直接取得する方法については、こちらを参照してください。

次に、スプ​​リングボード ヘッダーの内容に一致する構造体をローカルで宣言し、次のようにします。

// this was coded to match the iOS 5.0 header, but of course, this may
// change with each iOS version
typedef struct {
    char itemIsEnabled[23];
    char timeString[64];
    int gsmSignalStrengthRaw;
    int gsmSignalStrengthBars;
    char serviceString[100];
    char serviceCrossfadeString[100];
    char serviceImages[3][100];
    char operatorDirectory[1024];
    unsigned int serviceContentType;
    int wifiSignalStrengthRaw;
    int wifiSignalStrengthBars;
    unsigned int dataNetworkType;
    int batteryCapacity;
    unsigned int batteryState;
    char notChargingString[150];
    int bluetoothBatteryCapacity;
    int thermalColor;
    unsigned int thermalSunlightMode:1;
    unsigned int slowActivity:1;
    unsigned int syncActivity:1;
    char activityDisplayId[256];
    unsigned int bluetoothConnected:1;
    unsigned int displayRawGSMSignal:1;
    unsigned int displayRawWifiSignal:1;
} SbStatusBarDataType;

ivar を名前で取得するヘルパー:

#import <objc/runtime.h>

- (void *) instanceVariableForObject: (id)obj andKey: (NSString *)key {
    if (key != nil) {
        Ivar ivar = object_getInstanceVariable(obj, [key UTF8String], NULL);
        if (ivar) {
            return (void *)((char *)obj + ivar_getOffset(ivar));
        }
    }
    return NULL;
}

最後に、次のようにデータを取得します。

// get an instance to the data manager this way, or however you're 
//  doing it via Mobile Substrate
SBStatusBarDataManager* mgr = [SBStatusBarDataManager sharedDataManager];
SbStatusBarDataType data = *(SbStatusBarDataType*)[self instanceVariableForObject: mgr andKey: @"_data"];
int signalStrength = data.wifiSignalStrengthRaw;

次に、十分に速いと思われる間隔で、このデータを繰り返しクエリすることができます。

それ以外の場合は、SBStatusBarDataManager.hのメソッドを調べてみてください。それらのいくつかは、信号強度が変化する正確な時間に呼び出される可能性があるようです. これらのメソッドをフックすると、データが変更されたという通知をプッシュできる可能性があるため、データを常にポーリングする必要はありません。

例えば:

- (void)_dataChanged;
- (void)_updateSignalStrengthItem;
- (void)_signalStrengthChange;

WiFi 信号強度がいつ変化したかを判断しようとしている場合は、すべてフックの候補のように見えます。しかし、私はそれらの経験がなく、あなたの側で試行錯誤するでしょう. 幸運を!

二次的な質問に関するいくつかの参考文献:

クラスダンプ

Obj-C ランタイム API に関する Apple ドキュメント

于 2012-07-29T01:07:26.393 に答える
1

NSNotificationCenter を使用して、さまざまなクラスとの間で値を送受信します。Objective-C で NSNotificationCenter を介してメッセージを送受信するNSNotifications の使用例を次に示し ます。

于 2012-07-27T20:55:02.930 に答える
1

NSNotificationCenterを確認してください。これにより、変数が通知センターに投稿されると、変数にリスナーを追加できます。その後、どのクラスでもそれらの変更を「聞く」ことができます。

NotificationCenter の Apple ドキュメントの説明:

NSNotificationCenter オブジェクト (または単に通知センター) は、プログラム内で情報をブロードキャストするメカニズムを提供します。NSNotificationCenter オブジェクトは、基本的に通知ディスパッチ テーブルです。

簡単な例:

リスナーを追加する

 [[NSNotificationCenter defaultCenter] addObserver:self 
                                          selector:@selector(showMainMenu:) 
                                              name:@"loginComplete" object:nil];

loginComplete に通知を投稿する

[[NSNotificationCenter defaultCenter] postNotificationName:@"loginComplete" object:nil];

通知を聞く。

- (void)showMainMenu:(NSNotification *)note {
     NSLog(@"Received Notification - Someone seems to have logged in"); 
 }
于 2012-07-27T20:57:52.247 に答える
0

リッスンしたい変数に変更を加えているのがあなたである場合は、オブザーバー パターンを使用する必要があります。

開始するためのチュートリアルは次のとおりです: Objective-C のパターン: オブザーバー パターン

また、SOに関するその質問もご覧ください:Objective-Cでオブザーバー/オブザーバブルを実行する最も良い方法は何ですか(iphoneバージョン)

于 2012-07-27T20:53:09.950 に答える