从另一个类中调用方法?

时间:2014-12-26 13:40:27

标签: objective-c class methods

我有几个观点,一个是SettingsMenu,另一个是Game。

我已在Game中初始化了backgroundMusic。如果SettingsMenu发生了变化,我希望在settingsMenu中运行backgroundMusicStop,但是backgroundMusicStop是我的Game类的一部分。

Game.h

-(void)backgroundMusicStop;

Game.m

-(void)backgroundMusicStop {
    [backgroundMusic stop];
    backgroundMusic.currentTime = 0;
}

SettingsMenu.m

-(IBAction)musicOptionSwitch:(id)sender {
    if (backgroundMusicPlay == YES) {
        backgroundMusicPlay = NO;
        [Game backgroundMusicStop];
    }
}

我已经调查了它并且我不明白如何修复它,我知道我需要让所有类都可以访问该方法,但我对如何做到这一点感到困惑,任何帮助都会非常感谢。

2 个答案:

答案 0 :(得分:2)

问题在于这行代码:

[Game backgroundMusicStop];

在您的实现中, Game 是一个类名,您尝试在类上调用实例方法。有两种方法可以解决它:

  1. 创建新的游戏实例
  2. 制作 backgroundMusicStop 类方法
  3. 要创建游戏实例,您需要以下内容:

    Game myGame = [[Game alloc]init];
    //depending on your implementation it could be different
    

    或者,如果您选择第二个选项,则必须更改

    -(void)backgroundMusicStop;
    

    +(void)backgroundMusicStop;
    

    我还建议你找一些书/网站来更好,更深入地理解类和实例变量/方法。

答案 1 :(得分:1)

我认为你想要做的最好的架构是:

  • 创建一个Settings对象的实例并让它跟踪 您希望用户控制的每个选项的当前状态

  • 从SettingsMenu

  • 中更新这些值
  • 让您的游戏收听设置值的更改

这样做的好处是您的视图控制器只能通过更改数据模型(设置)进行通信,而不必相互了解。您的“设置”对象可以是单个应用程序,也可以是从应用程序委托中获取的普通对象。

首先创建设置数据模型:

// Settings.h
#import <Foundation/Foundation.h>

@interface Settings : NSObject

// A singleton so that the example stays simple
+ (instancetype)sharedSettings;

// YES/NO.  Add other properties as needed.
@property (nonatomic, assign) BOOL musicShouldPlay;
#define MUSIC_SHOULD_PLAY @"musicShouldPlay"

@end

// Settings.m
#import "Settings.h"

@implementation Settings

// Guarantee only one instance
+ (instancetype)sharedSettings {
    static dispatch_once_t onceToken;
    static Settings *result = nil;
    dispatch_once(&onceToken, ^{
        result = [[Settings alloc] init];
    });
    return result;
}

- (instancetype)init {
    self = [super init];
    if (self) {
        _musicShouldPlay = NO;
    }
    return self;
}

@end

进行更改的控制器:

// SettingsViewController.m
#import "SettingsViewController.h"
#import "Settings.h"

@interface SettingsViewController ()

@property (strong, nonatomic) IBOutlet UISwitch *musicSwitch;

@end

@implementation SettingsViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    // Make the display consistent with previous settings
    [self.musicSwitch setOn:[[Settings sharedSettings] musicShouldPlay]];
}

// I'm presenting this using a modal segue from a "Change settings" button on the main controller,
// so it has a "Done" button
- (IBAction)done:(id)sender {
    [ self dismissViewControllerAnimated:YES completion:nil];
}

// Switch value changes are connected to this in the storyboard
- (IBAction)changePlayState:(id)sender {
    [[Settings sharedSettings] setMusicShouldPlay:[self.musicSwitch isOn]];
}

@end

对变化做出反应的控制器:

// ViewController.m
#import "ViewController.h"
#import "Settings.h"

@implementation ViewController

// Since this is the primary controller, I'll have it listen for its lifetime.
- (void)viewDidLoad {
    [super viewDidLoad];
    [[Settings sharedSettings] addObserver:self
                                forKeyPath:MUSIC_SHOULD_PLAY
                                   options:NSKeyValueObservingOptionNew
                                   context:nil];
}

- (void)dealloc {
    [[Settings sharedSettings] removeObserver:self forKeyPath:MUSIC_SHOULD_PLAY];
}

// Here's where the KVO notifications are delivered.
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    if ([keyPath isEqualToString:MUSIC_SHOULD_PLAY]) {
        NSNumber *newValue = [change valueForKey:NSKeyValueChangeNewKey];
        if ([newValue integerValue] == 1) {
            NSLog(@"Request to turn music on");
        } else {
            NSLog(@"Request to turn music off");
        }
    }
}

@end