Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/macos/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 无关对象之间的通信 背景_Objective C_Macos_Sprite Kit_Event Handling_Delegation - Fatal编程技术网

Objective c 无关对象之间的通信 背景

Objective c 无关对象之间的通信 背景,objective-c,macos,sprite-kit,event-handling,delegation,Objective C,Macos,Sprite Kit,Event Handling,Delegation,我正在Mac OS上使用SpriteKit为MIDI打鼓创建一个节奏应用程序注意对象是下面绿色和蓝色的对象。注释在屏幕上从右向左移动。当音符越来越接近红色的“播放栏”时,我想在播放栏旁边创建一个音符的轮廓,以向用户表明音符越来越接近播放栏,是时候很快播放了 问题 我需要每个Note对象在与播放头保持一定距离时通知另一个名为Sequencer的类,以便它可以为最近的音符启动音符轮廓动画。音符知道它们离演奏头有多远,所以这不是问题授权是否会成为这种情况的候选?我曾试图理解授权的目的,但我始终不知道

我正在Mac OS上使用SpriteKit为MIDI打鼓创建一个节奏应用程序<代码>注意对象是下面绿色和蓝色的对象。注释在屏幕上从右向左移动。当音符越来越接近红色的“播放栏”时,我想在播放栏旁边创建一个音符的轮廓,以向用户表明音符越来越接近播放栏,是时候很快播放了

问题 我需要每个
Note
对象在与播放头保持一定距离时通知另一个名为
Sequencer
的类,以便它可以为最近的音符启动音符轮廓动画。音符知道它们离演奏头有多远,所以这不是问题授权是否会成为这种情况的候选?我曾试图理解授权的目的,但我始终不知道如何在我特定的游戏相关情况下实施授权

编辑:添加代码

游戏场景.m

@implementation GameScene

- (void)didMoveToView:(SKView *)view {
    ...
    [self initSequence];
    [self initNoteProcessor];
    [self initPlayBar];
    ...
}

...

//keeps track of a collection of notes and vertical line measure markers and
//responsible for drawing them in scene and moving them left
-(void) initSequence {
    _sequence = [[Sequencer alloc] initWithWidth:1150];
    [_sequence setPosition:CGPointMake(130, 0)];
    [self addChild:_sequence];
}
...

//responsible for handling incoming MIDI input from a keyboard and checking to see
//if notes are played on time, early or late
-(void) initNoteProcessor {
    _noteProcessor = [[NoteProcessor alloc] initWithSequence:_sequence];
}
...
//creates a vertical line that indicates when notes need to be played
-(void) initPlayBar {
    _playBar = (SKSpriteNode*)[self childNodeWithName:@"playBar"];
    _playBar.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:_playBar.frame.size];
    _playBar.physicsBody.affectedByGravity = NO;
    [_playBar.physicsBody setDynamic:YES];
    [_playBar.physicsBody setAllowsRotation:NO];
    [_playBar.physicsBody setCategoryBitMask:kPlayBarCategory];
    [_playBar.physicsBody setCollisionBitMask:kNoCategory];
    [_playBar.physicsBody setContactTestBitMask:kNoteCategory | kLineCategory];
    [[NSUserDefaults standardUserDefaults] setDouble:_playBar.position.x forKey:@"playBarXPosition"];
}
@implementation NoteProcessor

-(instancetype) initWithSequence:(Sequencer*)sequence {
    if (self = [super init]) {
        _sequence = sequence;
        _noteActiveIndex = 0;
        [self initActiveNoteIndices];
        [self initNoteIndicator];

        //when user plays key on keyboard, notify this class
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(midiPlayed:) name:@"MidiPlayedNotificationKey" object:nil];

    }
    return self;
}

//keeps track of the next note of each pitch that is incoming
-(void) initActiveNoteIndices {
    _activeNoteIndicesByPitch = [NSMutableArray array];
    for (int i = 0; i < kTotalKeys; i++) {
        [_activeNoteIndicesByPitch addObject:[NSNumber numberWithInteger:0]];
    }
}

