Posts etiquetados ‘SDK iOS8’


Modificar el código del controlador API

En primer lugar, nuestro plan real para esta aplicación es mostrar información de música iTunes. Así que vamos a modificar el controlador de API para manejar mejor esta información.

Una cosa me ha estado molestando sin embargo. Cuando creamos nuestra APIController, establecimos un delegado después de que se creó. Pero, un controlador de API sin un delegado no es tan útil, ¿por qué incluso ofrecen la opción de hacer uno?

Vamos a añadir un constructor que acepta el delegado, ya que es único.

init(delegate: APIControllerProtocol) {
    self.delegate = delegate
}
Ahora, nuestra variable delegado en el APIController no es en realidad va a ser una opción más. No hay APIController sin un delegado!
Así también cambiar la propiedad de ser un delegado, no opcional objeto APIControllerProtocol todos los días.
var delegate: APIControllerProtocol
Hay también va a haber un error al final del método searchItunesFor, porque estamos tratando el objeto delegado como una opción, pero no es opcional más. Así que cambiar la línea errónea de decir esto:
self.delegate.didReceiveAPIResults(results)
La única diferencia es que quitamos el? desde luego la propiedad delegado, para indicar que no es un opcional.
Ahora en nuestra SearchResultsController, tenemos que cambiar algunas cosas. En primer lugar, ya que el constructor APIController ahora necesita el objeto delegado para ejecutarse antes de *it* se pueden crear instancias en sí, tenemos que hacer que sea una forma implícita envolver opcional, y esperar hasta viewDidLoad para asignarlo.
var api : APIController!
En el método viewDidLoad tenemos que desenvolver el objeto api con el fin de llamar searchItunesFor (). Usted debe terminar con esta.
override func viewDidLoad() {
    super.viewDidLoad()
    api = APIController(delegate: self)
    api.searchItunesFor("JQ Software")
}
Busca los álbumes
También vamos a modificar nuestra llamada a la searchItunesFor () en la APIController utilizar un término de búsqueda para la música. También mostraremos un networkActivityIndicator, para indicar al usuario una operación de red está sucediendo. Esto se mostrará en la barra de estado superior del teléfono.
override func viewDidLoad() {
    super.viewDidLoad()
    api = APIController(delegate: self)
    UIApplication.sharedApplication().networkActivityIndicatorVisible = true
    api.searchItunesFor("Beatles")
}
Ahora en nuestra urlPath en el APIController, vamos a modificar los parámetros de la API para buscar específicamente para álbumes.
leturlPath = "https://itunes.apple.com/search?term=\(escapedSearchTerm)&media=music&entity=album"
Ahora pondremos los resultados en forma de datos Álbum, pero este esquema es un poco diferente de aplicaciones. De hecho se ejecuta la aplicación en este momento vamos a simplemente pondremos células defecto porque los datos JSON esperado no está allí. Este es el código muy frágil, pero podemos hacer que sea un poco menos frágil haciendo algunas modelado de los datos que esperamos.

Creación de un modelo Swift para iTunes Álbumes

Con el fin de facilitar que pasa alrededor de la información sobre los álbumes, debemos crear un modelo de lo que un álbum es exactamente. Crear un nuevo archivo rápida y llamarlo Album.swift con el siguiente contenido:

importFoundation
struct Album {
    lettitle: String
    letprice: String
    letthumbnailImageURL: String
    letlargeImageURL: String
    letitemURL: String
    letartistURL: String
    
    init(name: String, price: String, thumbnailImageURL: String, largeImageURL: String, itemURL: String, artistURL: String) {
        self.title = name
        self.price = price
        self.thumbnailImageURL = thumbnailImageURL
        self.largeImageURL = largeImageURL
        self.itemURL = itemURL
        self.artistURL = artistURL
    }
}
Es una estructura muy simple, sólo tiene unas pocas propiedades sobre álbumes para nosotros. Creamos las 6 propiedades diferentes como cadenas, y añadimos un inicializador que establece todas las propiedades en base a nuestros parámetros.

