【问题标题】:Calling method from within another class?从另一个类中调用方法?
【发布时间】:2015-02-23 19:31:52
【问题描述】:

我有几个视图,一个是 SettingsMenu 另一个是 Game 。

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

游戏.h

-(void)backgroundMusicStop;

游戏.m

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

SettingsMenu.m

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

我已经研究过了,但我不明白如何解决它,我知道我需要让所有类都可以访问该方法,但我对如何做到这一点感到困惑,任何帮助将不胜感激。

【问题讨论】:

  • Game 在你的SettingsMenu.m 一个对象还是只是一个类名?
  • @Novarg 这只是一个类名,我不知道如何使它成为一个对象
  • 使用 alloc 和某种形式的 init 是通常的方式。
  • @Abizern 你能给我指出一篇文章告诉我如何做到这一点吗?或者可以根据我的项目来解释一下?

标签: objective-c class methods


【解决方案1】:

问题出在这行代码中:

[Game backgroundMusicStop];

在您的实现中,Game 是一个类名,您尝试调用一个类的实例方法。有 2 个选项可以修复它:

  1. 创建一个新的游戏实例
  2. backgroundMusicStop设为类方法

要创建一个 Game 实例,您需要以下内容:

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

或者如果你选择第二个选项,你将不得不改变

-(void)backgroundMusicStop;

+(void)backgroundMusicStop;

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

【讨论】:

  • 如果我把它改成 +(void)backgroundMusicStop;我必须改变什么[游戏背景音乐停止];到?
  • 没什么,+ 会让这个方法成为类方法,所以你可以在没有对象实例的情况下调用它
  • 但是,朝这个方向前进会给您带来backgroundMusic 的问题,它似乎是一个实例变量。
【解决方案2】:

我认为最适合您尝试的架构是:

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

  • 从 SettingsMenu 中更新这些值

  • 让您的游戏监听设置值的更改

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

首先创建设置数据模型:

// 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

【讨论】:

  • 是的,我正在使用 UISwitch,所以它可以很好地工作,你能否指出我这样做的正确方向?我对编码很陌生。谢谢
  • 我会看看我是否可以在答案中添加一个简单的例子。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-02-07
  • 1970-01-01
  • 2011-09-09
  • 1970-01-01
相关资源
最近更新 更多