//checks position of note and decides whether they are on time, early or late
-(void) updateCurrentNoteStatus {
    ...
}

//handles notifications from MIDI keyboard when user plays a key
-(void) midiPlayed:(NSNotification*)notification {
     //stuff happens here
}


@end
@implementation Sequencer

-(instancetype) initWithWidth:(double)width {
    if (self = [super init]) {
        ...

        [self drawNotes];
    }
    return self;
}

//draws all of the notes on screen
-(void) drawNotes {
    NSMutableArray *parsedNotes = [_midiParser getNoteData];
    float distancePerBeat = [self getGridArea] / [self getMeasuresDisplayed] / 4;
    float xPos = 0;

    for (int i = 0; i < [parsedNotes count]; i++) {
        NSArray *currNote = [parsedNotes objectAtIndex:i];
        double location = [[currNote objectAtIndex:0] doubleValue];
        double duration = [[currNote objectAtIndex:1] doubleValue];
        int midiValue = [[currNote objectAtIndex:2] intValue];

        Note *note = [[Note alloc] initWithLocation:location Duration:duration MidiValue:midiValue];
        xPos = distancePerBeat * (location - 1);
        float yPos = kNoteHeight[note.midiValue - 36];
        [note setPosition:CGPointMake(xPos, yPos)];
        [note setZPosition:kNoteZPosition];

        NSMutableArray *noteList = [_notes objectAtIndex:midiValue-36];
        [noteList addObject:note];
        [self addChild:note];
    }
}

//this method is called 60 times per second
//each call moves 1/60th of the distance it would move in 1/60th of a second
-(void) moveLeftAfterElapsedTime:(double)elapsedTime {
    double timePerBeat = 60 / [self getBpm];
    double timePerMeasure = timePerBeat * 4;

    double lengthPerMeasure = [self getGridArea] / [self getMeasuresDisplayed];
    double distancePerFrame = lengthPerMeasure / (timePerMeasure * 60);

    double x = elapsedTime * distancePerFrame * 60;

    [self moveAllNotesLeftByDistance:x];
}

//actually does all of the moving of the notes
-(void) moveAllNotesLeftByDistance:(double)distance {
    for (int i = 0; i < [_notes count]; i++) {
        NSMutableArray *noteList = [_notes objectAtIndex:i];
        for (int j = 0; j < [noteList count]; j++) {
            Note *note = [noteList objectAtIndex:j];
            double xPos = note.position.x - distance;
            double y = note.position.y;

            [note setPosition:CGPointMake(xPos, y)];
        }
    }
}


NoteProcessor.m

@implementation GameScene

- (void)didMoveToView:(SKView *)view {
    ...
    [self initSequence];
    [self initNoteProcessor];
    [self initPlayBar];
    ...
}

...

//keeps track of a collection of notes and vertical line measure markers and
//responsible for drawing them in scene and moving them left
-(void) initSequence {
    _sequence = [[Sequencer alloc] initWithWidth:1150];
    [_sequence setPosition:CGPointMake(130, 0)];
    [self addChild:_sequence];
}
...

//responsible for handling incoming MIDI input from a keyboard and checking to see
//if notes are played on time, early or late
-(void) initNoteProcessor {
    _noteProcessor = [[NoteProcessor alloc] initWithSequence:_sequence];
}
...
//creates a vertical line that indicates when notes need to be played
-(void) initPlayBar {
    _playBar = (SKSpriteNode*)[self childNodeWithName:@"playBar"];
    _playBar.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:_playBar.frame.size];
    _playBar.physicsBody.affectedByGravity = NO;
    [_playBar.physicsBody setDynamic:YES];
    [_playBar.physicsBody setAllowsRotation:NO];
    [_playBar.physicsBody setCategoryBitMask:kPlayBarCategory];
    [_playBar.physicsBody setCollisionBitMask:kNoCategory];
    [_playBar.physicsBody setContactTestBitMask:kNoteCategory | kLineCategory];
    [[NSUserDefaults standardUserDefaults] setDouble:_playBar.position.x forKey:@"playBarXPosition"];
}
@implementation NoteProcessor