Así que ahora tenemos una estructura para los álbumes, vamos a usarlo!

Usando nuestro nuevo modelo Swift álbum

De vuelta en nuestra SearchResultsController, vamos a modificar la variable de matriz TableData, y en lugar de optar por una variedad nativa Swift para los álbumes. En rápido, esto es tan fácil como:

var albums = [Album]()
Podemos acabar con la línea de hacer var TableData = [], no vamos a estar usando eso nunca más.

Esto crea una matriz vacía que contiene estrictamente álbumes. Ahora tendremos que cambiar nuestros métodos DataSource y delegadas tableView entender álbumes.
En el método numberOfRowsInSection, vamos a cambiar el número de elementos a la cuenta de álbumes en nuestra gama álbumes:

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return albums.count
}
Ahora en cellForRowAtIndexPath, vamos intercambie a cabo esas operaciones de búsqueda de diccionario para un solo álbum de búsqueda:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    letcell: UITableViewCell = tableView.dequeueReusableCellWithIdentifier(kCellIdentifier) as! UITableViewCell
    letalbum = self.albums[indexPath.row]
    // Get the formatted price string for display in the subtitle
    cell.detailTextLabel?.text = album.price
    // Update the textLabel text to use the title from the Album model
    cell.textLabel?.text = album.title
    
    // Start by setting the cell's image to a static file
    // Without this, we will end up without an image view!
    cell.imageView?.image = UIImage(named: "Blank52")
    
    letthumbnailURLString = album.thumbnailImageURL
    letthumbnailURL = NSURL(string: thumbnailURLString)!
    
    // If this image is already cached, don't re-download
    ifletimg = imageCache[thumbnailURLString] {
        cell.imageView?.image = img
    }
    else{
        // The image isn't cached, download the img data
        // We should perform this in a background thread
        letrequest: NSURLRequest = NSURLRequest(URL: thumbnailURL)
        letmainQueue = NSOperationQueue.mainQueue()
        NSURLConnection.sendAsynchronousRequest(request, queue: mainQueue, completionHandler: { (response, data, error) -> Void in
            iferror == nil {
                // Convert the downloaded data in to a UIImage object
                letimage = UIImage(data: data)
                // Store the image in to our cache
                self.imageCache[thumbnailURLString] = image
                // Update the cell
                dispatch_async(dispatch_get_main_queue(), {
                    ifletcellToUpdate = tableView.cellForRowAtIndexPath(indexPath) {
                        cellToUpdate.imageView?.image = image
                    }
                })
            }
            else{
                println("Error: \(error.localizedDescription)")
            }
        })
    }
    returncell
}
Luego está el método didSelectRowAtIndexPath que necesita ser modificado para utilizar la matriz de discos. Pero, en realidad no vamos a necesitar esto más, así que vamos a borrar todo el método.

Creación de objetos Álbum de JSON

Ahora bien, todo esto no sirve de mucho si no estamos creando nuestra información del álbum en el primer lugar. Necesitamos modificar nuestro método didReceiveAPIResults de SearchResultsViewController tomar resultados JSON álbum, crear objetos Álbum, y guardarlas en álbumes a la matriz. Ya que tenemos un modelo para los álbumes ahora, tiene sentido para mover esta funcionalidad en el modelo del álbum en sí. Así que vamos a hacer un pequeño ajuste a didReceiveAPIResults y delegar la responsabilidad de la construcción de la matriz de discos a la clase del álbum.

func didReceiveAPIResults(results: NSArray) {
    dispatch_async(dispatch_get_main_queue(), {
        self.albums = Album.albumsWithJSON(results)
        self.appsTableView!.reloadData()
        UIApplication.sharedApplication().networkActivityIndicatorVisible = false
    })
}
Tenga en cuenta que ya que es donde viene la solicitud del API para su conclusión, también apagamos el networkActivityIndicator.

Ahora en el archivo Album.swift tenemos que añadir un método estático que crea una lista de los álbumes de una lista JSON.

