ios - 在 Swift Project 中将 MPMoviePlayerController 全屏按钮图标更改为 iOS 中的标题图标
问题描述
我使用 MPMoviePlayerController 作为嵌入式视频播放器,但 iOS 10+ 的全屏图标已更改。
iOS 8、9 中的原始图像
iOS 10+ 中的图像
我早些时候在一个 Objective-C 项目中进行了更改。参考这个 StackOverflow帖子。WorkaroundInlinePlayerFullScreenButtonBug.m
@import MediaPlayer;
@import ObjectiveC;
static void (*configureAuxiliaryButtonsIMP)(id, SEL, BOOL);
static void ConfigureAuxiliaryButtons(id self, SEL _cmd, BOOL flag)
{
configureAuxiliaryButtonsIMP(self, _cmd, flag);
@try
{
id delegate = [self delegate]; // Either nil or MPInlineVideoController (responds to `isFullscreen`) or MPInlineVideoFullscreenViewController (does not respond to `isFullscreen`)
BOOL isFullscreen = [delegate respondsToSelector:@selector(isFullscreen)] ? [delegate isFullscreen] : YES;
NSString *imageName = [@[ @"Video", @"Player", @"_", isFullscreen ? @"Exit" : @"Enter", @"Fullscreen" ] componentsJoinedByString:@""];
SEL imageNamedForControlState = NSSelectorFromString([@[ @"_", @"image", @"Named", @":", @"for", @"Control", @"State", @":" ] componentsJoinedByString:@""]);
UIImage *normalImage = ((UIImage *(*)(id, SEL, NSString *, UIControlState))objc_msgSend)(self, imageNamedForControlState, imageName, UIControlStateNormal);
UIImage *highlightedImage = ((UIImage *(*)(id, SEL, NSString *, UIControlState))objc_msgSend)(self, imageNamedForControlState, imageName, UIControlStateHighlighted);
UIButton *fullscreenButton = [self valueForKey:[@[ @"fullscreen", @"Button" ] componentsJoinedByString:@""]];
[fullscreenButton setImage:normalImage forState:UIControlStateNormal];
[fullscreenButton setImage:highlightedImage forState:UIControlStateHighlighted];
}
@catch (NSException *exception)
{
NSLog(@"Failed to workaround inline player fullscreen button bug: %@", exception);
}
}
void WorkaroundInlinePlayerFullScreenButtonBug(void)
{
if (![NSProcessInfo.processInfo isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){10, 0, 0}])
return;
Class MPVideoPlaybackOverlayView = NSClassFromString([@[ @"M", @"P", @"Video", @"Playback", @"Overlay", @"View" ] componentsJoinedByString:@""]);
SEL configureAuxiliaryButtonsSEL = NSSelectorFromString([@[ @"_", @"configure", @"Auxiliary", @"Buttons", @":" ] componentsJoinedByString:@""]);
NSMethodSignature *methodSignature = [MPVideoPlaybackOverlayView instanceMethodSignatureForSelector:configureAuxiliaryButtonsSEL];
if (methodSignature.numberOfArguments != 3)
{
NSLog(@"Failed to workaround inline player fullscreen button bug (method not found)");
return;
}
const char *returnType = methodSignature.methodReturnType;
const char *argType = [methodSignature getArgumentTypeAtIndex:2];
if (strcmp(returnType, @encode(void)) != 0 || strcmp(argType, @encode(BOOL)) != 0)
{
NSLog(@"Failed to workaround inline player fullscreen button bug (type mismatch)");
return;
}
Method configureAuxiliaryButtons = class_getInstanceMethod(MPVideoPlaybackOverlayView, configureAuxiliaryButtonsSEL);
configureAuxiliaryButtonsIMP = (__typeof__(configureAuxiliaryButtonsIMP))method_getImplementation(configureAuxiliaryButtons);
method_setImplementation(configureAuxiliaryButtons, (IMP)ConfigureAuxiliaryButtons);
}
然后从main.m
函数中调用它
#import "AppDelegate.h"
extern void WorkaroundInlinePlayerFullScreenButtonBug(void);
int main(int argc, char *argv[])
{
@autoreleasepool
{
WorkaroundInlinePlayerFullScreenButtonBug();
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
上述解决方案运行良好,但在 Swift 中,我不确定如何实现此功能。
解决方案
这个问题的解决方案有多个阶段。首先,我们需要在我们的 Swift 中添加一个 main.m,以便可以注入原始解决方案中的代码。在 Swift 项目中,主文件是抽象的。参考这篇文章。
所以第一步是从类中删除@UIApplicationMain
关键字。AppDelegate
然后我们通过添加一个 Objective-Cm 文件并将其命名为 .m 来添加一个main
main.m。
main.m
在文件中添加如下代码
#import <UIKit/UIKit.h>
#import "MoviePlayerDemo-Swift.h"
extern void WorkaroundInlinePlayerFullScreenButtonBug(void);
int main(int argc, char *argv[])
{
@autoreleasepool
{
WorkaroundInlinePlayerFullScreenButtonBug();
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
原始图标更改代码与原始答案相同:
@import MediaPlayer;
@import ObjectiveC;
static void (*configureAuxiliaryButtonsIMP)(id, SEL, BOOL);
static void ConfigureAuxiliaryButtons(id self, SEL _cmd, BOOL flag)
{
configureAuxiliaryButtonsIMP(self, _cmd, flag);
@try
{
id delegate = [self delegate]; // Either nil or MPInlineVideoController (responds to `isFullscreen`) or MPInlineVideoFullscreenViewController (does not respond to `isFullscreen`)
BOOL isFullscreen = [delegate respondsToSelector:@selector(isFullscreen)] ? [delegate isFullscreen] : YES;
NSString *imageName = [@[ @"Video", @"Player", @"_", isFullscreen ? @"Exit" : @"Enter", @"Fullscreen" ] componentsJoinedByString:@""];
SEL imageNamedForControlState = NSSelectorFromString([@[ @"_", @"image", @"Named", @":", @"for", @"Control", @"State", @":" ] componentsJoinedByString:@""]);
UIImage *normalImage = ((UIImage *(*)(id, SEL, NSString *, UIControlState))objc_msgSend)(self, imageNamedForControlState, imageName, UIControlStateNormal);
UIImage *highlightedImage = ((UIImage *(*)(id, SEL, NSString *, UIControlState))objc_msgSend)(self, imageNamedForControlState, imageName, UIControlStateHighlighted);
UIButton *fullscreenButton = [self valueForKey:[@[ @"fullscreen", @"Button" ] componentsJoinedByString:@""]];
[fullscreenButton setImage:normalImage forState:UIControlStateNormal];
[fullscreenButton setImage:highlightedImage forState:UIControlStateHighlighted];
}
@catch (NSException *exception)
{
NSLog(@"Failed to workaround inline player fullscreen button bug: %@", exception);
}
}
void WorkaroundInlinePlayerFullScreenButtonBug(void)
{
if (![NSProcessInfo.processInfo isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){10, 0, 0}])
return;
Class MPVideoPlaybackOverlayView = NSClassFromString([@[ @"M", @"P", @"Video", @"Playback", @"Overlay", @"View" ] componentsJoinedByString:@""]);
SEL configureAuxiliaryButtonsSEL = NSSelectorFromString([@[ @"_", @"configure", @"Auxiliary", @"Buttons", @":" ] componentsJoinedByString:@""]);
NSMethodSignature *methodSignature = [MPVideoPlaybackOverlayView instanceMethodSignatureForSelector:configureAuxiliaryButtonsSEL];
if (methodSignature.numberOfArguments != 3)
{
NSLog(@"Failed to workaround inline player fullscreen button bug (method not found)");
return;
}
const char *returnType = methodSignature.methodReturnType;
const char *argType = [methodSignature getArgumentTypeAtIndex:2];
if (strcmp(returnType, @encode(void)) != 0 || strcmp(argType, @encode(BOOL)) != 0)
{
NSLog(@"Failed to workaround inline player fullscreen button bug (type mismatch)");
return;
}
Method configureAuxiliaryButtons = class_getInstanceMethod(MPVideoPlaybackOverlayView, configureAuxiliaryButtonsSEL);
configureAuxiliaryButtonsIMP = (__typeof__(configureAuxiliaryButtonsIMP))method_getImplementation(configureAuxiliaryButtons);
method_setImplementation(configureAuxiliaryButtons, (IMP)ConfigureAuxiliaryButtons);
}
推荐阅读
- spring-cloud-dataflow - Spring Cloud 数据流 AWS S3 存储桶
- javascript - 如果属性匹配字符串,JSX 过滤数组中的项目,否则显示所有项目
- laravel - Laravel Livewire 将文件上传到 AWS S3 存储桶
- javascript - 单击标题时jQuery上下滑动ul
- javascript - HTML 向 PHP 后端发送消息并检查响应
- spring-boot - 如何在 graphql-spqr-spring-boot-starter 中禁用模式自省
- core-data - 使用公共 CloudKit 数据库 (NSPersistentCloudkitContainer) - macOS
- android - 是否有用于在 Android 上添加语言的 ADB 命令?
- javascript - 使用 TypeScript 和 Axios 进行 http 调用时如何选择响应正文中的某些字段
- php - Codeigniter URL 中的双斜杠问题