2014-12-26 4 views
0

У меня есть пара взглядов, один из которых - SettingsMenu, другой - игра.Вызов метода из другого класса?

У меня есть инициализированный backgroundMusic из игры. Когда есть изменения в SettingsMenu, я бы хотел, чтобы он запускал backgroundMusicStop в settingsMenu, однако 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]; 
    } 
} 

Я посмотрел на него, и я не понимаю, как это исправить , Я знаю, что мне нужно сделать метод доступным из всех классов, но я смущен тем, как это сделать, любая помощь будет очень признательна.

+0

является 'Game' в ваш объект 'SettingsMenu.m' или это просто имя класса? – Novarg

+0

@Novarg Это просто имя класса, я не уверен, как сделать его объектом – Darin

+0

с использованием alloc и некоторой формы init - это обычный способ. – Abizern

ответ

2

Проблема заключается в этой строке кода:

[Game backgroundMusicStop]; 

В вашей реализации, Game это имя класса, и вы пытаетесь вызвать метод экземпляра на классе. Есть 2 варианта, чтобы это исправить:

  1. Создать новый экземпляр игры
  2. Сделать backgroundMusicStop метод класса

Чтобы создать игры экземпляра вам нужно будет что-то вроде:

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

Или если вы выбрать для второго варианта вам придется изменить

-(void)backgroundMusicStop; 

в

+(void)backgroundMusicStop; 

Я также хотел бы предложить вам найти книгу/сайт, чтобы понять, переменные класса и экземпляра/методы лучше и более глубокий.

+0

Большое спасибо – Darin

+0

Если я изменю его на + (void) backgroundMusicStop; что я должен изменить [Game backgroundMusicStop]; к? – Darin

+0

ничего, '+' не сделает этот метод методом класса, поэтому вы можете вызывать его без экземпляра объекта – Novarg

1

Я думаю, лучшую архитектуру для того, что вы пытаетесь сделать бы:

  • создать один экземпляр настройки объекта и его следить за текущего состояния каждого параметра вы хотите, пользователь управлять

  • обновлений этих значений из внутри меню Настройки

  • есть ваша игра прослушивать изменения значения параметров

Преимущество в том, что ваши контроллеры представлений передают только изменения в модель данных (настройки), а не знают друг о друге.Объект «Настройки» может быть либо одиночным, либо нормальным объектом, который вы получаете от своего делегата приложения.

Сначала создайте модель настройки данных:

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

Да, я использую UISwitch, так что это будет работать неплохо, не могли бы вы указать мне правильное направление в этом? Я довольно новичок в кодировании. Спасибо – Darin

+0

Я посмотрю, могу ли я добавить простой пример ответа. –

Смежные вопросы