static func albumsWithJSON(results: NSArray) -> [Album] {
    // Create an empty array of Albums to append to from this list
    var albums = [Album]()
    
    // Store the results in our table data array
    if results.count>0 {
        
        // Sometimes iTunes returns a collection, not a track, so we check both for the 'name'
        for result in results {
            
            var name = result["trackName"] as? String
            if name == nil {
                name = result["collectionName"] as? String
            }
            
            // Sometimes price comes in as formattedPrice, sometimes as collectionPrice.. and sometimes it's a float instead of a string. Hooray!
            var price = result["formattedPrice"] as? String
            if price == nil {
                price = result["collectionPrice"] as? String
                if price == nil {
                    var priceFloat: Float? = result["collectionPrice"] as? Float
                    var nf: NSNumberFormatter = NSNumberFormatter()
                    nf.maximumFractionDigits = 2
                    if priceFloat != nil {
                        price = "$\(nf.stringFromNumber(priceFloat!)!)"
                    }
                }
            }
            
            let thumbnailURL = result["artworkUrl60"] as? String ?? ""
            let imageURL = result["artworkUrl100"] as? String ?? ""
            let artistURL = result["artistViewUrl"] as? String ?? ""
            
            var itemURL = result["collectionViewUrl"] as? String
            if itemURL == nil {
                itemURL = result["trackViewUrl"] as? String
            }
            
            var newAlbum = Album(name: name!, price: price!, thumbnailImageURL: thumbnailURL, largeImageURL: imageURL, itemURL: itemURL!, artistURL: artistURL)
            albums.append(newAlbum)
        }
    }
    return albums
}
Sé que esto se parece a una gran cantidad de código nuevo, pero en realidad no hay mucho que hacer aquí. No deja de ser un bucle a través de la lista que viene de allResults, y su acaparamiento de valores para algunas teclas, y el establecimiento de los valores predeterminados si se pierden.

Los ?? operador utilizado aquí es bastante ordenada. Funciona así:

let finalVariable = possiblyNilVariable ?? "Definitely Not Nil Variable"
El valor finalVariable se establece en possiblyNilVariable si no es nula. Pero si es nula? Se utiliza el valor de la cosa en el lado derecho de la ?? operador. En este caso, la cadena “Definitivamente no Variable Cero”.

Utilizamos esta aquí con el fin de prevenir el contagio de los valores nulos pasados en nuestro álbum.

En la línea 39, creamos un objeto del álbum. En la línea 40 del álbum se añade a la lista.
Por último en la línea 43 se devuelve la lista de álbumes.

Si ejecuta la aplicación debería ver una nueva lista de pop-up de cada álbum. Fresco, ¿no?

La creación de una segunda vista

Ahora para mostrar realmente los detalles de un álbum, necesitaremos una nueva vista. En primer lugar vamos a crear la clase.
Añadir un nuevo archivo llamado DetailsViewController.swift que hereda de UIViewController.

Nuestro controlador de vista será muy simple para empezar. Sólo vamos a agregar un álbum, y poner en práctica el método init del UIViewController así como viewDidLoad ().

import UIKit
class DetailsViewController: UIViewController {
    
    var album: Album?
    
    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
}
En el video que hicimos lo siguiente:

Embedded nuestro controlador de vista en un controlador de navegación utilizando el atajo de Xcode en el menú Editor, haga clic en el controlador de vista, luego seleccionando Editor-> In-> Controlador encajar Navegación
Se ha añadido un nuevo controlador de vista
Establecer es clase y storyboard ID para ‘DetailsViewController’
Control + Clicked + arrastró desde la vista de celda de la tabla en nuestro primer controlador vistas al nuevo controlador de vista que acabamos de crear, y selecciona ‘show’ para el tipo de segue.
Lo que este último paso hace es crea un segue en nuestro controlador de navegación que empuja a la nueva vista en la parte superior de la pila. Si ejecuta la aplicación y haga clic en una celda, debe ver esta nueva visión animado en.

