WKWebView単位でミュートをかける
以前 SafariのようにWKWebView単位でミュートをかける on Qiitaで紹介した方法の最新版です。
ややこしいことはしなくて良くなった
前回はシンボルから関数へのアドレスを検索してなど、かなりややこしいことをしていました。
しかし、(おそらく)High Sierraから-[WKWebView _setPageMute:]
メソッドが取り込まれたので、カテゴリを作ってこのメソッドを呼ぶだけでミュートができるようになりました
でも、やっぱり、ちょっと問題ありです…
setterはあるのにgetterがない。つまり今どうなっているかという状態は自分で記録しておく必要があります。
使用例(実装編)
ご自分で実装するならこんな感じになります。
@interface WKWebView (WATASHINO_WKWebView_Extension)
@property (getter=isMuted) BOOL muted;
@end
typedef NS_OPTIONS(NSInteger, _WKMediaMutedState) {
_WKMediaNoneMuted = 0,
_WKMediaAudioMuted = 1 << 0,
_WKMediaCaptureDevicesMuted = 1 << 1,
};
@interface WKWebView (Private_na_API)
- (void)_setPageMuted:(_WKMediaMutedState)mutedState;
@end
@implementation WKWebView (WATASHINO_WKWebView_Extension)
// プロパティ用。_WKMediaMutedStateは隠されている。
- (BOOL)isMuted {
return self.mute != _WKMediaNoneMuted;
}
- (void)setMuted:(BOOL)isMuted {
self.mute = isMuted ? _WKMediaAudioMuted : _WKMediaNoneMuted;
}
// 実際の実装部分
- (void)setMute:(_WKMediaMutedState)mute {
objc_setAssociatedObject(self, mutekey, [NSNumber numberWithInteger:mute], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
[self _setPageMuted:mute];
}
- (_WKMediaMutedState)mute {
NSNumber *muteVal = objc_getAssociatedObject(self, mutekey);
return muteVal.integerValue;
}
@end
associatedObject
を使用して現在の状態を記録しています。
使用例(ぼくのやつ)
こちらは以前の実装と上に書いた実装をframeworkがロードされるときに切り替えるようにして、10.13以前でも使用可能にしています。
ダミークラス(MethodSwizzler)を用意して+[MethodSwizzler load]
が呼ばれたときに-[WKWebView _setPageMute:]
メソッドが使えるならば、新しい実装に Method Swizzlingするようになってます。
若干ややこしいです。