需求描述:
APP主页右上角的图标显示音乐的播放状态(暂停或者播放), 并且这个图标带一个点击事件, 除了主页, 其他的多个页面都用到这个播放动画(Class A).
分析:
显然,这是一个app**全局**的状态, 它的应用模型是:
一个类A, 有多个对象, 每个对象都对应一个点击事件. 但是这个类却具有一个”全局”的属性,能同时应用于多个对象.
所以, 可以考虑使用通知, 但不能用单例, 因为单例的点击事件也是”全局的”,与需求不符合.
我的解决方法:
通知+类A使用static变量记住播放状态
具体实现:
(1)在A的.m文件里, 使用静态变量记住通知里最新的状态(这样, 就算是在发送通知以后, 才建立的新对象, 也能利用此静态变量, 确定app中原有的状态);
(2)在视图A.m 中的init方法, 该类的对象都会注册通知;
(3)在视图A.m 中的init方法, 如果静态变量为Yes,则开启动画, 默认不开启.
(4)在视图A.h 中, 暴露一个发送通知的接口, 每次想要改变播放状态, 都只需调用此接口. 接着在.m文件实现此接口即可.
(为什么一定要用通知呢? 直接封装成一个开启/关闭动画的方法不可以吗?——–不行!! 只有通知, 才能通知多个对象, 如果使用普通方法, 只能是一对一,无法通知多个对象. )
注意事项:
①delloc时, 必须移除通知, 且UI的更新需要回到主线程;
②postNotification最好封装成该类的一个方法, 好处:该方法会通知到所有对象哦
③静态变量, 是在栈上的, 全局的
具体代码
.h文件
#import
typedef NS_ENUM(NSInteger,JYMusicPlayerState){
JYMusicPlayerStateStop = 0, //默认
JYMusicPlayerStatePlaying = 1
};
typedef void(^JYMusicAnimationClickBlock)(void);
/**
导航栏的播放动画
*/
@interface JYMusicPlayerStateView : UIView
@property (nonatomic, copy) JYMusicAnimationClickBlock clickBlock;
/**
发送改变播放动画的状态的通知
@param state JYMusicPlayerState状态值
*/
+(void)postMusicPlayAnimationStateNotificationWithState:(JYMusicPlayerState)state;
@end
.m文件
#import "JYMusicPlayerStateView.h"
static NSString * JYMusicPlayerNavStateChnageNotification = @"JYMusicPlayerNavStateChnageNotification";
@interface JYMusicPlayerStateView()
@property (nonatomic, strong) UIImageView *imgView;
@property (nonatomic, strong) NSMutableArray *imgNameArray;
@property (nonatomic, assign) BOOL isAnimated;
@end
@implementation JYMusicPlayerStateView
static JYMusicPlayerState my_app_play_state;
- (instancetype)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if (self) {
//注册通知
//好处:多个self都会执行通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didReceiveStateChnageNotification:) name:JYMusicPlayerNavStateChnageNotification object:nil];
_imgView = [[UIImageView alloc] initWithFrame:self.bounds];
_imgView.userInteractionEnabled = YES;
[_imgView setImage:[UIImage imageNamed:@"ios_00000"]];
//动画数组
_imgView.animationImages = [self transformToImagesByNames];
_imgView.animationDuration = 1.0f;
_imgView.animationRepeatCount = 0;
[self addSubview:_imgView];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(doClick)];
[self addGestureRecognizer:tap];
//静态变量,栈上的.
if (my_app_play_state == JYMusicPlayerStatePlaying) {
[_imgView startAnimating];
}
}
return self;
}
//发送通知
+(void)postMusicPlayAnimationStateNotificationWithState:(JYMusicPlayerState)state{
[[NSNotificationCenter defaultCenter] postNotificationName:JYMusicPlayerNavStateChnageNotification object:@(state)];
}
//点击回调
-(void)doClick{
if (self.clickBlock) {
self.clickBlock();
}
}
#pragma mark -- private method
//收到通知
-(void)didReceiveStateChnageNotification:(NSNotification *)notify{
JYMusicPlayerState state = ((NSNumber *)notify.object).integerValue;
my_app_play_state = state; //使用静态变量记住
dispatch_async(dispatch_get_main_queue(), ^{
if (state == JYMusicPlayerStatePlaying) {
[_imgView startAnimating];
} else {
[_imgView stopAnimating];
}
});
// [[NSUserDefaults standardUserDefaults] setObject:@(state) forKey:@"JYMusicPlayerStateSave"];
}
//返回image数组
-(NSArray<UIImage *> *)transformToImagesByNames{
NSArray *names = @[@"ios_00000",@"ios_00001",@"ios_00002",@"ios_00003",@"ios_00004",@"ios_00005"];
NSMutableArray *imgArr = [[NSMutableArray alloc]init];
for (NSString *n in names) {
[imgArr addObject:[UIImage imageNamed:n]];
}
return imgArr;
}
-(void)dealloc{
[[NSNotificationCenter defaultCenter] removeObserver:self name:JYMusicPlayerNavStateChnageNotification object:nil];
}
@end