-(instancetype) initWithSequence:(Sequencer*)sequence {
    if (self = [super init]) {
        _sequence = sequence;
        _noteActiveIndex = 0;
        [self initActiveNoteIndices];
        [self initNoteIndicator];

        //when user plays key on keyboard, notify this class
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(midiPlayed:) name:@"MidiPlayedNotificationKey" object:nil];

    }
    return self;
}

//keeps track of the next note of each pitch that is incoming
-(void) initActiveNoteIndices {
    _activeNoteIndicesByPitch = [NSMutableArray array];
    for (int i = 0; i < kTotalKeys; i++) {
        [_activeNoteIndicesByPitch addObject:[NSNumber numberWithInteger:0]];
    }
}

//checks position of note and decides whether they are on time, early or late
-(void) updateCurrentNoteStatus {
    ...
}

//handles notifications from MIDI keyboard when user plays a key
-(void) midiPlayed:(NSNotification*)notification {
     //stuff happens here
}


@end
@implementation Sequencer

-(instancetype) initWithWidth:(double)width {
    if (self = [super init]) {
        ...

        [self drawNotes];
    }
    return self;
}

//draws all of the notes on screen
-(void) drawNotes {
    NSMutableArray *parsedNotes = [_midiParser getNoteData];
    float distancePerBeat = [self getGridArea] / [self getMeasuresDisplayed] / 4;
    float xPos = 0;

    for (int i = 0; i < [parsedNotes count]; i++) {
        NSArray *currNote = [parsedNotes objectAtIndex:i];
        double location = [[currNote objectAtIndex:0] doubleValue];
        double duration = [[currNote objectAtIndex:1] doubleValue];
        int midiValue = [[currNote objectAtIndex:2] intValue];

        Note *note = [[Note alloc] initWithLocation:location Duration:duration MidiValue:midiValue];
        xPos = distancePerBeat * (location - 1);
        float yPos = kNoteHeight[note.midiValue - 36];
        [note setPosition:CGPointMake(xPos, yPos)];
        [note setZPosition:kNoteZPosition];

        NSMutableArray *noteList = [_notes objectAtIndex:midiValue-36];
        [noteList addObject:note];
        [self addChild:note];
    }
}

//this method is called 60 times per second
//each call moves 1/60th of the distance it would move in 1/60th of a second
-(void) moveLeftAfterElapsedTime:(double)elapsedTime {
    double timePerBeat = 60 / [self getBpm];
    double timePerMeasure = timePerBeat * 4;

    double lengthPerMeasure = [self getGridArea] / [self getMeasuresDisplayed];
    double distancePerFrame = lengthPerMeasure / (timePerMeasure * 60);

    double x = elapsedTime * distancePerFrame * 60;

    [self moveAllNotesLeftByDistance:x];
}