Vamos a construir una sencilla interfaz de usuario para esta nueva visión. Se va a contener un UIImageView que es 100 × 100 píxeles, y una etiqueta de título. Arrastre estos objetos fuera de la biblioteca de objetos y organizarlos como quieras en la nueva vista.

Providing the new view with Album information

When the storyboard segue fires off, it first calls a function on whatever view controller is currently on the screen called prepareForSegue. We’re going to intercept this call in order to tell our new view controller which album we’re looking at. Add the following in SearchResultsViewController:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if let detailsViewController: DetailsViewController = segue.destinationViewController as? DetailsViewController {
        var albumIndex = appsTableView!.indexPathForSelectedRow()!.row
        var selectedAlbum = self.albums[albumIndex]
        detailsViewController.album = selectedAlbum
    }
}
¿Qué está pasando aquí es el parámetro segue siendo aprobada en tiene un miembro llamado destinationViewController, que es nuestra fantasía nueva DetailsViewController que acabamos de crear. Con el fin de establecer el miembro álbum en él, primero tenemos que echarlo a DetailsViewController utilizando el “como” de palabras clave como se muestra arriba.
Luego, utilizando el método indexPathForSelectedRow () de nuestra vista de tabla podemos determinar qué álbum es seleccionado en el momento presente segue sucede.
Con esta información, así decirle a nuestro detailsViewController qué álbum se ha hecho clic antes de que se muestre.

Ahora voy a mostrar una característica bastante ingeniosa de Xcode. Vamos a dejar que escribir algo de código para nosotros.

Abre tu guión gráfico de nuevo vamos a empezar creando IBOutlets para nuestra vista de la imagen, etiqueta, botón, y vista de texto. En la esquina superior derecha de Xcode está el botón de ‘asistente’. El icono se parece a una chaqueta de pajarita y traje. Haciendo clic en este se abrirá una ventana de código justo al lado de la ventana de su guión gráfico. Asegúrese de que uno de los paneles está mostrando DetailsViewController.swift, y el otro está mostrando Main.storyboard.

Ahora, mantenga el control, y haga clic + arrastrar de su vista de la imagen en el archivo de código. Sólo una línea debajo de la definición de clase para DetailsViewController. Esto te pedirá un nombre, así que vamos a llamarlo ‘albumCover’. Las opciones por defecto deberían estar bien aquí. Después de hacer esto usted debe ver esta línea de código que acaba de agregar:

@IBOutlet weak varalbumCover: UIImageView!
self.delegate.didReceiveAPIResults(results)
Acabamos de crear una nueva IBOutlet, y ahora está conectado a DetailsViewController de nuestro guión gráfico. Cuan genial es eso?

Haga lo mismo para el sello que ha añadido a su punto de vista, y lo llaman ‘TitleLabel’.

A continuación, vamos a modificar viewDidLoad para que se cargue en la información que nos están pasamos a nuestros objetos de vista, aquí está el código DetailsViewController definitiva:

import UIKit
class DetailsViewController: UIViewController {
    var album: Album?
    @IBOutlet weak var albumCover: UIImageView!
    @IBOutlet weak var titleLabel: UILabel!
    
    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        titleLabel.text = self.album?.title
        albumCover.image = UIImage(data: NSData(contentsOfURL: NSURL(string: self.album!.largeImageURL)!)!)
    }
}
LosIBOutlets son las conexiones de interfaz de usuario realizadas por nuestros guiones gráficos, y nuestro método viewDidLoad establece las variables de título y de la cubierta del álbum para cargar desde nuestro objeto álbum.

Ahora intente ejecutar la aplicación y echar un vistazo. Ahora podemos perforar en los detalles para los álbumes y obtener una grande y bonita vista de detalle con la portada del álbum y el título. Debido a que empujamos en un controlador de navegación, también conseguimos un botón Volver funcional de forma gratuita!

FUENTE:
DESCARGA:
Bueno hago esta traducción ya que no eh encontrado mucha información es español para que lo puedan entender gracias.
Anuncios