Domanda

Per favore qualcuno può aiutare a risolvere un noob fuori? Ho postato questo problema su vari forum e ho ricevuto nessuna risposta, mentre molte ricerche per altre risposte hanno alzato StackOverflow, quindi sto sperando che questo è il posto giusto.

Ho un BeachView.h (sottoclasse di UIScrollView, foto di una spiaggia di sabbia) coperto con un numero casuale di Stone.h (sottoclasse di UIImageView, un PNG casuale di una pietra, userInteractionEnabled = YES per accettare tocchi) .

Se i tocchi di utenti e si muove sulla spiaggia, dovrebbe scorrere. Se l'utente tocca una pietra, si deve chiamare il metodo "touchedStone". Se l'utente tocca la spiaggia dove non c'è pietra, si deve chiamare il metodo "touchedBeach".

Ora, mi rendo conto che questo suona semplice morto. Tutti e tutto mi dice che se c'è qualcosa su un UIScrollView che accetta tocchi che dovrebbe passare il controllo su di esso. Così, quando ho toccare e trascinare, si deve scorrere; ma se si tocca, ed è su una pietra, si deve ignorare rubinetti da spiaggia e di accettare i rubinetti in pietra, sì?

Tuttavia, sembra che entrambe le viste stanno accettando il rubinetto e chiamando sia touchedStone E touchedBeach. Inoltre, il rubinetto mare si verifica per primo, quindi non posso anche mettere in una bandiera "se touchedStone quindi non correre touchedBeach" tipo.

Ecco un po 'di codice. Su BeachView.m


- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
     if (self.decelerating) { didScroll = YES; }
        else { didScroll = NO; }

     UITouch *touch = [[event allTouches] anyObject];
     CGPoint touchLocation = [touch locationInView:touch.view];
     NSLog(@"touched beach = %@", [touch view]);
     lastTouch = touchLocation;
     [super touchesBegan:touches withEvent:event];
}

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
     didScroll = YES;
     [super touchesMoved:touches withEvent:event];
}

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
     if (didScroll == NO && isPaused == NO) { 
          [self touchedBeach:YES location:lastTouch];
     }
     [super touchesEnded:touches withEvent:event];
}

On Stone.m


-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
     [parent stoneWasTouched]; // parent = ivar pointing from stone to beachview
}

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
     UITouch *touch = [[event allTouches] anyObject];
     CGPoint touchLocation = [touch locationInView:touch.view];
     NSLog(@"touched stone = %@", [touch view]);
     [parent touchedStone:YES location:touchLocation];
}

Dopo un rubinetto di pietra, La mia NSLog assomiglia a questo:


Touched beach = <BeachView: 0x1276a0>
ran touchedBeach
Touched Stone = <Stone: 0x1480c0>
ran touchedStone

Quindi è effettivamente in esecuzione entrambi. Che cosa è ancora più strano è se prendo il touchesBegan e touchesEnded fuori Stone.m ma lascio userInteractionEnabled = YES, il Beachview registra entrambi si tocchi, ma restituisce lo Stone come la vista ha toccato (la seconda volta).


Touched beach = <BeachView: 0x1276a0>
ran touchedBeach
Touched beach = <Stone: 0x1480c0>
ran touchedBeach

Quindi, per favore, ho cercato di risolvere questo per giorni. Come faccio a fare in modo una pietra sfruttato solo chiamate touchedStone e una spiaggia sfruttato solo chiamate touchedBeach? Dove sto andando male?

È stato utile?

Soluzione

Prima di iPhone OS 3.0, l'UIScrollView hitTest: withEvent:. Metodo restituisce sempre di sé in modo che riceva l'UIEvent direttamente, l'inoltro solo per la visualizzazione secondaria appropriata se e quando si determina non è legato al scrolling o lo zoom

non ho potuto commentare su iPhone OS 3.0, come è sotto NDA, ma controllare il vostro "osserva iPhone SDK di uscita per iPhone OS 3.0 beta 5":)

Se avete bisogno di indirizzare pre-3.0, si potrebbe ignorare hitTest: withEvent:. In BeachView e impostare un flag di ignorare il successivo tocco spiaggia se la CGPoint è in realtà in una pietra

Ma hai provato semplicemente spostando le chiamate a [Super tocca *: withEvent:] dalla fine dei tuoi metodi override all'avvio? Ciò potrebbe causare il rubinetto di pietra che si verifichi prima.

Altri suggerimenti

È vero, iPhone SDK 3.0 e fino, non passare tocchi per -touchesBegan: e -touchesEnded: ** ** UIScrollview metodi delle sottoclassi più. È possibile utilizzare i metodi touchesShouldBegin e touchesShouldCancelInContentView che non è lo stesso.

Se davvero si vuole ottenere questo tocchi, hanno una mod che permettere questo.

Nella vostra sottoclasse di UIScrollView l'override del metodo hitTest in questo modo:

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {

  UIView *result = nil;
  for (UIView *child in self.subviews)
    if ([child pointInside:point withEvent:event])
      if ((result = [child hitTest:point withEvent:event]) != nil)
        break;

  return result;
}

Questa passerà a voi sottoclasse questo tocca, tuttavia non è possibile annullare i tocchi di UIScrollView superclasse.

Ho avuto un problema simile con un simpleView e viene aggiunto a una scrollView, e ogni volta che ho toccato la simpleView, il scrollView usato per ottenere il tatto e al posto del SimpleView, il scrollView commosso. Per evitare questo, ho disabilitato lo srcolling del scrollView quando l'utente ha toccato la simpleView e altrimenti lo scorrimento è attivato.

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {

    UIView *result = [super hitTest:point withEvent:event] ;
    if (result == simpleView)
    {
        scrollView.scrollEnabled = NO ;
    }
    else
    {
        scrollView.scrollEnabled = YES ;
    }

    return result ;

}

Questo potrebbe essere correlato a un bug in iOS7 si prega di consultare il mio problema (bug report presentato)

UIScrollView sottoclasse è cambiato il comportamento in iOS7

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top