如何在我的应用程序委托applicationWillTerminate中访问MPVolumeView?

时间:2019-01-05 16:29:53

标签: ios objective-c mpvolumeview

编辑:看来,似乎没有任何可能的方法可以仅在终止应用程序时将设备音量设置回启动应用程序时的水平。对我来说,这可能是苹果公司的疏忽。 Apple为什么不希望我的应用成为一个优秀的露营者,让露营地像他们找到露营地一样离开,必须有一种方法,请帮忙...我试图回答这个更广泛的问题with another topic,但它已作为重复副本关闭,请去那里投票重新打开它:)

我的应用程序终止时,我想将系统音量设置回与我的应用程序启动时相同的音量(编辑:并且在应用程序进入后台时不更改其音量)。

我正在尝试使用MPVolumeView作为设置设备音量的机制。根据我的研究,这似乎是以编程方式设置设备音量的唯一方法。如果还有其他方法,请提出建议。

因此,当我启动应用程序时,我将系统卷另存为AppDelegate.m中的外部变量“ appStartVol”。

我让用户通过MPVolumeView在应用程序使用期间更改音量。

然后,我尝试将系统卷设置回AppDelegate.m文件的applicationWillTerminate中的appStartVol。 编辑:当用户从其最近使用的列表中删除应用程序时,将调用applicationWillTerminate。我一直这样做,并且将经常使用的应用程序留在最近使用的应用程序中,因此我不必滚动浏览9页的图标即可找到它们。因此,有理由在该功能中执行我要问的事情。

我使用这种方法来提高屏幕亮度,但似乎无法做到音量大。

我遇到了麻烦,因为我似乎无法访问AppDelegate.m applicationWillTerminate中的情节提要MPVolumeView,而且我似乎无法使AppDelegate.m applicationWillTerminate中的本地MPVolumeView工作。

如果我在视图控制器中使用UIApplicationWillTerminateNotification通知,由于该故事板MPVolumeView似乎也无法从该事件访问,因此在通知事件中仍然遇到相同的问题。

编辑:这是在applicationDidEnterBackground中使用代码不能满足我的需要的原因: 我希望我的用户能够以他们的音量使用音乐播放器在他们决定将另一个应用程序作为重点时,已经在我的应用程序中手动选择了。我相信这是用户自然会想到的事情。例如,如果我要使用计算器,为什么音量会改变?我也想相信,对于用户而言,自然的假设是,如果应用程序被关闭,则该音量应弹出到应用程序前的音量。使用applicationDidEnterBackground可以使应用程序在进入后台和终止时都进入应用程序前音量,这是不可接受的。

ATTEMPT 1:这是我在AppDelegate.m applicationWillTerminate中的代码:

- (void)applicationWillTerminate:(UIApplication *)application {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
NSLog(@"=== App is terminating ===");
UIScreen.mainScreen.brightness = brightnessORG;
NSLog(@"=== Screen brightness back to pre-app level of %f ===", brightnessORG);

UISlider *volumeViewSlider;
for (UIView *view in [_mpVolumeViewParentView subviews]){
    if ([view.class.description isEqualToString:@"MPVolumeSlider"]){
        volumeViewSlider = (UISlider*)view;
        volumeViewSlider.value = appStartVol;
        break;
    }
}
}

尝试1:这是我的AppDelegate.h:

#import <UIKit/UIKit.h>
#import <MediaPlayer/MediaPlayer.h>

extern CGFloat brightnessORG;
extern float appStartVol;

@interface AppDelegate : UIResponder <UIApplicationDelegate>
{
    MPVolumeView *_mpVolumeViewParentView;
}

@property (strong, nonatomic) UIWindow *window;

@property (nonatomic, retain) IBOutlet MPVolumeView *mpVolumeViewParentView;

@end

重新。尝试1:尽管此代码运行没有错误,但由于应用程序委托[_mpVolumeViewParentView子视图]中没有视图,因此它不会将卷设置回appStartVol。显然,我无法访问情节提要中的mpVolumeViewParentView。

ATTEMPT 2:让我们看看是否可以在AppDelegate.m applicationWillTerminate中添加本地MPVolumeView:

- (void)applicationWillTerminate:(UIApplication *)application {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
NSLog(@"=== App is terminating ===");
UIScreen.mainScreen.brightness = brightnessORG;
NSLog(@"=== Screen brightness back to pre-app level of %f ===", brightnessORG);

MPVolumeView *volumeView = [ [MPVolumeView alloc] init];
UISlider *volumeViewSlider;
volumeViewSlider = (UISlider*)volumeView;
volumeViewSlider.value = appStartVol;
}

重新。 ATTEMPT 2:运行,错误为“由于未捕获的异常'NSInvalidArgumentException'而终止应用程序,原因:'-[[MPVolumeView setValue:]:无法识别的选择器已发送到实例”

但是我已经尝试过:),如您所见,我是一名Objective-C新手...

任何帮助将不胜感激:)

ATTEMPT 3:在applicationWillTerminate的本地MPVolumeView中尝试子视图:

MPVolumeView *_mpVolumeViewParentView = [ [MPVolumeView alloc] init];
MPVolumeView *volumeView = [ [MPVolumeView alloc] init];
[_mpVolumeViewParentView addSubview:volumeView];
UISlider *volumeViewSlider;
for (UIView *view in [_mpVolumeViewParentView subviews]){
    if ([view.class.description isEqualToString:@"MPVolumeSlider"]){
        volumeViewSlider = (UISlider*)volumeView;
        volumeViewSlider.value = appStartVol;
        break;
    }
}

重新。 ATTEMPT 3:在for循环启动时运行时出错:“由于未捕获的异常“ NSInvalidArgumentException”而终止应用程序,原因:“-[MPVolumeView setValue:]:无法识别的选择器已发送到实例”

ATTEMPT 4:将AVfoundation框架添加到项目后,我将其添加到了AppDelegate.m:

    #import <AVFoundation/AVFoundation.h>

然后将这两行放在AppDelegate.m applicationWillTerminate中:

    AVAudioPlayer* wavplayer = [[AVAudioPlayer alloc] init];
    wavplayer.volume = appStartVol;

重新。尝试4:在'wavplayer.volume = appStartVol;'处运行时出错:'线程1:EXC_BAD_ACCESS(code = 1,address = 0x48)',该死的......

1 个答案:

答案 0 :(得分:0)

首先,您正在尝试一些可能无法工作的事情-将MPVolumeView强制转换为UISlider,然后尝试使用UISlider的{​​{1}}方法。但是您的对象仍然是setValue:并支持该方法。所以这行不通,不是因为您在错误的地方使用它,而是永远都行不通。

也-appWillTerminate是不够的,因为仅在一种特定情况下会调用它。如果应用程序先进入后台,然后又被杀死,则不会调用willTerminate。

我假设您正在尝试进行类似iOS 9: How to change volume programmatically without showing system sound bar popup?所述的操作-但您应该做同样的事情-因此,请在子视图中找到MPVolumeView,而不是将整个操作都投射到上面。

编辑:

UISlider

这是我使用的示例代码。不幸的是,使用in ter无效,所以这是我所能完成的最大工作(我也认为这是比使用终止更正确的方法,因为它并不总是被调用)。 请记住,这可以随时停止工作,甚至在提交到AppStore时会被拒绝。