在Swift Project中将MPMoviePlayerController全屏按钮图标更改为iOS中的标题图标

时间:2019-01-01 19:33:30

标签: ios iphone swift mpmovieplayercontroller code-migration

我将MPMoviePlayerController用作嵌入式视频播放器,但iOS 10+的全屏图标已更改。

iOS 8、9中的原始图片

enter image description here

iOS 10以上版本中的图片

enter image description here

我之前在Objective-C项目中进行了更改。引用此StackOverflow postWorkaroundInlinePlayerFullScreenButtonBug.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中,我不确定如何实现此功能。

1 个答案:

答案 0 :(得分:2)

这个问题的解决方案有多个阶段。首先,我们需要在我们的Swift中添加一个main.m,以便可以注入原始解决方案中的代码。在Swift项目中,主文件是抽象的。请参阅此post

因此,第一步是从@UIApplicationMain类中删除AppDelegate关键字。

然后我们通过添加一个Objective-C.m文件并将其命名为main来添加一个main.m。 enter image description here

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]));
    }
}

原始图标更改代码与原始answer中的代码相同:

@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);
}