Activatorの場合、通常ですとSpringBoard内で呼び出せるメソッドを実行するようになっていますが、それを別の場所でも実行できるようにする方法を紹介します。
##Sample
https://github.com/ichitaso/UIRotation9
- (void)activator:(LAActivator *)activator receiveEvent:(LAEvent *)event
ここがActivatorのジェスチャーを実行した時に呼び出される部分です。
[(UIDevice *)[objc_getClass("UIDevice") currentDevice] setOrientationByUIRotaion];
CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), CFSTR("com.ichitaso.uirotation-changed"), NULL, NULL, true);
objc_getClassメソッドで呼ぶことも出来ますが、一回では回転しなかったので「CFNotificationCenterPostNotification」の通知を使って呼び出しています。
「CFNotificationCenterPostNotification」の通知は、他の部分でも有用なコードなので後日また別の利用方法を紹介します。
##別のdylibを作ってそちら側で処理をする
UIRotationHelper.xm
こちらの方はフィルターのplistが
{ Filter = { Bundles = ( "com.apple.UIKit" ); }; }
となっているので、UIKitで動作しているもの全てをhookできます。
@interface UIDevice (UIRotation)
+ (id)currentDevice;
- (void)setOrientation:(int)arg1 animated:(char)arg2;
- (void)setOrientationByUIRotaion;
@end
UIDevice.hに新しく「- (void)setOrientationByUIRotaion;」というものを作っています。
%new
- (void)setOrientationByUIRotaion
{
LoadSettings();
[self setOrientation:setRotate animated:YES];
}
LoadSettings();でplistに保存されたint値の「setRotate」の方向に回転するように命令します。
それを呼び出すのが先ほどのCFNotification
// Call method from Activator
static void setUIRotaionChanged(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo)
{
[(UIDevice *)[objc_getClass("UIDevice") currentDevice] setOrientationByUIRotaion];
}
##通知の受け取り
これだけでは実行しないので、%ctorの部分に通知の受け取りを記述しておきます。
// Activator Notification
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(),NULL,setUIRotaionChanged,CFSTR("com.ichitaso.uirotation-changed"),NULL,CFNotificationSuspensionBehaviorCoalesce);
これで「com.ichitaso.uirotation-changed」という通知を受け取った時に「static void setUIRotaionChanged」のメソッドが実行されます。
つまり、Activatorのdylib側で通知を出して、UIRotationHelperでその処理を行うので、SpringBoard外でもActivatorの処理を実行できるようになったわけですね。
##実際の回転処理
%hook UIDevice
- (void)setOrientation:(int)arg1 animated:(char)arg2
{
LoadSettings();
if (setRotate == 2) {
%orig(2,YES);
} else if (setRotate == 3) {
%orig(3,YES);
} else if (setRotate == 4) {
%orig(4,YES);
} else {
%orig();
}
}
%end
UIDevice.hをhookして
- (void)setOrientation:(int)arg1 animated:(char)arg2
ここのint値のarg1で回転させています。
次回は明日ストック2記事を書く予定なので、他の方で残りの部分を埋めていただけるとありがたいです。
それでは。