//actually does all of the moving of the notes
-(void) moveAllNotesLeftByDistance:(double)distance {
    for (int i = 0; i < [_notes count]; i++) {
        NSMutableArray *noteList = [_notes objectAtIndex:i];
        for (int j = 0; j < [noteList count]; j++) {
            Note *note = [noteList objectAtIndex:j];
            double xPos = note.position.x - distance;
            double y = note.position.y;

            [note setPosition:CGPointMake(xPos, y)];
        }
    }
}
@implementation-NoteProcessor
-(instancetype)initWithSequence:(Sequencer*)序列{
if(self=[super init]){
_顺序=顺序;
_noteActiveIndex=0;
[自初始化索引];
[自启动指示器];
//当用户播放键盘上的键时,通知该类
[[NSNotificationCenter defaultCenter]添加观察者:自选择器:@选择器(midiPlayed:)名称:@“MidiPlayedNotificationKey”对象:nil];
}
回归自我;
}
//跟踪每个音高的下一个音符
-(void)initActiveNoteIndex{
_ActiveNoteIndicatesByPitch=[NSMutableArray];
对于(int i=0;i


Sequencer.m

@implementation GameScene

- (void)didMoveToView:(SKView *)view {
    ...
    [self initSequence];
    [self initNoteProcessor];
    [self initPlayBar];
    ...
}

...

//keeps track of a collection of notes and vertical line measure markers and
//responsible for drawing them in scene and moving them left
-(void) initSequence {
    _sequence = [[Sequencer alloc] initWithWidth:1150];
    [_sequence setPosition:CGPointMake(130, 0)];
    [self addChild:_sequence];
}
...

//responsible for handling incoming MIDI input from a keyboard and checking to see
//if notes are played on time, early or late
-(void) initNoteProcessor {
    _noteProcessor = [[NoteProcessor alloc] initWithSequence:_sequence];
}
...
//creates a vertical line that indicates when notes need to be played
-(void) initPlayBar {
    _playBar = (SKSpriteNode*)[self childNodeWithName:@"playBar"];
    _playBar.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:_playBar.frame.size];
    _playBar.physicsBody.affectedByGravity = NO;
    [_playBar.physicsBody setDynamic:YES];
    [_playBar.physicsBody setAllowsRotation:NO];
    [_playBar.physicsBody setCategoryBitMask:kPlayBarCategory];
    [_playBar.physicsBody setCollisionBitMask:kNoCategory];
    [_playBar.physicsBody setContactTestBitMask:kNoteCategory | kLineCategory];
    [[NSUserDefaults standardUserDefaults] setDouble:_playBar.position.x forKey:@"playBarXPosition"];
}
@implementation NoteProcessor

-(instancetype) initWithSequence:(Sequencer*)sequence {
    if (self = [super init]) {
        _sequence = sequence;
        _noteActiveIndex = 0;
        [self initActiveNoteIndices];
        [self initNoteIndicator];

        //when user plays key on keyboard, notify this class
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(midiPlayed:) name:@"MidiPlayedNotificationKey" object:nil];

    }
    return self;
}

//keeps track of the next note of each pitch that is incoming
-(void) initActiveNoteIndices {
    _activeNoteIndicesByPitch = [NSMutableArray array];
    for (int i = 0; i < kTotalKeys; i++) {
        [_activeNoteIndicesByPitch addObject:[NSNumber numberWithInteger:0]];
    }
}

//checks position of note and decides whether they are on time, early or late
-(void) updateCurrentNoteStatus {
    ...
}

//handles notifications from MIDI keyboard when user plays a key
-(void) midiPlayed:(NSNotification*)notification {
     //stuff happens here
}


@end
@implementation Sequencer

-(instancetype) initWithWidth:(double)width {
    if (self = [super init]) {
        ...

        [self drawNotes];
    }
    return self;
}

//draws all of the notes on screen
-(void) drawNotes {
    NSMutableArray *parsedNotes = [_midiParser getNoteData];
    float distancePerBeat = [self getGridArea] / [self getMeasuresDisplayed] / 4;
    float xPos = 0;

    for (int i = 0; i < [parsedNotes count]; i++) {
        NSArray *currNote = [parsedNotes objectAtIndex:i];
        double location = [[currNote objectAtIndex:0] doubleValue];
        double duration = [[currNote objectAtIndex:1] doubleValue];
        int midiValue = [[currNote objectAtIndex:2] intValue];

        Note *note = [[Note alloc] initWithLocation:location Duration:duration MidiValue:midiValue];
        xPos = distancePerBeat * (location - 1);
        float yPos = kNoteHeight[note.midiValue - 36];
        [note setPosition:CGPointMake(xPos, yPos)];
        [note setZPosition:kNoteZPosition];

        NSMutableArray *noteList = [_notes objectAtIndex:midiValue-36];
        [noteList addObject:note];
        [self addChild:note];
    }
}

//this method is called 60 times per second
//each call moves 1/60th of the distance it would move in 1/60th of a second
-(void) moveLeftAfterElapsedTime:(double)elapsedTime {
    double timePerBeat = 60 / [self getBpm];
    double timePerMeasure = timePerBeat * 4;

    double lengthPerMeasure = [self getGridArea] / [self getMeasuresDisplayed];
    double distancePerFrame = lengthPerMeasure / (timePerMeasure * 60);

    double x = elapsedTime * distancePerFrame * 60;

    [self moveAllNotesLeftByDistance:x];
}

