Dalla loro introduzione in Xcode 6 insieme a Swift, fino alla loro attuale iterazione in Xcode 7.3.1, i parchi giochi hanno fatto molta strada. Con nuove funzionalità e una migliore stabilità, si stanno evolvendo in uno strumento fattibile per la prototipazione rapida o l'hacking rapido di una dimostrazione del concetto.
Come sviluppatore, a volte hai un lampo di ispirazione sotto forma di un'idea interessante per un'app e vuoi codificare rapidamente un prototipo che rappresenta la nuda essenza della tua idea. O vuoi solo verificare la tua comprensione di come si comporterà una parte del codice UIKit. Se sei come me, preferiresti evitare il fastidio e il sovraccarico mentale della creazione di un progetto Xcode e di dover gestire una miriade di fattori, come i tipi di dispositivi e le risoluzioni e le impostazioni di costruzione. Queste decisioni possono essere rimandate fino a dopo che hai deciso che l'idea principale è degna di essere perseguita.
In questo tutorial, creiamo un gioco di memoria basato su schede tutto all'interno dei confini di un parco giochi. È un gioco comune e ben noto, quindi non c'è credito per l'originalità lì. Il gioco consiste di otto coppie di carte identiche (quindi un totale di 16 carte) messe a faccia in giù in una griglia 4x4.
Il giocatore ha bisogno di capovolgere due carte i cui volti sono rivelati brevemente e poi rapidamente tornare indietro. L'obiettivo del gioco è che il giocatore tenti di ricordare le posizioni delle carte e scoprire coppie identiche, che vengono rimosse dal gioco. Il gioco termina quando viene cancellata la griglia.
Il gioco è basato sul tocco e incorpora semplici animazioni di visualizzazione. Scopri come apportare modifiche alla tua app e vedere i risultati delle tue modifiche dal vivo.
Accendi Xcode e seleziona Nuovo> Parco giochi ... da Xcode's File menu. Dai al parco giochi un nome, ad esempio MemoryGameXCPTut, impostato piattaforma a iOS, e salvare il parco giochi. Sto usando Xcode 7.3.1 per questo tutorial.
Passiamo un po 'di tempo a familiarizzare con l'interfaccia del parco giochi. Sentiti libero di sfogliare questa sezione se hai già familiarità con i campi da gioco.
Un parco giochi può avere più pagine, ciascuna associata alla propria visualizzazione live e alle proprie cartelle di risorse / risorse. Non useremo più pagine in questo tutorial. I parchi giochi supportano la formattazione del markup che ti consente di aggiungere un testo avanzato a un parco giochi e un collegamento tra le pagine del parco giochi.
La prima cosa che vedi dopo aver creato un parco giochi è l'editor di sorgenti del parco giochi. Qui è dove scrivi il codice, che ha un effetto immediato sulla visualizzazione live. Uno dei modi per attivare l'aspetto (dis) di Project Navigator sta usando la scorciatoia Comando-0. Nel Project Navigator, puoi vedere due cartelle, fonti e risorse.
Nel fonti cartella, è possibile aggiungere un codice ausiliario in uno o più file Swift, come classi personalizzate, visualizzare i controller e le viste. Anche se la maggior parte del codice che definisce la logica del tuo prototipo va lì, è ausiliaria nel senso che è nascosta in background quando stai visualizzando la tua app in diretta.
Il vantaggio di inserire il codice ausiliario nel file fonti la cartella è che viene compilata automaticamente ogni volta che si modifica e si salva il file. In questo modo, si ottiene un feedback più veloce nella visualizzazione live dalle modifiche apportate nel campo da gioco. Torna nel parco giochi, sei in grado di accedere pubblico proprietà e metodi esposti nel codice ausiliario che influiscono sul comportamento della tua app.
È possibile aggiungere risorse esterne, come immagini, in risorse cartella.
In questo tutorial, è spesso necessario saltare tra un file Swift che creiamo in fonti cartella e il file del parco giochi (tecnicamente anche un file Swift, tranne che non ti riferirai con il nome del file). Usiamo anche il Assistente editore nel tutorial, avendo visualizzato il Sequenza temporale, per visualizzare l'output dal vivo parallelamente al codice del parco giochi. Qualsiasi modifica apportata al campo da gioco si riflette istantaneamente (beh, in pochi secondi) nell'output live. Puoi anche interagire con la vista live e i suoi elementi dell'interfaccia utente. Per assicurarti di poter fare tutto questo, dai un'occhiata alla figura sottostante.
Corrispondente ai numeri verdi che ho aggiunto alla figura:
A volte, quando si guarda il parco giochi, è necessario assicurarsi che il Assistente editore sta visualizzando il Sequenza temporale invece di qualche altro file. La seguente figura mostra come fare questo. Nel Assistente editore, selezionare Sequenza temporale, la controparte del parco giochi, invece di Manuale, che ti permette di mostrare qualsiasi file nel file Assistente editore.
Quando si modifica un file sorgente dal fonti cartella, come sua controparte, il Assistente editore mostra l'interfaccia del tuo codice, cioè dichiarazioni e prototipi di funzioni senza le loro implementazioni. Preferisco nascondere il Assistente editore quando sto lavorando su un file in fonti cartella e esporre solo il Assistente editore nel parco giochi per vedere la vista dal vivo.
Per accedere alle abilità speciali dei campi da gioco, è necessario importare il modulo XCPlayground.
importa XCPlayground
Hai impostato il dal vivo
proprietà del pagina corrente
del XCPlaygroundPage
oggetto a un oggetto conforme al XCPlaygroundLiveViewable
protocollo. Questo può essere un corso personalizzato o può essere un UIView
o UIViewController
esempio.
Ho aggiunto alcune immagini con le quali possiamo lavorare in questo tutorial. Scarica le immagini, estrai l'archivio e aggiungi le immagini nel immagini cartella al risorse cartella del parco giochi nel Project Navigator.
Assicurati di trascinare solo le immagini in modo che ciascun file immagine risieda nel risorse cartella, non in Risorse / Immagini.
Elimina il codice nel parco giochi. Fare clic con il tasto destro del mouse su fonti cartella e selezionare Nuovo file dal menu. Imposta il nome del file su Game.swift.
Aggiungere il seguente codice a Game.swift. Assicurati di salvare il file dopo ogni aggiunta di codice.
import UIKit import XCPlayground import GameplayKit // (1) estensione pubblica UIImage // (2) public convenience init? (color: UIColor, dimensione: CGSize = CGSize (larghezza: 1, altezza: 1)) let rect = CGRect ( origine: .zero, dimensione: dimensione) UIGraphicsBeginImageContextWithOptions (rect.size, false, 0.0) color.setFill () UIRectFill (rect) let image = UIGraphicsGetImageFromCurrentImageContext () UIGraphicsEndImageContext () guardia lascia cgImage = image.CGImage else return nil self .init (CGImage: cgImage) let cardWidth = CGFloat (120) // (3) let cardHeight = CGFloat (141) public class Card: UIImageView // (4) public lascia x: Int pubblico let y: Int pubblico init (image: UIImage ?, x: Int, y: Int) self.x = x self.y = y super.init (immagine: immagine) self.backgroundColor = .grayColor () self.layer.cornerRadius = 10.0 self .userInteractionEnabled = true richiesto public init? (coder aDecoder: NSCoder) fatalError ("init (coder :) non è stato implementato")
Ho aggiunto alcuni commenti numerati per spiegare alcune sezioni dell'implementazione:
UIKit
e XCPlayground
, stiamo anche importando GamePlayKit
. Questo framework include un metodo conveniente che ci aiuterà a implementare un metodo per mescolare casualmente un array.UIImage
ci consente, con l'aiuto di UIKit
metodi, per rendere le immagini con un colore solido di qualsiasi dimensione che vogliamo. Lo useremo per impostare l'immagine di sfondo iniziale delle carte da gioco.cardHeight
e cardWidth
le costanti rappresentano le dimensioni delle immagini delle carte in base alle quali calcoleremo altre dimensioni.Carta
classe, ereditando da UIImageView
, rappresenta una carta. Anche se impostiamo alcune proprietà nel Carta
classe, lo scopo principale della creazione di questa classe è quello di aiutarci a identificare e scorrere le sottoview che corrispondono alle carte da gioco nel gioco. Le carte hanno anche proprietà X
e y
per ricordare la loro posizione nella griglia.Aggiungere il seguente codice a Game.swift, subito dopo il codice precedente:
public class GameController: UIViewController // (1): variabili pubbliche in modo da poterle manipolare nel playground public var padding = CGFloat (20) / * didSet resetGrid () * / public var backImage: UIImage = UIImage ( color: .redColor (), size: CGSize (width: cardWidth, height: cardHeight))! // (2): proprietà calcolate var viewWidth: CGFloat get return 4 * cardWidth + 5 * padding var viewHeight: CGFloat get return 4 * cardHeight + 5 * padding var shuffledNumbers = [Int] () // memorizza i numeri delle carte mescolate // var firstCard: Card? // uncomment tardi public init () super.init (nibName: nil, bundle: nil) preferredContentSize = CGSize (width: viewWidth, height: viewHeight) shuffle () setupGrid () // commento successivo: // let tap = UITapGestureRecognizer (target: self, action: #selector (GameController.handleTap (_ :))) // view.addGestureRecognizer (tap) required public init? (coder aDecoder: NSCoder) fatalError ("init (coder :) non è stato implementato ") override pubblico func loadView () view = UIView () view.backgroundColor = .blueColor () view.frame = CGRect (x: 0, y: 0, larghezza: viewWidth, altezza: viewHeight) // ( 3): Utilizzo dell'API GameplayKit per generare uno shuffling dell'array [1, 1, 2, 2, ..., 8, 8] func shuffle () let numbers = (1 ... 8) .flatMap [$ 0, $ 0] shuffledNumbers = GKRandomSource.sharedRandom (). arrayByShufflingObjectsInArray (numeri) come! [Int] // (4): Converti dalla posizione della carta sulla griglia all'indice nei numeri della carta mescolata. Matrice func cardNumberAt (x: Int, _ y: Int) -> Int assert (0 <= x && x < 4 && 0 <= y && y < 4) return shuffledNumbers[4 * x + y] // (5): Position of card's center in superview func centerOfCardAt(x: Int, _ y: Int) -> CGPoint asserire (0 <= x && x < 4 && 0 <= y && y < 4) let (w, h) = (cardWidth + padding, cardHeight + padding) return CGPoint( x: CGFloat(x) * w + w/2 + padding/2, y: CGFloat(y) * h + h/2 + padding/2) // (6): setup the subviews func setupGrid() for i in 0… <4 for j in 0… <4 let n = cardNumberAt(i, j) let card = Card(image: UIImage(named: String(n)), x: i, y: j) card.tag = n card.center = centerOfCardAt(i, j) view.addSubview(card) // (7): reset grid /* func resetGrid() view.frame = CGRect(x: 0, y: 0, width: viewWidth, height: viewHeight) for v in view.subviews if let card = v as? Card card.center = centerOfCardAt(card.x, card.y) */ override public func viewDidAppear(animated: Bool) for v in view.subviews if let card = v as? Card // (8): failable casting UIView.transitionWithView( card, duration: 1.0, options: .TransitionFlipFromLeft, animations: card.image = self.backImage , completion: nil)
imbottitura
e backImage
, sono dichiarati pubblico
in modo che possiamo accedervi nel parco giochi più tardi. Rappresentano lo spazio vuoto che circonda le carte sulla griglia e l'immagine visualizzata sul retro di ciascuna carta, rispettivamente. Si noti che a entrambe le proprietà sono stati dati valori iniziali, che rappresentano una spaziatura di 20 e un colore rosso fisso per l'immagine non frontale della carta. Puoi ignorare il codice commentato per ora.viewWidth
calcolo, ricorda che ci sono quattro carte in ogni riga e dobbiamo anche prendere in considerazione il padding di ogni carta. La stessa idea si applica al viewHeight
calcolo.(1 ... 8). FlatMap [$ 0, $ 0]
è un modo conciso per produrre l'array [1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8]
. Se non hai familiarità con la programmazione funzionale, potresti anche scrivere a per
-loop per generare l'array. Usando metodi dal GamePlayKit
framework, mescoliamo i numeri nell'array. I numeri corrispondono alle otto coppie di carte. Ogni numero rappresenta l'immagine della carta con lo stesso nome (ad esempio, un valore di 1
nel shuffledArray
corrisponde a 1.png).shuffledNumbers
array di lunghezza 16. Il fattore 4
nel calcolo aritmetico riflette il fatto che abbiamo quattro carte per riga.centro
proprietà) nella griglia in base alle dimensioni e al riempimento della carta.setupGrid ()
il metodo viene chiamato durante l'inizializzazione del controller della vista. Disegna il 4x4 Carta
griglia. Assegna inoltre l'identità di ciascuna carta in base al shuffledNumbers
array e lo memorizza nel etichetta
proprietà ereditata dalla classe base della carta, UIView
. Nella logica del gioco, confrontiamo il etichetta
valori per capire se due carte corrispondono o meno. Questo schema di modellizzazione piuttosto rudimentale serve abbastanza bene per i nostri bisogni attuali.imbottitura
proprietà come proprietà pubblica in modo che possiamo accedervi nel parco giochi.viewDidAppear (_ :)
viene eseguito immediatamente dopo che la vista del controller della vista diventa visibile. Effettuiamo l'iterazione delle sottoview della vista e, se la sottoview è un'istanza di Carta
classe, (controllato attraverso il come?
operatore di downcasting disponibile) il corpo del Se
-la dichiarazione definisce la transizione da eseguire. Qui è dove cambieremo l'immagine visualizzata sulle carte, dall'immagine del fumetto che definisce la faccia di ogni carta al (comune) backImage
di tutte le carte. Questa transizione è accompagnata da un'animazione di vibrazione da sinistra a destra che dà l'impressione che le carte vengano fisicamente girate. Se non hai familiarità con come UIView
le animazioni funzionano, questo può sembrare un po 'strano. Anche se abbiamo aggiunto l'animazione di ogni carta in sequenza in un ciclo, le animazioni sono raggruppate in una singola transazione di animazione ed eseguite simultaneamente, cioè le carte ruotano insieme.Rivedi il campo giochi e sostituisci qualsiasi testo nell'editor con il seguente:
import XCPlayground import UIKit let gc = GameController () XCPlaygroundPage.currentPage.liveView = gc
Assicurati che la timeline sia visibile. La visuale del controller della vista dovrebbe prendere vita e mostrarci una griglia di carte 4x4 con simpatici cartoni animati che girano per mostrarci il retro delle carte. In questo momento, non possiamo fare molto con questa visione perché non abbiamo ancora programmato alcuna interazione al suo interno. Ma è sicuramente un inizio.
Passiamo ora alle facce posteriori delle carte dal rosso fisso a un'immagine, in particolare b.png nel risorse cartella. Aggiungi la seguente riga alla fine del campo da giuoco.
gc.backImage = UIImage (named: "b")!
Dopo un secondo o due, vedrai che i lati posteriori delle carte sono passati da una semplice mano rossa a una mano da cartone animato.
Proviamo ora a modificare il imbottitura
proprietà, a cui è stato assegnato un valore predefinito di 20 in Game.swift. Di conseguenza, lo spazio tra le carte dovrebbe aumentare. Aggiungi la seguente riga alla fine del campo giochi:
gc.padding = 75
Attendi che la vista live si aggiorni e vedi che ... nulla è cambiato.
Per capire cosa sta succedendo, devi tenere presente che le entità, come i controller di visualizzazione e le loro viste associate, hanno un ciclo di vita complesso. Ci concentreremo su questi ultimi, cioè sulle visualizzazioni. La creazione e l'aggiornamento della vista di un controller di visualizzazione è un processo a più fasi. In punti specifici del ciclo di vita della vista, le notifiche vengono inviate al UIViewController
, informandolo di cosa sta succedendo. Ancora più importante, il programmatore può collegarsi a queste notifiche inserendo il codice per indirizzare e personalizzare questo processo.
Il loadview ()
e viewDidAppear (_ :)
i metodi sono due metodi che abbiamo usato per agganciare il ciclo di vita della vista. Questo argomento è in qualche modo coinvolto e va oltre lo scopo di questa discussione, ma ciò che conta per noi è che il codice nel parco giochi, dopo l'assegnazione del controller di visualizzazione come il campo da gioco dal vivo
, viene eseguito un po 'di tempo tra la chiamata a viewWillAppear (_ :)
e la chiamata a viewDidAppear (_ :)
. È possibile verificare ciò modificando alcune proprietà nel parco giochi e aggiungere istruzioni di stampa a questi due metodi per visualizzare il valore di questa proprietà.
Il problema con il valore di imbottitura
non avendo l'effetto visivo atteso è che, a quel punto, la vista e le sue sottoview sono già state esposte. Tieni presente che, ogni volta che apporti una modifica al codice, il campo di gioco viene ripetuto dall'inizio. In questo senso, questo problema non è specifico per i campi da gioco. Anche se stavi sviluppando codice da eseguire sul simulatore o su un dispositivo fisico, spesso dovresti scrivere del codice aggiuntivo per assicurarti che la modifica del valore di una proprietà abbia l'effetto desiderato sull'aspetto o sul contenuto della vista.
Potresti chiedere perché siamo stati in grado di modificare il valore di backImage
proprietà e vedere il risultato senza fare nulla di speciale. Osservare che il backImage
la proprietà viene effettivamente utilizzata per la prima volta in viewDidAppear (_ :)
, da quel momento ha già preso il suo nuovo valore.
Il nostro modo di affrontare questa situazione sarà monitorare i cambiamenti nel valore di imbottitura
e ridimensiona / riposiziona la vista e le sottoview. Fortunatamente, questo è facile da fare con Swift a portata di mano osservazione delle proprietà caratteristica. Inizia decommentando il codice per resetGrid ()
metodo in Game.swift:
// (7): reset grid func resetGrid () view.frame = CGRect (x: 0, y: 0, larghezza: viewWidth, height: viewHeight) per v in view.subviews if let card = v as? Card card.center = centerOfCardAt (card.x, card.y)
Questo metodo ricalcola la posizione della cornice della vista e quella di ciascuna Carta
oggetto basato sui nuovi valori di viewWidth
e viewHeight
. Ricorda che queste proprietà sono calcolate in base al valore di imbottitura
, che è stato appena modificato.
Inoltre, modificare il codice per imbottitura
usare il didSet
osservatore il cui corpo, come indica il nome, viene eseguito ogni volta che viene impostato il valore di imbottitura
:
// (1): variabili pubbliche in modo che possiamo manipolarle nel playground public var padding = CGFloat (20) didSet resetGrid ()
Il resetGrid ()
il metodo inizia e la vista viene aggiornata per riflettere la nuova spaziatura. Puoi verificarlo nel parco giochi.
Sembra che siamo stati in grado di sistemare le cose abbastanza facilmente. In realtà, quando ho deciso per la prima volta, volevo essere in grado di interagire con il imbottitura
proprietà, ho dovuto tornare indietro e apportare modifiche al codice in Game.swift. Per esempio, ho dovuto astrarre il Carta
calcolo del centro in una funzione separata (centerOfCardAt (_: _ :)
) per calcolare in modo pulito e indipendente (ri) le posizioni delle carte ogni volta che dovevano essere disposte.
Creare proprietà calcolate per viewWidth
e viewHeight
anche aiutato. Mentre questo tipo di riscrittura è qualcosa che dovresti essere preparato per un compromesso di non fare molto design in anticipo, può essere ridotto con un po 'di lungimiranza ed esperienza.
È giunto il momento di implementare la logica del gioco e permetterci di interagire con esso attraverso il tatto. Inizia decifrando il firstCard
dichiarazione di proprietà nel Gamecontroller
classe:
var firstCard: card?
Ricorda che la logica del gioco implica rivelare due carte, una dopo l'altra. Questa variabile tiene traccia di se un capovolgimento della carta eseguito dal giocatore è il primo dei due o meno.
Aggiungi il seguente metodo alla fine del Gamecontroller
classe, prima della parentesi graffa che termina:
func handleTap (gr: UITapGestureRecognizer) let v = view.hitTest (gr.locationInView (view), withEvent: nil)! se let card = v come? Card UIView.transitionWithView (scheda, durata: 0,5, opzioni: .TransitionFlipFromLeft, animazioni: card.image = UIImage (named: String (card.tag))) // finale del gestore di completamento: _ in card.userInteractionEnabled = false se let pCard = self.firstCard if pCard.tag == card.tag UIView.animateWithDuration (0.5, animations: card.alpha = 0.0, completamento: _ in card.removeFromSuperview ()) UIView.animateWithDuration (0.5, animazioni: pCard.alpha = 0.0, completamento: _ in pCard.removeFromSuperview ()) else UIView.transitionWithView (scheda, durata: 0.5, opzioni: .TransitionFlipFromLeft, animazioni: card.image = self.backImage) _ in card.userInteractionEnabled = true UIView.transitionWithView (pCard, durata: 0.5, opzioni: .TransitionFlipFromLeft, animazioni: pCard.image = self.backImage) _ in pCard.userInteractionEnabled = true self.firstCard = nil else self.firstCard = card
Questo è un metodo lungo. Questo perché racchiude in un unico metodo tutta la gestione del tocco, la logica di gioco e le animazioni associate richieste. Vediamo come questo metodo fa il suo lavoro:
Carta
esempio. Questo è lo stesso come?
costrutto che abbiamo usato in precedenza.Carta
Per esempio, lo capovolgiamo usando un'animazione simile a quella che abbiamo implementato in precedenza. L'unico nuovo aspetto è che utilizziamo il gestore di completamento, che viene eseguito al termine dell'animazione, per disabilitare temporaneamente le interazioni tattili per quella particolare scheda impostando il userInteractionEnabled
proprietà della carta. Questo impedisce al giocatore di capovolgere la stessa carta. Notare la _ nel
costrutto che è usato più volte in questo metodo. Questo è solo per dire che vogliamo ignorare il Bool
parametro che assume il gestore di completamento.firstCard
è stato assegnato un valore non nullo utilizzando l'associazione opzionale, familiare a Swift se lasciato
costruire.firstCard
è non-zero, quindi questa era la seconda carta della sequenza che il giocatore ha girato. Ora dobbiamo confrontare la faccia di questa carta con quella precedente (confrontando il etichetta
valori) per vedere se abbiamo una corrispondenza o meno. Se lo facessimo, animiamo le carte in dissolvenza (impostando le loro alfa
a 0). Rimuoviamo anche queste carte dalla vista. Se i tag non sono uguali, il che significa che le carte non corrispondono, semplicemente li capovolgere di nuovo verso il basso e impostare userInteractionEnabled
a vero
in modo che l'utente possa selezionarli di nuovo.firstCard
, abbiamo impostato su entrambi zero
o alla carta attuale. Questo è il modo in cui cambiamo il comportamento del codice tra due tocchi successivi.Infine, decommentare le seguenti due dichiarazioni nel Gamecontroller
l'inizializzatore che aggiunge un tocco di riconoscimento del gesto alla vista. Quando il rilevatore del gesto di tocco rileva un tocco, il handleTap ()
il metodo è invocato:
let tap = UITapGestureRecognizer (target: self, action: #selector (GameController.handleTap (_ :))) view.addGestureRecognizer (tap)
Torna alla timeline del parco giochi e gioca al gioco di memoria. Sentiti libero di diminuire il grande imbottitura
abbiamo assegnato un po 'prima.
Il codice in handleTap (_ :)
è praticamente la versione non abbellita di ciò che ho scritto la prima volta. Si potrebbe sollevare l'obiezione che, come metodo unico, fa troppo. O che il codice non è abbastanza orientato agli oggetti e che la logica che gira la logica e le animazioni dovrebbe essere ordinatamente estratta in metodi del Carta
classe. Mentre queste obiezioni non sono invalide di per sé, ricorda che la prototipazione rapida è al centro di questo tutorial e dal momento che non prevedevamo alcuna necessità di interagire con questa parte del codice nel parco giochi, potremmo permetterci di essere un po 'più "hack-ish".
Una volta che avremo qualcosa di funzionante e decidiamo di perseguire ulteriormente l'idea, dovremmo certamente prendere in considerazione il refactoring del codice. In altre parole, prima fallo funzionare, quindi rendilo veloce / elegante / bello / ...
Mentre la parte principale del tutorial è finita, come interessante a parte, voglio mostrarti come possiamo scrivere il codice di manipolazione del tocco direttamente nel parco giochi. In primo luogo aggiungeremo un metodo al Gamecontroller
classe che ci permette di sbirciare sui volti delle carte. Aggiungi il seguente codice al Gamecontroller
classe, immediatamente dopo il handleTap (_ :)
metodo:
public func quickPeek () per v in view.subviews if let card = v as? Card card.userInteractionEnabled = false UIView.transitionWithView (card, duration: 1.0, options: .TransitionFlipFromLeft, animations: card.image = UIImage (named: String (card.tag))) _ in UIView.transitionWithView (card , durata: 1.0, opzioni: .TransitionFlipFromLeft, animazioni: card.image = self.backImage) _ in card.userInteractionEnabled = true
Supponiamo di voler attivare o disattivare questa funzione "quick peek" dall'interno del parco giochi. Un modo per farlo sarebbe creare un pubblico Bool
proprietà nel Gamecontroller
classe che potremmo impostare nel parco giochi. E, naturalmente, dovremmo scrivere un gestore di gesti nel Gamecontroller
classe, attivata da un diverso gesto, che invocerebbe quickPeek ()
.
Un altro modo sarebbe quello di scrivere il codice di gestione dei gesti direttamente nel parco giochi. Un vantaggio di farlo in questo modo è che potremmo incorporare qualche codice personalizzato oltre a chiamare quickPeek ()
. Questo è ciò che faremo dopo. Aggiungi il seguente codice alla fine del campo da giuoco:
class LPGR static var counter = 0 @objc static func longPressed (lp: UILongPressGestureRecognizer) if lp.state == .Began gc.quickPeek () counter + = 1 print ("Hai sbirciato \ (contatore) tempo (s) . ") let longPress = UILongPressGestureRecognizer (target: LPGR.self, action: #selector (LPGR.longPressed)) longPress.minimumPressDuration = 2.0 gc.view.addGestureRecognizer (longPress)
Per attivare la funzione di quick peek, useremo un gesto a pressione lunga, cioè il giocatore tiene il dito sullo schermo per un certo periodo di tempo. Usiamo due secondi come soglia.
Per gestire il gesto, creiamo una classe, LPGR
(premere a lungo il riconoscimento del gesto abbreviato), con a statico
proprietà variabile, contatore
, per tenere traccia di quante volte abbiamo sbirciato, e a statico
metodo longPressed (_ :)
per gestire il gesto.
Usando il statico
qualificatore, possiamo evitare di dover creare un LPGR
istanza perché le entità dichiarate statiche sono associate al LPGR
scrivi (classe) piuttosto che con una particolare istanza.
A parte questo, non vi è alcun vantaggio particolare in questo approccio. Per motivi complicati, dobbiamo contrassegnare il metodo come @objc
per mantenere il compilatore felice. Notare l'uso di LPGR.self
per riferirsi al tipo di oggetto. Si noti inoltre che nel gestore del gesto, controlliamo se il stato
del gesto è .Ha inizia