//actually does all of the moving of the notes
-(void) moveAllNotesLeftByDistance:(double)distance {
    for (int i = 0; i < [_notes count]; i++) {
        NSMutableArray *noteList = [_notes objectAtIndex:i];
        for (int j = 0; j < [noteList count]; j++) {
            Note *note = [noteList objectAtIndex:j];
            double xPos = note.position.x - distance;
            double y = note.position.y;

            [note setPosition:CGPointMake(xPos, y)];
        }
    }
}
@实现序列器
-(instancetype)initWithWidth:(双)宽度{
if(self=[super init]){
...
[自动提款];
}
回归自我;
}
//在屏幕上绘制所有注释
-(作废)汇票{
NSMutableArray*parsedNotes=[\u midiParser getNoteData];
float distance perbeat=[self-getGridArea]/[self-getMeasuresDisplayed]/4;
浮点xPos=0;
for(int i=0;i<[parsedNotes count];i++){
NSArray*currenote=[parsedNotes objectAtIndex:i];
双位置=[[currNote objectAtIndex:0]doubleValue];
double duration=[[currNote objectAtIndex:1]doubleValue];
int midiValue=[[currNote objectAtIndex:2]intValue];
Note*Note=[[Note alloc]initWithLocation:location持续时间:持续时间MidiValue:MidiValue];
xPos=距离每拍*(位置-1);
float yPos=节点高度[note.midiValue-36];
[注:设置位置:CGPointMake(xPos、YPO)];
[注:设置位置:节点位置];
NSMutableArray*noteList=[\u notes objectAtIndex:midiValue-36];
[注释列表添加对象:注释];
[自我添加儿童:注];
}
}
//此方法每秒调用60次
//每一次呼叫移动的距离是其在1/60秒内移动距离的1/60
-(无效)在elapsedTime之后向左移动:(双精度)elapsedTime{
双时差=60/[self-getBpm];
双时差测量=每拍时间*4;
双长度Permeasure=[self-getGridArea]/[self-getMeasuresDisplayed];
双距离perframe=长度permeasure/(时间permeasure*60);
双x=延迟时间*距离性能帧*60;
[自动移动所有NotesLeftByDistance:x];
}
//实际上所有音符的移动
-(无效)移动所有NotesLeftByDistance:(双)距离{
对于(int i=0;i<[u注释计数];i++){
NSMUTABLEARRY*noteList=[\u notes objectAtIndex:i];
对于(int j=0;j<[记事本计数];j++){
注*注=[noteList objectAtIndex:j];
double xPos=note.position.x-距离;
双y=注释位置y;
[注:设置位置:CGPointMake(xPos,y)];
}
}
}

我不会像这个词所暗示的那样使用授权,而是让别人为你做些事情。在这种情况下,注释不需要知道或关心如何处理有关其距离的信息。使用通知。让Sequencer侦听通知,并让Notes在距离合适时发送通知。您也不需要通知,通知就像在对讲机上发送消息,任何具有该频率的人都可以收听。如果没有代码,很难确切地说该做什么,但是应该有某种管理者来处理注释和序列。我假设这是游戏场景。游戏场景应该看一下便条,然后告诉序列它是upOk。我以前用过通知。我读过一些网站说,由于可追溯性和类似的东西,这很糟糕,这就是为什么我开始研究授权和其他解决方案。这很棘手,因为我知道我想让我的代码做什么,但我不知道如何在代码中清楚地表达这一点而不让它变得更混乱。试图让你的代码有条理是件苦差事!感谢您的回复。为您的所有对象指定一个特定的作业。笔记的工作不应该是告诉某人他们正在接近。notes的工作应该是做note所做的任何事情。其他人应该扮演总机,并在执行某些事件时进行通信,这些被称为管理者。@Knight0fDragon我将在上面发布一些代码,并解释到目前为止这些类负责什么。正如你所说的,我试着给我所有的班级一个单一的任务来完成。我不会使用授权,就像这个词所暗示的那样,它是当你让某人完成任务的时候