<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Miguel Diaz Rubio</title>
	<atom:link href="http://www.migueldiazrubio.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.migueldiazrubio.com</link>
	<description>Desarrollo iOS y XCode</description>
	<lastBuildDate>Fri, 17 May 2013 08:00:39 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
		<title>Desarrollo iOS: Primeros pasos con UICollectionView (parte II)</title>
		<link>http://www.migueldiazrubio.com/2013/05/17/desarrollo-ios-primeros-pasos-con-uicollectionview-parte-ii/</link>
		<comments>http://www.migueldiazrubio.com/2013/05/17/desarrollo-ios-primeros-pasos-con-uicollectionview-parte-ii/#comments</comments>
		<pubDate>Fri, 17 May 2013 08:00:39 +0000</pubDate>
		<dc:creator>javimoreno</dc:creator>
				<category><![CDATA[Desarrollo iOS]]></category>

		<guid isPermaLink="false">http://www.migueldiazrubio.com/?p=1195</guid>
		<description><![CDATA[<div id="fb-root"></div><p>En este artículo vamos a ponerlos en práctica todos los [...]</p><p>The post <a href="http://www.migueldiazrubio.com/2013/05/17/desarrollo-ios-primeros-pasos-con-uicollectionview-parte-ii/">Desarrollo iOS: Primeros pasos con UICollectionView (parte II)</a> appeared first on <a href="http://www.migueldiazrubio.com">Miguel Diaz Rubio</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>En este artículo vamos a ponerlos en práctica todos los conceptos teóricos aprendidos sobre <strong>UICollectionView</strong> haciendo un juego.</p>
<p><span id="more-1195"></span></p>
<div class='et-box et-shadow'>
					<div class='et-box-content'><b>Javier Moreno</b></p>
<p>Me dedico al desarrollo de software de forma profesional desde 2003. En mis ratos libres estoy aprendiendo a desarrollar aplicaciones para dispositivos iOS, como tantos otros lo hago desde que me compre un iPhone 3G. <img src='http://www.migueldiazrubio.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />
Para contactar conmigo, la mejor forma de hacerlo es en Twitter. Si os interesa el mundo del desarrollo, la tecnología y no os importa leer chorradas, seguid a <a href="http://www.twitter.com/jmoreno78" target="_blank">@jmoreno78</a>. De vez en cuando me pongo un poco más
serio y escribo en <a href="http://javi.zinkinapps.com" target="_blank">http://javi.zinkinapps.com</a>.</div></div>
<h2>Artículo anterior</h2>
<p>Si aún no habéis leido el artículo anterior, podéis consultarlo en <a href="http://www.migueldiazrubio.com/2013/05/14/desarrollo-ios-primeros-pasos-con-uicollectionview-parte-i/" target="_blank"><strong>Desarrollo iOS: Primeros pasos con UICollectionView (parte I)</strong></a>.</p>
<p>&nbsp;</p>
<h2>Introducción</h2>
<p>No, no os creáis que vamos a hacer el nuevo <strong>Angry Birds</strong>, será algo más sencillo: el típico de emparejar cartas iguales.</p>
<p>Empezamos creando una nueva aplicación <strong>iOS</strong> a partir de la plantilla <strong>Single View Application</strong> que llamaremos “Memorion”. En principio, la haremos exclusivamente para <strong>iPad</strong> usando <strong>ARC</strong> y <strong>Storyboards</strong> (si, habéis leído bien: storyboards). La única precaución que tendremos al trabajar con <strong>Storyboards</strong> es desactivar el <strong>Auto Layout</strong> ya que, de lo contrario, tendremos problemas… serios problemas.</p>
<p><a href="http://www.migueldiazrubio.com/wp-content/uploads/2013/05/Captura-de-pantalla-2013-05-07-a-las-00.46.04.png"><img class="alignnone size-full wp-image-1199" alt="Captura de pantalla 2013-05-07 a la(s) 00.46.04" src="http://www.migueldiazrubio.com/wp-content/uploads/2013/05/Captura-de-pantalla-2013-05-07-a-las-00.46.04.png" width="731" height="493" /></a></p>
<p>&nbsp;</p>
<div title="Page 1">
<p>Lo primero que vamos a hacer es diseñar nuestro juego. En eso <strong>storyboard</strong> no tiene parangón ya que vamos a ver como podemos ir incluyendo componentes en nuestra vista y de forma simultánea probar la aplicación para ver como quedaría. En nuestro juego de la memoria vamos a disponer las tarjetas en un grid cuadrado. También necesitaremos un <strong>UIButton</strong> para controlar el comienzo del juego y un <strong>UISegmentedButton</strong> con cuatro segmentos para seleccionar el nivel de dificultad (Bebe, humano, superhombre y robot).</p>
<p>En el <strong>UIControllerViewCell</strong> incluiremos dos elementos <strong>UIImage</strong>, uno para la imagen oculta y otro para una imagen genérica y enigmática. Para darle un poco más de apariencia al juego, crearemos una transición animada entre los cambios de imagen. Para trabajar cómodamente, en el interface builder hacemos un <strong>UIControllerViewCell</strong> cuadrado de un tamaño considerable (150 pixeles de lado, por ejemplo). Dentro de esta celda vamos a incluir los dos <strong>UIImage</strong> de un tamaño ligeramente inferior al de la celda y centrados (de 140 pixeles de lado con un offset de 5 en cada eje). Para asegurarnos de que independientemente del tamaño de la celda, las imágenes conservan unas proporciones y siguen centradas, en el <em>size inspector</em> marcamos en el autosizing que la distancia de cada uno de los lados del objeto con respecto al objeto que lo contiene es fija. El contenido también debe ajustarse al tamaño:</p>
<p><a href="http://www.migueldiazrubio.com/wp-content/uploads/2013/05/Captura-de-pantalla-2013-05-08-a-las-00.47.20.png"><img class="alignnone size-full wp-image-1204" alt="Captura de pantalla 2013-05-08 a la(s) 00.47.20" src="http://www.migueldiazrubio.com/wp-content/uploads/2013/05/Captura-de-pantalla-2013-05-08-a-las-00.47.20.png" width="80" height="99" /></a></p>
<p>El modo de las imágenes será en ambos casos <em>Aspect Fit</em>. Todas estas restricciones van encaminadas a que cuando cambiemos el número de elementos que forman el grid (por el cambio en la dificultad del juego) las imágenes se ajusten lo mejor posible.</p>
<div title="Page 1">
<p>Las imágenes que vamos a usar en esta aplicación son los animales de la fuente <strong>Emoji</strong>. Esta fuente está formada por imágenes a diferentes resoluciones, sin embargo, si incluimos la fuente en un <strong>UILabel</strong> o en un <strong>UITextView</strong> y aumentamos el tamaño veremos que aunque aumenta el tamaño de la fuente la imagen sale renderizada. Por esta razón hemos extraído las imágenes mediante un script en Ruby y las incorporamos al proyecto como png’s. Podéis <a href="http://www.migueldiazrubio.com/wp-content/uploads/2013/05/Imagenes.zip">descargar estas imágenes y algunas más que pueden ser útiles aquí</a>.</p>
<p>Si hemos seguido todos estos pasos en el <strong>Interface Builder</strong> y sin tirar una sola linea de código, al arrancar la aplicación en el simulador veremos algo como esto:</p>
<p><a href="http://www.migueldiazrubio.com/wp-content/uploads/2013/05/Captura-de-pantalla-de-Simulador-iOS-07.05.2013-01.53.58.png"><img class="alignnone  wp-image-1205" alt="Captura de pantalla de Simulador iOS 07.05.2013 01.53.58" src="http://www.migueldiazrubio.com/wp-content/uploads/2013/05/Captura-de-pantalla-de-Simulador-iOS-07.05.2013-01.53.58.png" width="461" height="614" /></a></p>
<p>No está mal, ¿no? Ahora si que hay que empezar a programar un poco. <img src='http://www.migueldiazrubio.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Modificamos el fichero .h de nuestro <strong>viewController</strong> para que quede de la siguiente manera:</p>

<div class="wp_codebox"><table><tr id="p119518"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code" id="p1195code18"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &amp;lt;UIKit/UIKit.h&amp;gt;</span>
&nbsp;
<span style="color: #a61390;">@interface</span> ZNKViewController <span style="color: #002200;">:</span> UIViewController <span style="color: #002200;">&amp;</span>lt;UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout<span style="color: #002200;">&amp;</span>gt;
&nbsp;
<span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>strong, nonatomic<span style="color: #002200;">&#41;</span> IBOutlet UISegmentedControl <span style="color: #002200;">*</span>levelControl;
<span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>strong, nonatomic<span style="color: #002200;">&#41;</span> IBOutlet UIButton <span style="color: #002200;">*</span>mainButton;
<span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>strong, nonatomic<span style="color: #002200;">&#41;</span> IBOutlet UICollectionView <span style="color: #002200;">*</span>collectionView;
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>IBAction<span style="color: #002200;">&#41;</span>levelChanged<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>sender;
&nbsp;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>

<p>¿Qué hemos hecho? Hemos incluido los protocolos del <strong>UICollectionView</strong> que nos permitirán controlar sus eventos, su contenido así como la distribución de sus elementos. Esto implica que en el <strong>Interface Builder</strong> hemos tenido que conectar los outlet <em>dataSource</em> y <em>delegate</em> al <strong>viewController</strong>:</p>
<p><a href="http://www.migueldiazrubio.com/wp-content/uploads/2013/05/Captura-de-pantalla-2013-05-07-a-las-02.16.15.png"><img class="alignnone size-full wp-image-1201" alt="Captura de pantalla 2013-05-07 a la(s) 02.16.15" src="http://www.migueldiazrubio.com/wp-content/uploads/2013/05/Captura-de-pantalla-2013-05-07-a-las-02.16.15.png" width="312" height="184" /></a></p>
<p>&nbsp;</p>
<p>También hemos incluido tres <strong>IBOutlet</strong>: el <strong>UISegmentedControl</strong>, el <strong>UIButton</strong> y el <strong>UICollectionView</strong>. Para saber cuando se produce un cambio de nivel hemos creado el método <code>-(IBAction)levelChanged:(id)sender</code> vinculado al ValueChanged del <strong>UISegmentedButton</strong>.</p>
<p><a href="http://www.migueldiazrubio.com/wp-content/uploads/2013/05/Captura-de-pantalla-2013-05-07-a-las-02.16.34.png"><img class="alignnone size-full wp-image-1202" alt="Captura de pantalla 2013-05-07 a la(s) 02.16.34" src="http://www.migueldiazrubio.com/wp-content/uploads/2013/05/Captura-de-pantalla-2013-05-07-a-las-02.16.34.png" width="315" height="396" /></a></p>
<h2>Llenando el UICollectionView</h2>
<p>Tal y como nos ha contado Miguel, el componente <strong>UICollectionView</strong> es muy semejante al clásico <strong>UITableView</strong>. Ahora vamos a comprobar in situ lo sencillo que es.</p>
<p>Lo primero que vamos a hacer es crear una subclase de <strong>UICollectionViewCell</strong> para nuestra celda. Esto nos va resultar muy útil cuando vayamos a cargar las imágenes o cuando vayamos a hacer alguna transición animada. Bastará con crear las propiedades correspondientes a cada <strong>UIImageView</strong>:</p>

<div class="wp_codebox"><table><tr id="p119519"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
</pre></td><td class="code" id="p1195code19"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &amp;lt;UIKit/UIKit.h&amp;gt;</span>
&nbsp;
<span style="color: #a61390;">@interface</span> ZNKMemoryCell <span style="color: #002200;">:</span> UICollectionViewCell
&nbsp;
<span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>strong, nonatomic<span style="color: #002200;">&#41;</span> IBOutlet UIImageView <span style="color: #002200;">*</span>secretImageView;
<span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>strong, nonatomic<span style="color: #002200;">&#41;</span> IBOutlet UIImageView <span style="color: #002200;">*</span>coverImageView;
&nbsp;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>

<p>Ahora vamos a cargar los datos en el <strong>UICollectionView</strong>, tal y como ha contado Miguel, tendremos que incluir los métodos &#8211; (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section, &#8211; (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView y &#8211; (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath</p>
<p>El número de elementos que contendrá el grid vendrá determinado por el nivel de dificultad que haya seleccionado el jugador. Para que no haya un número impar de elementos, el número de elementos por lado deberá ser par. Es decir, queremos tener matrices de 2&#215;2 (dos parejas), 4&#215;4 (ocho parejas), 6&#215;6 (dieciocho parejas),… Según esto, la relación entre la dificultad y el número de elementos viene dada por la expresión ((n + 1)*2)^2) donde n es la dificultad que va de 0 a n.</p>
<p>Incluimos el siguiente código en nuestro <strong>ZNKViewController.m</strong>:</p>

<div class="wp_codebox"><table><tr id="p119520"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
</pre></td><td class="code" id="p1195code20"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#pragma mark - UICollectionView Data Source Methods</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>NSInteger<span style="color: #002200;">&#41;</span>collectionView<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UICollectionView <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>collectionView numberOfItemsInSection<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>NSInteger<span style="color: #002200;">&#41;</span>section
<span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">return</span> <a href="http://www.opengroup.org/onlinepubs/009695399/functions/pow.html"><span style="color: #a61390;">pow</span></a><span style="color: #002200;">&#40;</span><span style="color: #002200;">&#40;</span>_levelControl.selectedSegmentIndex <span style="color: #002200;">+</span> <span style="color: #2400d9;">1</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">*</span> <span style="color: #2400d9;">2</span>, <span style="color: #2400d9;">2</span><span style="color: #002200;">&#41;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>NSInteger<span style="color: #002200;">&#41;</span>numberOfSectionsInCollectionView<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UICollectionView <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>collectionView
<span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">return</span> <span style="color: #2400d9;">1</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>UICollectionViewCell <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>collectionView<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UICollectionView <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>collectionView cellForItemAtIndexPath<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSIndexPath_Class/"><span style="color: #400080;">NSIndexPath</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>indexPath
<span style="color: #002200;">&#123;</span>
    <span style="color: #11740a; font-style: italic;">// we're going to use a custom UICollectionViewCell, which will hold an image and its label</span>
    <span style="color: #11740a; font-style: italic;">//</span>
    ZNKMemoryCell <span style="color: #002200;">*</span>cell <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>collectionView dequeueReusableCellWithReuseIdentifier<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;collectionViewCell&quot;</span> forIndexPath<span style="color: #002200;">:</span>indexPath<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// make the cell's title the actual NSIndexPath value</span>
    cell.coverImageView.image <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>UIImage imageNamed<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;105.png&quot;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #a61390;">return</span> cell;
&nbsp;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Este código tiene que ser superfamiliar para todos aquellas que hayan cargado una <strong>UITableView</strong>. Tenemos una única sección. En esa única sección tenemos un numero de celdas que viene determinado por la dificultad del juego y en cada celda incluimos una enigmática imagen.</p>
<p>A continuación, vamos a definir el tamaño de las celdas. Para eso incorporaremos los siguientes métodos: sizeForItemAtIndexPath, minimumInteritemSpacingForSectionAtIndex, minimumLineSpacingForSectionAtIndex.</p>
<p>Tal y como hemos comentado antes, el número de celdas por lado es un valor que depende del nivel de dificultad por lo que la forma más sencilla de calcular el tamaño de la celda es dividir el ancho del <strong>UICollectionView</strong> por el número de celdas que hay en cada lado. Como en el <strong>storyboard</strong> ya hemos dejado unos margenes entre celdas al hacer las imágenes más pequeñas que la celda en si no es necesario definir un espacio entre celdas. Al tener una sola sección tampoco tenemos necesidad de definir un espacio entre secciones. Dicho lo cual incluimos el siguiente código en nuestro <strong>viewController</strong>:</p>

<div class="wp_codebox"><table><tr id="p119521"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
</pre></td><td class="code" id="p1195code21"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#pragma mark – UICollectionViewDelegateFlowLayout</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>CGSize<span style="color: #002200;">&#41;</span>collectionView<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UICollectionView <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>collectionView layout<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UICollectionViewLayout<span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>collectionViewLayout sizeForItemAtIndexPath<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSIndexPath_Class/"><span style="color: #400080;">NSIndexPath</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>indexPath <span style="color: #002200;">&#123;</span>
&nbsp;
    <span style="color: #a61390;">int</span> screenWidth <span style="color: #002200;">=</span> _collectionView.bounds.size.width;
&nbsp;
    NSInteger width <span style="color: #002200;">=</span> screenWidth <span style="color: #002200;">/</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#40;</span>_levelControl.selectedSegmentIndex <span style="color: #002200;">+</span> <span style="color: #2400d9;">1</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">*</span> <span style="color: #2400d9;">2</span><span style="color: #002200;">&#41;</span>;
&nbsp;
    CGSize cellSize <span style="color: #002200;">=</span> CGSizeMake<span style="color: #002200;">&#40;</span>width, width<span style="color: #002200;">&#41;</span>;
&nbsp;
    <span style="color: #a61390;">return</span> cellSize;
&nbsp;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>CGFloat<span style="color: #002200;">&#41;</span>collectionView<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UICollectionView <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>collectionView layout<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UICollectionViewLayout<span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>collectionViewLayout minimumInteritemSpacingForSectionAtIndex<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>NSInteger<span style="color: #002200;">&#41;</span>section
<span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">return</span> <span style="color: #2400d9;">0</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>CGFloat<span style="color: #002200;">&#41;</span>collectionView<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UICollectionView <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>collectionView layout<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UICollectionViewLayout<span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>collectionViewLayout minimumLineSpacingForSectionAtIndex<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>NSInteger<span style="color: #002200;">&#41;</span>section
<span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">return</span> <span style="color: #2400d9;">0</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Y para terminar con el <strong>UICollectionView</strong>, aunque no vamos a utilizarlo todavía, incluimos el método que nos permite detectar las interacciones con las celdas:</p>

<div class="wp_codebox"><table><tr id="p119522"><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code" id="p1195code22"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#pragma mark - UICollectionView Delegate</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>collectionView<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UICollectionView <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>collectionView didSelectItemAtIndexPath<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSIndexPath_Class/"><span style="color: #400080;">NSIndexPath</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>indexPath
<span style="color: #002200;">&#123;</span>
&nbsp;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Antes de ejecutar la aplicación en el simulador para ver el resultado, vamos a incluir una recarga completa del <strong>UICollectionView</strong> cada vez que cambie el nivel de dificultad:</p>

<div class="wp_codebox"><table><tr id="p119523"><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code" id="p1195code23"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>IBAction<span style="color: #002200;">&#41;</span>levelChanged<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>sender <span style="color: #002200;">&#123;</span>
&nbsp;
    <span style="color: #002200;">&#91;</span>_collectionView reloadData<span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Ahora sí. Ejecutamos la aplicación en el simulador, deberíamos ver algo como esto:</p>
<p><a href="http://www.migueldiazrubio.com/wp-content/uploads/2013/05/Captura-de-pantalla-de-Simulador-iOS-08.05.2013-00.07.26.png"><img class="alignnone  wp-image-1206" alt="Captura de pantalla de Simulador iOS 08.05.2013 00.07.26" src="http://www.migueldiazrubio.com/wp-content/uploads/2013/05/Captura-de-pantalla-de-Simulador-iOS-08.05.2013-00.07.26.png" width="461" height="614" /></a></p>
<p>&nbsp;</p>
<p>Esto tiene buena pinta, ¿eh? <a href="http://www.migueldiazrubio.com/wp-content/uploads/2013/05/Memorion-Intermedio.zip">aquí puedes descargar una versión del proyecto en este punto</a>.</p>
<h2>El motor del juego</h2>
<p>Vamos a <a href="http://www.migueldiazrubio.com/2013/03/19/snippets-ios-crear-una-clase-de-tipo-singleton/" target="_blank">crear una clase con el patrón Singleton</a> para gestionar toda la lógica del juego. ¿Por qué un singleton? porque solo es necesaria una instancia del motor del juego en todo momento. De esta forma, si decidimos reiniciar la partida, cambiar el nivel, cambiar las imágenes, etc tendremos siempre de hacerlo en la única instancia del juego que hay disponible.</p>
<p>El contenido inicial de esta clase será el siguiente:</p>
<h4>ZNKMemoryGame.h</h4>

<div class="wp_codebox"><table><tr id="p119524"><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code" id="p1195code24"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &amp;lt;Foundation/Foundation.h&amp;gt;</span>
&nbsp;
<span style="color: #a61390;">@interface</span> ZNKMemoryGame <span style="color: #002200;">:</span> <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/"><span style="color: #400080;">NSObject</span></a>
&nbsp;
    <span style="color: #002200;">+</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>sharedInstance;
&nbsp;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>

<h4>ZNKMemoryGame.m</h4>

<div class="wp_codebox"><table><tr id="p119525"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
</pre></td><td class="code" id="p1195code25"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &quot;ZNKMemoryGame.h&quot;</span>
&nbsp;
<span style="color: #a61390;">@implementation</span> ZNKMemoryGame
&nbsp;
<span style="color: #002200;">+</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>sharedInstance <span style="color: #002200;">&#123;</span>
   <span style="color: #a61390;">static</span> ZNKMemoryGame <span style="color: #002200;">*</span>sharedInstance <span style="color: #002200;">=</span> <span style="color: #a61390;">nil</span>;
   <span style="color: #a61390;">static</span> dispatch_once_t onceToken;
   dispatch_once<span style="color: #002200;">&#40;</span><span style="color: #002200;">&amp;</span>amp;onceToken, <span style="color: #002200;">^</span><span style="color: #002200;">&#123;</span>
       sharedInstance <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>self alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
   <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#41;</span>;
   <span style="color: #a61390;">return</span> sharedInstance;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>init <span style="color: #002200;">&#123;</span>
   <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>self <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>super init<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
&nbsp;
   <span style="color: #002200;">&#125;</span>
   <span style="color: #a61390;">return</span> self;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>

<p>Los elementos que se van a mostrar en el <strong>UICollectionView</strong> los almacenaremos en una <strong>NSArray</strong> que llamaremos <strong>arrayOfItems</strong>, también necesitaremos un array donde llevar el control de las parejas que hemos encontrado (<strong>arrayOfDiscovered</strong>) y otro array para saber si estamos en búsqueda activa de pareja. Ya hemos visto que el nivel del juego es un elemento indispensable para determinar el número de elementos a mostrar en el <strong>CollectionView</strong> por lo que también será necesario una variable de tipo entero que almacene el nivel seleccionado: level.</p>
<p>Cada vez que queramos empezar una partida nueva o cambiemos el nivel del juego, habrá que inicializar los <em>arrays</em> a los valores por defecto: necesitaremos un método &#8211; (void)newGameWithLevel:(int)level; que se encargue de esta operación.</p>
<p>Teniendo todo esto en cuenta, actualizamos nuestro fichero ZNKMemoryGame.h:</p>

<div class="wp_codebox"><table><tr id="p119526"><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code" id="p1195code26"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>strong, nonatomic<span style="color: #002200;">&#41;</span> <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/"><span style="color: #400080;">NSMutableArray</span></a> <span style="color: #002200;">*</span>arrayOfItems;
<span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>strong, nonatomic<span style="color: #002200;">&#41;</span> <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/"><span style="color: #400080;">NSMutableArray</span></a> <span style="color: #002200;">*</span>arrayOfSelected;
<span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>strong, nonatomic<span style="color: #002200;">&#41;</span> <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/"><span style="color: #400080;">NSMutableArray</span></a> <span style="color: #002200;">*</span>arrayOfDiscovered;
<span style="color: #a61390;">@property</span> <span style="color: #a61390;">int</span> level;
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>newGameWithLevel<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">int</span><span style="color: #002200;">&#41;</span>level;</pre></td></tr></table></div>

<p>y nuestro fichero ZNKMemoryGame.m:</p>

<div class="wp_codebox"><table><tr id="p119527"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
</pre></td><td class="code" id="p1195code27"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>init <span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>self <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>super init<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        _level <span style="color: #002200;">=</span> <span style="color: #2400d9;">1</span>;
        <span style="color: #002200;">&#91;</span>self newGameWithLevel<span style="color: #002200;">:</span>_level<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">return</span> self;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #6e371a;">#pragma mark - Metodos para la gestión de los arrays</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>newGameWithLevel<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">int</span><span style="color: #002200;">&#41;</span>level
<span style="color: #002200;">&#123;</span>
    _level <span style="color: #002200;">=</span> level;
    <span style="color: #a61390;">int</span> numberOfItems <span style="color: #002200;">=</span> <a href="http://www.opengroup.org/onlinepubs/009695399/functions/pow.html"><span style="color: #a61390;">pow</span></a><span style="color: #002200;">&#40;</span><span style="color: #002200;">&#40;</span><span style="color: #002200;">&#40;</span>_level <span style="color: #002200;">+</span> <span style="color: #2400d9;">1</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">*</span> <span style="color: #2400d9;">2</span><span style="color: #002200;">&#41;</span>, <span style="color: #2400d9;">2</span><span style="color: #002200;">&#41;</span>;
&nbsp;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span>_arrayOfDiscovered<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        _arrayOfDiscovered <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/"><span style="color: #400080;">NSMutableArray</span></a> alloc<span style="color: #002200;">&#93;</span> initWithCapacity<span style="color: #002200;">:</span><span style="color: #2400d9;">0</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #002200;">&#91;</span>_arrayOfDiscovered removeAllObjects<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">int</span> i <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>; i <span style="color: #002200;">&amp;</span>lt; numberOfItems; i<span style="color: #002200;">++</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #002200;">&#91;</span>_arrayOfDiscovered addObject<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;NO&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span>_arrayOfSelected<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        _arrayOfSelected <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/"><span style="color: #400080;">NSMutableArray</span></a> alloc<span style="color: #002200;">&#93;</span> initWithCapacity<span style="color: #002200;">:</span><span style="color: #2400d9;">0</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #002200;">&#91;</span>_arrayOfSelected removeAllObjects<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span>_arrayOfItems<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        _arrayOfItems <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/"><span style="color: #400080;">NSMutableArray</span></a> alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #002200;">&#91;</span>_arrayOfItems removeAllObjects<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">int</span> i <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>; i <span style="color: #002200;">&amp;</span>lt; numberOfItems <span style="color: #002200;">/</span> <span style="color: #2400d9;">2</span> ; i<span style="color: #002200;">++</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #002200;">&#91;</span>_arrayOfItems addObject<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>UIImage imageNamed<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> stringWithFormat<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%i.png&quot;</span>, i<span style="color: #002200;">+</span><span style="color: #2400d9;">1</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #002200;">&#91;</span>_arrayOfItems addObjectsFromArray<span style="color: #002200;">:</span>_arrayOfItems<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>self shuffle<span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>shuffle
<span style="color: #002200;">&#123;</span>
    NSUInteger count <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>_arrayOfItems count<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span>NSUInteger i <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>; i <span style="color: #002200;">&amp;</span>lt; count; <span style="color: #002200;">++</span>i<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #11740a; font-style: italic;">// Select a random element between i and end of array to swap with.</span>
        NSInteger nElements <span style="color: #002200;">=</span> count <span style="color: #002200;">-</span> i;
        NSInteger n <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span>arc4random<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">%</span> nElements<span style="color: #002200;">&#41;</span> <span style="color: #002200;">+</span> i;
        <span style="color: #002200;">&#91;</span>_arrayOfItems exchangeObjectAtIndex<span style="color: #002200;">:</span>i withObjectAtIndex<span style="color: #002200;">:</span>n<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Venga, va, hemos hecho trampa. De repente hemos metido un chorizo de código importante. Aun así es bastante legible:</p>
<p>En el método <strong>init</strong> ya empezamos a usar propiedades y métodos que acabamos de crear: por defecto el nivel del juego será el 1 y con este nivel crearemos una nueva partida.</p>
<p>Al crear una nueva partida lo primero que haremos será determinar el número de elementos que va a contener el <strong>collectionView</strong> con una fórmula que ya nos suena de antes. A continuación se procede a la creación del <strong>arrayOfDiscovered</strong> en vacío si es que no está creado ya o la limpieza de todos los elementos si ya estuviera creado. Se carga con tantos noes como elementos tengamos que mostrar.</p>
<p>El <strong>arrayOfSelected</strong> se inicializa de forma análoga. En este caso no hay precarga ya que en eso consiste el juego, en ir cargando y limpiando este array.</p>
<p>La inicialización del <strong>arrayOfItems</strong> es la habitual. Lo llamativo aquí es la precarga: Las imágenes extraídas de la fuente <strong>Emoji</strong> que hemos incorporado al proyecto se llaman 1.png, 2.png, 3.png,… Por eso se carga este array con el nombre de la imagen correspondiente al indice más uno. Este <em>array</em> solo se llena hasta la mitad ya que la otra mitad deben ser exactamente las mismas imágenes que acabamos de cargar, por eso se añaden a este array todos los objetos que ya tiene.</p>
<p>Por último y para que el juego sea algo divertido, se desordena el <strong>arrayOfItems</strong> con el método &#8211; (void)shuffle.</p>
<p>Con lo que hemos incluido en el motor del juego hasta ahora ya podemos alimentar el <strong>collectionView</strong> del <strong>viewController</strong> de la aplicación, para ello hay que hacer los siguientes cambios:</p>

<div class="wp_codebox"><table><tr id="p119528"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
</pre></td><td class="code" id="p1195code28"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>viewDidLoad
<span style="color: #002200;">&#123;</span>
    <span style="color: #002200;">&#91;</span>super viewDidLoad<span style="color: #002200;">&#93;</span>;
    <span style="color: #11740a; font-style: italic;">// Do any additional setup after loading the view, typically from a nib.</span>
    _memoryGame <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>ZNKMemoryGame sharedInstance<span style="color: #002200;">&#93;</span>;
    _levelControl.selectedSegmentIndex <span style="color: #002200;">=</span> _memoryGame.level;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>IBAction<span style="color: #002200;">&#41;</span>levelChanged<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>sender <span style="color: #002200;">&#123;</span>
&nbsp;
    <span style="color: #002200;">&#91;</span>_memoryGame newGameWithLevel<span style="color: #002200;">:</span>_levelControl.selectedSegmentIndex<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>_collectionView reloadData<span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>NSInteger<span style="color: #002200;">&#41;</span>collectionView<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UICollectionView <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>collectionView numberOfItemsInSection<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>NSInteger<span style="color: #002200;">&#41;</span>section
<span style="color: #002200;">&#123;</span>
     <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span>_memoryGame.arrayOfItems count<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>CGSize<span style="color: #002200;">&#41;</span>collectionView<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UICollectionView <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>collectionView layout<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UICollectionViewLayout<span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>collectionViewLayout sizeForItemAtIndexPath<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSIndexPath_Class/"><span style="color: #400080;">NSIndexPath</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>indexPath <span style="color: #002200;">&#123;</span>
&nbsp;
    <span style="color: #a61390;">int</span> screenWidth <span style="color: #002200;">=</span> _collectionView.bounds.size.width;
&nbsp;
    NSInteger width <span style="color: #002200;">=</span> screenWidth <span style="color: #002200;">/</span> <a href="http://www.opengroup.org/onlinepubs/009695399/functions/sqrt.html"><span style="color: #a61390;">sqrt</span></a><span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>_memoryGame.arrayOfItems count<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>;
&nbsp;
     CGSize cellSize <span style="color: #002200;">=</span> CGSizeMake<span style="color: #002200;">&#40;</span>width, width<span style="color: #002200;">&#41;</span>;
&nbsp;
     <span style="color: #a61390;">return</span> cellSize;
&nbsp;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Si ejecutamos ahora la aplicación veremos que todo funciona igual que antes… pero seguimos sin poder jugar. Toca implementar la funcionalidad del juego.</p>
<h2>Busca la pareja</h2>
<p>El juego de buscar las parejas es un juego muy típico para niños y personas mayores que permite ejercitar la memoria. Consiste en poner un número determinado de cartas emparejadas boca abajo e ir dando la vuelta de dos en dos hasta encontrar una pareja. Si trasladamos estas reglas a nuestra aplicación veremos que tenemos que mostrar el contenido secreto de dos celdas, comprobar si son iguales y si lo son, marcarlas como acertadas. La selección de una celda se hace con el método delegado didSelectItemAtIndexPath, pero antes tenemos que incluir algún método más en nuestro motor:</p>

<div class="wp_codebox"><table><tr id="p119529"><td class="line_numbers"><pre>1
2
</pre></td><td class="code" id="p1195code29"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>cellAtIndexPathCanBeSelected<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSIndexPath_Class/"><span style="color: #400080;">NSIndexPath</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>indexPath;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>checkSelectionWithCompletion<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">^</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span> matched, <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a> <span style="color: #002200;">*</span>selectedCells<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>completion;</pre></td></tr></table></div>

<p>Un método para comprobar si nuestra celda puede ser seleccionada y un método que comprueba si se ha encontrado una pareja, método que además usa un bloque para informar, si se ha producido un <em>matching</em>, con que celdas ha sido. Este bloque lo usaremos para resaltar las celdas emparejadas.</p>

<div class="wp_codebox"><table><tr id="p119530"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
</pre></td><td class="code" id="p1195code30"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>cellAtIndexPathCanBeSelected<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSIndexPath_Class/"><span style="color: #400080;">NSIndexPath</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>indexPath
<span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>_arrayOfDiscovered objectAtIndex<span style="color: #002200;">:</span>indexPath.row<span style="color: #002200;">&#93;</span> isEqualToString<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;NO&quot;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #a61390;">return</span> <span style="color: #a61390;">YES</span>;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">return</span> <span style="color: #a61390;">NO</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>checkSelectionWithCompletion<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">^</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span>, <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>completion
<span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>_arrayOfSelected count<span style="color: #002200;">&#93;</span> <span style="color: #002200;">==</span> <span style="color: #2400d9;">2</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSIndexPath_Class/"><span style="color: #400080;">NSIndexPath</span></a> <span style="color: #002200;">*</span>firstSelection <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>_arrayOfSelected objectAtIndex<span style="color: #002200;">:</span><span style="color: #2400d9;">0</span><span style="color: #002200;">&#93;</span>;
        <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSIndexPath_Class/"><span style="color: #400080;">NSIndexPath</span></a> <span style="color: #002200;">*</span>secondSelection <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>_arrayOfSelected objectAtIndex<span style="color: #002200;">:</span><span style="color: #2400d9;">1</span><span style="color: #002200;">&#93;</span>;
        <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>_arrayOfItems objectAtIndex<span style="color: #002200;">:</span>firstSelection.row<span style="color: #002200;">&#93;</span> isEqual<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>_arrayOfItems objectAtIndex<span style="color: #002200;">:</span>secondSelection.row<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
            completion<span style="color: #002200;">&#40;</span><span style="color: #a61390;">YES</span>, _arrayOfSelected<span style="color: #002200;">&#41;</span>;
            <span style="color: #002200;">&#91;</span>_arrayOfSelected removeAllObjects<span style="color: #002200;">&#93;</span>;
            <span style="color: #002200;">&#91;</span>_arrayOfDiscovered replaceObjectAtIndex<span style="color: #002200;">:</span>firstSelection.row withObject<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;YES&quot;</span><span style="color: #002200;">&#93;</span>;
            <span style="color: #002200;">&#91;</span>_arrayOfDiscovered replaceObjectAtIndex<span style="color: #002200;">:</span>secondSelection.row withObject<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;YES&quot;</span><span style="color: #002200;">&#93;</span>;
            _totalDiscovered <span style="color: #002200;">+=</span> <span style="color: #2400d9;">2</span>;
            <span style="color: #002200;">&#91;</span>self reloadScoreLabel<span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#125;</span>
    <span style="color: #002200;">&#125;</span>
    completion<span style="color: #002200;">&#40;</span><span style="color: #a61390;">NO</span>, <span style="color: #a61390;">nil</span><span style="color: #002200;">&#41;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Ya casi hemos terminado. Solo nos falta empezar a usar estos métodos en el <strong>viewController</strong>:</p>

<div class="wp_codebox"><table><tr id="p119531"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
</pre></td><td class="code" id="p1195code31"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>UICollectionViewCell <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>collectionView<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UICollectionView <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>collectionView cellForItemAtIndexPath<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSIndexPath_Class/"><span style="color: #400080;">NSIndexPath</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>indexPath
<span style="color: #002200;">&#123;</span>
    ZNKMemoryCell <span style="color: #002200;">*</span>cell <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>collectionView dequeueReusableCellWithReuseIdentifier<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;collectionViewCell&quot;</span> forIndexPath<span style="color: #002200;">:</span>indexPath<span style="color: #002200;">&#93;</span>;
&nbsp;
    cell.coverImageView.image <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>UIImage imageNamed<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;105.png&quot;</span><span style="color: #002200;">&#93;</span>;
    cell.secretImageView.image <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>_memoryGame.arrayOfItems objectAtIndex<span style="color: #002200;">:</span>indexPath.row<span style="color: #002200;">&#93;</span>;
    cell.secretImageView.alpha <span style="color: #002200;">=</span> <span style="color: #2400d9;">0.0</span>;
    cell.coverImageView.alpha <span style="color: #002200;">=</span> <span style="color: #2400d9;">1.0</span>;
&nbsp;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>_memoryGame.arrayOfDiscovered objectAtIndex<span style="color: #002200;">:</span>indexPath.row<span style="color: #002200;">&#93;</span> isEqualToString<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;NO&quot;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        cell.backgroundColor <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>UIColor colorWithRed<span style="color: #002200;">:</span><span style="color: #2400d9;">102.0</span><span style="color: #002200;">/</span><span style="color: #2400d9;">255.0</span> green<span style="color: #002200;">:</span><span style="color: #2400d9;">102.0</span><span style="color: #002200;">/</span><span style="color: #2400d9;">255.0</span> blue<span style="color: #002200;">:</span><span style="color: #2400d9;">255.0</span><span style="color: #002200;">/</span><span style="color: #2400d9;">255.0</span> alpha<span style="color: #002200;">:</span><span style="color: #2400d9;">1</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #002200;">&#123;</span>
        cell.backgroundColor <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>UIColor redColor<span style="color: #002200;">&#93;</span>;
        cell.secretImageView.alpha <span style="color: #002200;">=</span> <span style="color: #2400d9;">1.0</span>;
        cell.coverImageView.alpha <span style="color: #002200;">=</span> <span style="color: #2400d9;">0.0</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
    <span style="color: #a61390;">return</span> cell;
&nbsp;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Al cargar el <strong>collectionView</strong> ya vamos a incluir la imagen secreta pero le pondremos un alpha de cero para que no se vea. En caso de que esté ya descubierta el <em>alpha</em> a cero lo tendrá la imagen con la interrogación y el fondo de la celda será de color rojo.</p>

<div class="wp_codebox"><table><tr id="p119532"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
</pre></td><td class="code" id="p1195code32"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#pragma mark - UICollectionView Delegate</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>collectionView<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UICollectionView <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>collectionView didSelectItemAtIndexPath<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSIndexPath_Class/"><span style="color: #400080;">NSIndexPath</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>indexPath
<span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>_memoryGame cellAtIndexPathCanBeSelected<span style="color: #002200;">:</span>indexPath<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>_memoryGame.arrayOfSelected count<span style="color: #002200;">&#93;</span> <span style="color: #002200;">==</span> <span style="color: #2400d9;">2</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
            <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSIndexPath_Class/"><span style="color: #400080;">NSIndexPath</span></a> <span style="color: #002200;">*</span>indexPathSelected <span style="color: #a61390;">in</span> _memoryGame.arrayOfSelected<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
                <span style="color: #002200;">&#91;</span>self hideTheShowedObjectAtIndexPath<span style="color: #002200;">:</span>indexPathSelected<span style="color: #002200;">&#93;</span>;
            <span style="color: #002200;">&#125;</span>
            <span style="color: #002200;">&#91;</span>_memoryGame.arrayOfSelected removeAllObjects<span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>_memoryGame.arrayOfSelected count<span style="color: #002200;">&#93;</span> <span style="color: #002200;">==</span> <span style="color: #2400d9;">1</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
            <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span><span style="color: #002200;">&#91;</span>indexPath isEqual<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>_memoryGame.arrayOfSelected objectAtIndex<span style="color: #002200;">:</span><span style="color: #2400d9;">0</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
                <span style="color: #002200;">&#91;</span>self showTheHidenObjectAtIndexPath<span style="color: #002200;">:</span>indexPath<span style="color: #002200;">&#93;</span>;
                <span style="color: #002200;">&#91;</span>_memoryGame.arrayOfSelected addObject<span style="color: #002200;">:</span>indexPath<span style="color: #002200;">&#93;</span>;
            <span style="color: #002200;">&#125;</span>
        <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #002200;">&#123;</span>
            <span style="color: #002200;">&#91;</span>self showTheHidenObjectAtIndexPath<span style="color: #002200;">:</span>indexPath<span style="color: #002200;">&#93;</span>;
            <span style="color: #002200;">&#91;</span>_memoryGame.arrayOfSelected addObject<span style="color: #002200;">:</span>indexPath<span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#125;</span>
    <span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Al seleccionar tenemos que comprobar que la celda en cuestión pueda ser seleccionada. Si es así lo primero que comprobamos es que no tengamos ya dos celdas seleccionadas ya que, en ese caso, lo que hay que hacer es deseleccionarlas (ocultarlas). Si ya tenemos una seleccionada, verificamos que no se haya vuelto a seleccionar la misma y si no es así se muestra la imagen oculta.</p>
<p>Para ocultar y mostrar las imágenes vamos a utilizar unas sencillas animaciones cambiando el <em>alpha</em> de las imágenes lo que provocara una sensación de aparición/desaparición de las mismas.</p>

<div class="wp_codebox"><table><tr id="p119533"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
</pre></td><td class="code" id="p1195code33"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#pragma mark - Animated selections</span>
&nbsp;
<span style="color: #002200;">-</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>showTheHidenObjectAtIndexPath<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSIndexPath_Class/"><span style="color: #400080;">NSIndexPath</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>indexPath
<span style="color: #002200;">&#123;</span>
    ZNKMemoryCell <span style="color: #002200;">*</span>cell <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span>ZNKMemoryCell <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#91;</span>_collectionView cellForItemAtIndexPath<span style="color: #002200;">:</span>indexPath<span style="color: #002200;">&#93;</span>;
    cell.secretImageView.alpha <span style="color: #002200;">=</span> <span style="color: #2400d9;">0.0</span>;
    cell.coverImageView.alpha <span style="color: #002200;">=</span> <span style="color: #2400d9;">1.0</span>;
&nbsp;
    <span style="color: #002200;">&#91;</span>UIView animateWithDuration<span style="color: #002200;">:</span><span style="color: #2400d9;">0.5</span> animations<span style="color: #002200;">:^</span><span style="color: #002200;">&#123;</span>
        cell.secretImageView.alpha <span style="color: #002200;">=</span> <span style="color: #2400d9;">1.0</span>;
        cell.coverImageView.alpha <span style="color: #002200;">=</span> <span style="color: #2400d9;">0.0</span>;
    <span style="color: #002200;">&#125;</span> completion<span style="color: #002200;">:^</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span> finished<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #002200;">&#91;</span>_memoryGame checkSelectionWithCompletion<span style="color: #002200;">:^</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span> matched, <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a> <span style="color: #002200;">*</span>selectedCells<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
            <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>matched<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
                <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSIndexPath_Class/"><span style="color: #400080;">NSIndexPath</span></a> <span style="color: #002200;">*</span>cell <span style="color: #a61390;">in</span> selectedCells<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
                    <span style="color: #002200;">&#91;</span>self changeTheColorOfTheCellAtIndexPath<span style="color: #002200;">:</span>cell<span style="color: #002200;">&#93;</span>;
                <span style="color: #002200;">&#125;</span>
            <span style="color: #002200;">&#125;</span>
        <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>hideTheShowedObjectAtIndexPath<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSIndexPath_Class/"><span style="color: #400080;">NSIndexPath</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>indexPath
<span style="color: #002200;">&#123;</span>
    ZNKMemoryCell <span style="color: #002200;">*</span>cell <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span>ZNKMemoryCell <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#91;</span>_collectionView cellForItemAtIndexPath<span style="color: #002200;">:</span>indexPath<span style="color: #002200;">&#93;</span>;
    cell.secretImageView.alpha <span style="color: #002200;">=</span> <span style="color: #2400d9;">1.0</span>;
    cell.coverImageView.alpha <span style="color: #002200;">=</span> <span style="color: #2400d9;">0.0</span>;
&nbsp;
    <span style="color: #002200;">&#91;</span>UIView animateWithDuration<span style="color: #002200;">:</span><span style="color: #2400d9;">0.5</span> animations<span style="color: #002200;">:^</span><span style="color: #002200;">&#123;</span>
        cell.secretImageView.alpha <span style="color: #002200;">=</span> <span style="color: #2400d9;">0.0</span>;
        cell.coverImageView.alpha <span style="color: #002200;">=</span> <span style="color: #2400d9;">1.0</span>;
    <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Al mostrar las celdas verificaremos si las celdas que están descubiertas contienen la misma imagen, si esto es así, cambiaremos el color de fondo de la celda</p>

<div class="wp_codebox"><table><tr id="p119534"><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code" id="p1195code34"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>changeTheColorOfTheCellAtIndexPath<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSIndexPath_Class/"><span style="color: #400080;">NSIndexPath</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>indexPath
<span style="color: #002200;">&#123;</span>
    ZNKMemoryCell <span style="color: #002200;">*</span>cell <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span>ZNKMemoryCell <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#91;</span>_collectionView cellForItemAtIndexPath<span style="color: #002200;">:</span>indexPath<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>UIView animateWithDuration<span style="color: #002200;">:</span><span style="color: #2400d9;">0.25</span> animations<span style="color: #002200;">:^</span><span style="color: #002200;">&#123;</span>
        cell.backgroundColor <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>UIColor redColor<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#93;</span>;    
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<h2>A jugar</h2>
<p>Si hemos hecho todo correctamente y ejecutamos la aplicación tendremos un juego de encontrar parejas con el que entretener a hijos, sobrinos, etc. Si además retocáis un poquito más el <strong>storyboard</strong> que habíamos hecho tendréis algo como esto:</p>
<p><img class="alignnone  wp-image-1208" alt="Captura de pantalla de Simulador iOS 11.05.2013 03.43.19" src="http://www.migueldiazrubio.com/wp-content/uploads/2013/05/Captura-de-pantalla-de-Simulador-iOS-11.05.2013-03.43.19.png" width="461" height="614" /></p>
<p>El <strong>código fuente</strong> del proyecto terminado lo podéis <a href="http://www.migueldiazrubio.com/wp-content/uploads/2013/05/Memorion-Final.zip">descargar de aquí</a>.</p>
<p><div class='et-box et-info'>
					<div class='et-box-content'><b>Atribuciones:<b>
La idea del juego está sacada de un programa de ejemplo de la aplicación <a href="https://itunes.apple.com/es/app/pythonista/id528579881?mt=8" target="_blank"><b>Phytonista</b></a>, las imágenes de la fuente Emoji se han extraído con un script de Ruby: <a href="https://github.com/tmm1/emoji-extractor/blob/master/emoji_extractor.rb" target="_blank">emoji_extractor.rb</a>.</div></div> </b></b></p>
<div class='et-box et-shadow'>
					<div class='et-box-content'><b>Javier Moreno</b></p>
<p>Me dedico al desarrollo de software de forma profesional desde 2003. En mis ratos libres estoy aprendiendo a desarrollar aplicaciones para dispositivos iOS, como tantos otros lo hago desde que me compre un iPhone 3G. <img src='http://www.migueldiazrubio.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />
Para contactar conmigo, la mejor forma de hacerlo es en Twitter. Si os interesa el mundo del desarrollo, la tecnología y no os importa leer chorradas, seguid a <a href="http://www.twitter.com/jmoreno78" target="_blank">@jmoreno78</a>. De vez en cuando me pongo un poco más
serio y escribo en <a href="http://javi.zinkinapps.com" target="_blank">http://javi.zinkinapps.com</a>.</div></div>
</div>
</div>
<div class="ptl_div"><a href="http://twitter.com/share" class="twitter-share-button" data-url="http://www.migueldiazrubio.com/2013/05/17/desarrollo-ios-primeros-pasos-con-uicollectionview-parte-ii/" data-text="Desarrollo iOS: Primeros pasos con UICollectionView (parte II)" data-count="horizontal">Tweet</a></div>
<p>The post <a href="http://www.migueldiazrubio.com/2013/05/17/desarrollo-ios-primeros-pasos-con-uicollectionview-parte-ii/">Desarrollo iOS: Primeros pasos con UICollectionView (parte II)</a> appeared first on <a href="http://www.migueldiazrubio.com">Miguel Diaz Rubio</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://www.migueldiazrubio.com/2013/05/17/desarrollo-ios-primeros-pasos-con-uicollectionview-parte-ii/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Desarrollo iOS: Primeros pasos con UICollectionView (parte I)</title>
		<link>http://www.migueldiazrubio.com/2013/05/14/desarrollo-ios-primeros-pasos-con-uicollectionview-parte-i/</link>
		<comments>http://www.migueldiazrubio.com/2013/05/14/desarrollo-ios-primeros-pasos-con-uicollectionview-parte-i/#comments</comments>
		<pubDate>Tue, 14 May 2013 08:00:25 +0000</pubDate>
		<dc:creator>migueldiazrubio</dc:creator>
				<category><![CDATA[Desarrollo iOS]]></category>

		<guid isPermaLink="false">http://www.migueldiazrubio.com/?p=1023</guid>
		<description><![CDATA[<p>Vamos a aprender todos los conceptos teoricos y práctic [...]</p><p>The post <a href="http://www.migueldiazrubio.com/2013/05/14/desarrollo-ios-primeros-pasos-con-uicollectionview-parte-i/">Desarrollo iOS: Primeros pasos con UICollectionView (parte I)</a> appeared first on <a href="http://www.migueldiazrubio.com">Miguel Diaz Rubio</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>Vamos a aprender todos los conceptos teoricos y prácticos para aplicar desde ya <strong>UICollectionView</strong> en nuestras aplicaciones. Una forma muy versátil y visual de presentar grandes cantidades de datos.</p>
<p><span id="more-1023"></span></p>
<h2>Introducción</h2>
<p>Apple lanza con <strong>iOS 6</strong> una gran novedad para <strong>UIKit</strong>, que son las <strong>UICollectionView</strong>. Según ellos mismos indican, su objetivo es dotar al desarrollador de nuevos mecanismos para mostrar grandes cantidades de información de forma más versátil que las actuales <strong>UITableView</strong>.</p>
<p>Una <strong>UICollectionView</strong> esta estructurada inicialmente en filas y columnas, aunque es posible definir formas de presentación a medida, como presentación circular de elementos como si de una ruleta se tratase, y todo aquello que nos permita nuestra imaginación.</p>
<p>Básicamente una <strong>UICollectionView</strong> esta compuesta por los siguientes elementos:</p>
<ul>
<li><strong><span style="line-height: 13px;">Items</span></strong></li>
<li><strong>Supplementary Views:</strong> inicialmente pensadas para definir cabeceras para las diferentes sections de nuestra <strong>UICollectionView</strong>.</li>
<li><strong>Decoration Views:</strong> las cuales nos permiten configurar elementos adicionales a los items, como el fondo de la <strong>UICollectionView</strong> y otros.</li>
</ul>
<h2>Rellenar los datos de la UICollectionView</h2>
<p>Para nutrir de contenido nuestro <strong>UICollectionView</strong> tenemos el protocolo <strong>UICollectionViewDataSource</strong>:</p>
<ul>
<li><span style="line-height: 13px;"><strong>numberOfSectionsInCollectionView:</strong> si no se implementa se asume que solo hay 1 sección.</span></li>
<li><strong>collectionView:numberOfItemsInSection:</strong> para cada sección se llamará a este método.</li>
<li><strong>collectionView:cellForItemAtIndexPath:</strong> que configurará cada item antes de mostrarlo. Únicamente nos debemos encargar de qué mostrar en cada item, no de donde se muestra el item en cuestión.</li>
</ul>
<p>El concepto de reutilización de celdas también se aplica a las vistas en si mismas (<strong>dequeueReusableCellWithReuseIdentifier</strong> y <strong>dequeueReusableSupplementaryViewOfKind</strong>). Además, para el que se lo haya perdido, desde <strong>iOS 6</strong> ya no es necesario en <strong>UITableView</strong> ni <strong>UICollectionView</strong> comprobar si al recuperar un item reusable nos ha devuelto <strong>nil</strong>, ahora en ese caso nos genera un nuevo item.</p>
<h2>Interactuar con la UICollectionView</h2>
<p>Para interactuar con la <strong>UICollectionView</strong> tenemos el protocolo <strong>UICollectionViewDelegate</strong> que controla los siguientes comportamientos:</p>
<ul>
<li><span style="line-height: 13px;">Hightlight de un item</span></li>
<li>Selección de un item</li>
<li>Menú secundario</li>
</ul>
<p>Para gestionar estos estados de highlighting y selection tenemos dos propiedades <em>BOOL</em>, <strong>selected</strong> y <strong>highlighted</strong>.</p>
<p>Cuando el usuario pulsa un item, se ejecuta el método <strong>shouldHighlightItemAtIndexPath</strong>. Si devuelve NO, se interrumpe el proceso de selección del item, y en caso de que devuelva YES, se invoca al método <strong>didHighlightItemAtIndexPath</strong> dejando la propiedad <strong>hightlight</strong> a YES.</p>
<p>Una vez que el usuario separa el dedo del item seleccionado (<em>touch up inside</em>), se ejecuta el método <strong>shouldSelectItemAtIndexPath</strong>. Si se devuelve YES, se marca la propiedad <strong>selected</strong> como YES, de nuevo se cambia el valor de <strong>highlighted</strong> a NO, y se invoca al método <strong>didSelectItemAtIndexPath</strong>.</p>
<p>En el caso de la de-selección ocurre la misma secuencia que en la selección pero con los correspondientes métodos.</p>
<p>Algo muy interesante a comentar, es que cuando un item se marca como selected o hightlighted, el <strong>UICollectionView</strong> navegará por todo el árbol de vistas que componen dicho item, y si alguna de ellas implementa los métodos <strong>setSelected</strong> o <strong>setHightlighted</strong>, éstos serán ejecutados automáticamente. Esto nos permite establecer comportamientos especificos de los elementos que componen un item para los estados de highlight y selected sin encargarnos de dicha gestión.</p>
<h2>Estilos de la UICollectionView</h2>
<p>En el caso de <strong>UICollectionView</strong> no existen estilos por defecto para los items, tal y como ocurre con las <strong>UITableView </strong>(<em>Basic, Subtitle, Left detail</em> y <em>Right detail</em>). Sin embargo, incluye algunas funcionalidades interesantes como son: <strong>background view</strong> y <strong>selected background</strong>, que permiten configurar un fondo del item dependiendo del estado del mismo. Dicho cambio se realiza automáticamente sin tener que implementar ningún código, solo definir ambas vistas para sus fondos.</p>
<h2>Jerarquía de vistas de una UICollectionViewCell</h2>
<p>Como supongo que habréis intuido, cada un de los items que componen un <strong>UICollectionView</strong> son objetos de tipo <strong>UICollectionViewCell</strong>.</p>
<p>La jerarquía de vistas de una <strong>UICollectionViewCell</strong> es la siguiente:</p>
<ul>
<li><span style="line-height: 13px;"><strong>UICollectionViewCell:</strong> es el propio item.</span></li>
<li><strong>Background View:</strong> es la vista que compone el fondo de nuestro item por defecto.</li>
<li><strong>Selected Background View:</strong> es la vista que compone el fonde de nuestro item cuando éste se encuentra seleccionado.</li>
<li><strong>Content View:</strong> es la vista que contiene todos los elementos que conforman la interfaz de la misma, como puedan ser <em>UILabels</em>, <em>UITextView</em>, <em>UIImageView</em>, etc.</li>
</ul>
<h2>UICollectionViewLayout (UICollectionViewFlowLayout)</h2>
<p>Todos los elementos anteriores, ya sean las vistas que componen cada item, como los metodos que debemos implementar para definir su aspecto y comportamiento, unicamente abarcan el <strong>cómo son</strong> los items de nuestra <strong>UICollectionView</strong>. Sin embargo, para definir el donde se muestran dichos items, debemos incorporar una nueva clase, que es <strong>UICollectionViewLayout</strong>.</p>
<p>Esta clase, y sus subclases, se encargan de definir como se distribuyen y organizan los items en nuestro <strong>UICollectionView</strong>.</p>
<p>Por defecto, <strong>iOS 6</strong> nos provee de una subclase de ésta denominada <strong>UICollectionViewFlowLayout</strong>, que basicamente se podría asemejar a lo que muestra la aplicación Fotos de <strong>iOS</strong>. Nos permite distribuir en modo rejilla, los diferentes items de que dispongamos gestionando automaticamente el espacio disponible para cada uno de ellos, independientemente de su tamaño. Es decir, que si considera que en una fila van a poder mostrarse 5 items y en otra fila por tratarse de items mas grandes solo 3, él se encargará de todo lo necesario.</p>
<p>Dentro de las opciones de configuración o personalización de <strong>UICollectionViewFlowLayout</strong> encontramos las siguientes:</p>
<ul>
<li><span style="line-height: 13px;"><strong>Tamaño de los items:</strong> puede configurarse a nivel global mediante la propiedad <strong>layout.itemSize</strong>, o bien a través del método <strong>sizeForItemAtIndexPath</strong> del protocolo.</span></li>
<li><strong>Espacio entre items (horizontal):</strong> donde podemos definir la distancia mínima entre items. Tambié n puede definirse a nivel global o a nivel sección a través de los métodos delegados <strong>minimumInteritemSpacingForSectionAtIndex</strong>.</li>
<li><strong>Espacio entre items (vertical):</strong> donde igualmente podemos defini la distancia mínima entre dos filas de items. También puede definirse a nivel global o a nivel sección a través de los métodos delegados <strong>minimumLineSpacingForSectionAtIndex</strong>.</li>
<li><strong>Dirección del scroll (vertical u horizontal)</strong></li>
<li><strong>Tamaño de la cabecera y pie: </strong>se pueden definir a nivel global mediante <strong>headerReferenceSize</strong> y <strong>footerReferenceSize</strong> o bien a través de los métodos delegados <strong>referenceSizeForHeaderInSection</strong> y <strong>referenceSizeForFooterInSection</strong>. El tamaño proporcionado es un <strong>CGSize</strong> con valores ancho y alto. Dependera de si nuestra colección esta en formato vertical u horizontal el que se utilice uno u otro valor.</li>
<li><strong>Padding entre secciones: </strong>podemos definir el espacio que queramos definir como margen o colchon alrededor de los items que componen uno de nuestras secciones.</li>
</ul>
<p>Los métodos delegados indicados anteriormente corresponden al protocolo <strong>UICollectionViewDelegateFlowLayout</strong> que básicamente es una subclase de <strong>UICollectionViewDelegate</strong>.</p>
<p>Si por cualquier motivo necesitamos una distribución totalmente diferente a lo ofrecido por <strong>UICollectionViewFlowLayout</strong>, podemos crear nuestra propia subclase de <strong>UICollectionViewLayout</strong>, pero eso lo dejo para los mas valientes, dado que no es algo sencillo.</p>
<h2>Práctica</h2>
<p>Para los que no os hayáis dormido y aún sigáis leyendo, en el próximo artículo podréis poner en práctica estos conceptos en un juego para niños de encontrar parejas utilizando <strong>UICollectionView</strong>, cortesía de un nuevo colaborador del blog, <strong>Javi Moreno </strong>(<a href="http://www.twitter.com/jmoreno78" target="_blank"><strong>@jmoreno78</strong></a>).</p>
<p>Podéis consultar el artículo en: <a href="http://www.migueldiazrubio.com/2013/05/17/desarrollo-ios-primeros-pasos-con-uicollectionview-parte-ii/"><b>Desarrollo iOS: Primeros pasos con UICollectionView (parte II)</b></a></p>
<p>¡Os esperamos en el próximo artículo!
<div class="ptl_div"><a href="http://twitter.com/share" class="twitter-share-button" data-url="http://www.migueldiazrubio.com/2013/05/14/desarrollo-ios-primeros-pasos-con-uicollectionview-parte-i/" data-text="Desarrollo iOS: Primeros pasos con UICollectionView (parte I)" data-count="horizontal">Tweet</a></div>
<p>The post <a href="http://www.migueldiazrubio.com/2013/05/14/desarrollo-ios-primeros-pasos-con-uicollectionview-parte-i/">Desarrollo iOS: Primeros pasos con UICollectionView (parte I)</a> appeared first on <a href="http://www.migueldiazrubio.com">Miguel Diaz Rubio</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://www.migueldiazrubio.com/2013/05/14/desarrollo-ios-primeros-pasos-con-uicollectionview-parte-i/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Desarrollo iOS: Accede a los calendarios con el framework EventKit</title>
		<link>http://www.migueldiazrubio.com/2013/05/10/desarrollo-ios-accede-a-los-calendarios-con-el-framework-eventkit/</link>
		<comments>http://www.migueldiazrubio.com/2013/05/10/desarrollo-ios-accede-a-los-calendarios-con-el-framework-eventkit/#comments</comments>
		<pubDate>Fri, 10 May 2013 08:00:04 +0000</pubDate>
		<dc:creator>migueldiazrubio</dc:creator>
				<category><![CDATA[Desarrollo iOS]]></category>

		<guid isPermaLink="false">http://www.migueldiazrubio.com/?p=1113</guid>
		<description><![CDATA[<p>Aprende a acceder a los eventos que el usuario tiene en [...]</p><p>The post <a href="http://www.migueldiazrubio.com/2013/05/10/desarrollo-ios-accede-a-los-calendarios-con-el-framework-eventkit/">Desarrollo iOS: Accede a los calendarios con el framework EventKit</a> appeared first on <a href="http://www.migueldiazrubio.com">Miguel Diaz Rubio</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>Aprende a acceder a los eventos que el usuario tiene en su calendario con <strong>EventKit</strong>, e incluso genera nuevos creando un calendario propio para tu aplicación.</p>
<p><span id="more-1113"></span></p>
<h2>Introducción</h2>
<p>Como ya comentábamos en el artículo <a href="http://www.migueldiazrubio.com/2013/05/03/desarrollo-ios-accede-a-los-contactos-con-el-framework-addressbook/" target="_blank"><strong>Desarrollo iOS: Accede a los contactos con el framework AddressBook</strong></a> anteriormente, desde la salida de <strong>iOS 6</strong>, Apple ha reforzado bastante la seguridad en lo referente al acceso a datos del usuario y su privacidad.</p>
<p>Hay ciertas cosas que nos va a permitir hacer <strong>Apple</strong> con respecto a los calendarios y que veremos con mas detalle durante el artículo:</p>
<ul>
<li><span style="line-height: 13px;">Acceder internamente, previa aceptación del usuario, a los diferentes calendarios disponibles y los eventos que contiene, dando incluso la posibilidad de crear eventos nuevos sin la intervención del usuario.</span></li>
<li>Editar eventos del usuario mediante la presentación en pantalla de los controladores propios de <strong>Apple</strong> para calendarios y donde el usuario debe realizar las acciones de edición y/o eliminación. Esta tarea no la hará el <em>EventKit.framework</em>, sino el <em>EventKitUI.framework</em>.</li>
<li>Crear un calendario propio para nuestra aplicación donde si podremos editar o eliminar eventos internamente sin mostrar <strong>UI</strong> al usuario.</li>
</ul>
<p>Como veis, en el momento en que queramos hacer edición o eliminación de eventos que no pertenecen al calendario propio de nuestra aplicación, <strong>Apple</strong> como es logico no nos lo va a permitir, obligándonos a presentar al usuario cuadros de dialogo pertenecientes a la aplicación <strong>Calendario</strong> donde será el usuario quien realice o no dicha acción. Esto, aunque quita libertad a los desarrolladores, nos protege a los usuarios frente a que por un error del programador de una aplicación que acabamos de bajar de la <strong>AppStore</strong>, se nos borren todas las reuniones que teníamos para esta semana.</p>
<h2>Solicitar acceso a EventKit</h2>
<p>Vamos a crear una nueva aplicación de tipo <strong>Single View Application</strong>, incluiremos los framework <strong>EventKit</strong> y <strong>EventKitUI</strong>, y crearemos un <strong>UIButton</strong>, tal y como hicimos en el anterior artículo, que tendrá un <strong>IBAction</strong> denominado <em>obtenerCalendarios</em>.</p>
<p>En segundo lugar y dado que vamos a utilizar esta variable a lo largo de varios métodos de nuestro controlador, vamos a crear una variable en la cabecera:</p>

<div class="wp_codebox"><table><tr id="p111339"><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code" id="p1113code39"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">@interface</span> ViewController <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
    EKEventStore <span style="color: #002200;">*</span>store;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>A continuación, debemos garantizar que cuando se carga nuestro controlador, dicha variable es instanciada. Para ello incluimos el siguiente código en el método <strong>viewDidLoad</strong> del controlador:</p>

<div class="wp_codebox"><table><tr id="p111340"><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code" id="p1113code40"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>viewDidLoad <span style="color: #002200;">&#123;</span>
    <span style="color: #002200;">&#91;</span>super viewDidLoad<span style="color: #002200;">&#93;</span>;
&nbsp;
    store <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>EKEventStore alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>A continuación vamos a ver cuales son los pasos que debemos seguir para poder solicitar acceso a los calendarios del usuario, y como hacer una consulta a dichos calendarios:</p>

<div class="wp_codebox"><table><tr id="p111341"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
</pre></td><td class="code" id="p1113code41"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>IBAction<span style="color: #002200;">&#41;</span>obtenerCalendarios <span style="color: #002200;">&#123;</span>
&nbsp;
    <span style="color: #002200;">&#91;</span>store requestAccessToEntityType<span style="color: #002200;">:</span>EKEntityTypeEvent completion<span style="color: #002200;">:^</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span> granted, <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSError_Class/"><span style="color: #400080;">NSError</span></a> <span style="color: #002200;">*</span>error<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
&nbsp;
        <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span>granted<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
&nbsp;
            dispatch_async<span style="color: #002200;">&#40;</span>dispatch_get_main_queue<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>, <span style="color: #002200;">^</span><span style="color: #002200;">&#123;</span>
&nbsp;
            <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UIAlertView alloc<span style="color: #002200;">&#93;</span> initWithTitle<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Error&quot;</span> message<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Acceso denegado&quot;</span> delegate<span style="color: #002200;">:</span>self cancelButtonTitle<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Ok&quot;</span> otherButtonTitles<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span> show<span style="color: #002200;">&#93;</span>;
&nbsp;
            <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#41;</span>;
&nbsp;
        <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #002200;">&#123;</span>
&nbsp;
            <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSCalendar_Class/"><span style="color: #400080;">NSCalendar</span></a> <span style="color: #002200;">*</span>calendar <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSCalendar_Class/"><span style="color: #400080;">NSCalendar</span></a> currentCalendar<span style="color: #002200;">&#93;</span>;
&nbsp;
            <span style="color: #11740a; font-style: italic;">// Creamos la fecha de inicio de nuestra consulta (hace un día)</span>
            <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSDateComponents_Class/"><span style="color: #400080;">NSDateComponents</span></a> <span style="color: #002200;">*</span>oneDayAgoComponents <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSDateComponents_Class/"><span style="color: #400080;">NSDateComponents</span></a> alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
            oneDayAgoComponents.day <span style="color: #002200;">=</span> <span style="color: #002200;">-</span><span style="color: #2400d9;">1</span>;
            <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSDate_Class/"><span style="color: #400080;">NSDate</span></a> <span style="color: #002200;">*</span>oneDayAgo <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>calendar dateByAddingComponents<span style="color: #002200;">:</span>oneDayAgoComponents
                                                          toDate<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSDate_Class/"><span style="color: #400080;">NSDate</span></a> date<span style="color: #002200;">&#93;</span>
                                                         options<span style="color: #002200;">:</span><span style="color: #2400d9;">0</span><span style="color: #002200;">&#93;</span>;
&nbsp;
            <span style="color: #11740a; font-style: italic;">// Creamos la fecha de fin de nuestra consulta (dentro de una semana)</span>
            <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSDateComponents_Class/"><span style="color: #400080;">NSDateComponents</span></a> <span style="color: #002200;">*</span>oneWeekFromNowComponents <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSDateComponents_Class/"><span style="color: #400080;">NSDateComponents</span></a> alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
            oneWeekFromNowComponents.week <span style="color: #002200;">=</span> <span style="color: #2400d9;">1</span>;
            <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSDate_Class/"><span style="color: #400080;">NSDate</span></a> <span style="color: #002200;">*</span>oneWeekFromNow <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>calendar dateByAddingComponents<span style="color: #002200;">:</span>oneWeekFromNowComponents
                                                               toDate<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSDate_Class/"><span style="color: #400080;">NSDate</span></a> date<span style="color: #002200;">&#93;</span>
                                                              options<span style="color: #002200;">:</span><span style="color: #2400d9;">0</span><span style="color: #002200;">&#93;</span>;
&nbsp;
            <span style="color: #11740a; font-style: italic;">// Creamos un predicate para poder hacer la consulta con los datos generados</span>
            <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSPredicate_Class/"><span style="color: #400080;">NSPredicate</span></a> <span style="color: #002200;">*</span>predicate <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>store predicateForEventsWithStartDate<span style="color: #002200;">:</span>oneDayAgo
                                                                    endDate<span style="color: #002200;">:</span>oneWeekFromNow
                                                                  calendars<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
&nbsp;
            <span style="color: #11740a; font-style: italic;">// Solicitamos al EKEventStore el listado de eventos que cumplen</span>
            <span style="color: #11740a; font-style: italic;">// el predicate indicado como parámetro</span>
            <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a> <span style="color: #002200;">*</span>events <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>store eventsMatchingPredicate<span style="color: #002200;">:</span>predicate<span style="color: #002200;">&#93;</span>;
&nbsp;
            <span style="color: #11740a; font-style: italic;">// Recorremos los eventos recuperados</span>
            <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span>EKEvent <span style="color: #002200;">*</span>evento <span style="color: #a61390;">in</span> events<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
&nbsp;
                <span style="color: #11740a; font-style: italic;">// Pintamos el título del evento</span>
                NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%@&quot;</span>,evento.title<span style="color: #002200;">&#41;</span>;
&nbsp;
            <span style="color: #002200;">&#125;</span>
&nbsp;
            <span style="color: #11740a; font-style: italic;">// Dado que nos encontramos en un bloque, debemos asegurarnos que las operaciones</span>
            <span style="color: #11740a; font-style: italic;">// relativas a UI se ejecutan en el hilo principal. Mostramos un mensaje</span>
            <span style="color: #11740a; font-style: italic;">// con el total de eventos para esta semana.</span>
            dispatch_async<span style="color: #002200;">&#40;</span>dispatch_get_main_queue<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>, <span style="color: #002200;">^</span><span style="color: #002200;">&#123;</span>
&nbsp;
                <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UIAlertView alloc<span style="color: #002200;">&#93;</span> initWithTitle<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Eventos&quot;</span> message<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> stringWithFormat<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Tienes %d eventos para esta semana&quot;</span>,<span style="color: #002200;">&#91;</span>events count<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span> delegate<span style="color: #002200;">:</span>self cancelButtonTitle<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Ok&quot;</span> otherButtonTitles<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span> show<span style="color: #002200;">&#93;</span>;
&nbsp;
            <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#41;</span>;
&nbsp;
        <span style="color: #002200;">&#125;</span>
    <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Como se puede ver, lo que hacemos es generar un objeto <strong>NSDate</strong> con la fecha del día de ayer, y otro objeto <strong>NSDate</strong> con la fecha de dentro de una semana. Invocando al <strong>Store</strong> mediante un predicado creado previamente con estos valores, obtenemos fácilmente toda la información. Recordar que al estar utilizando bloques, debemos garantizar que la ejecución de las operaciones relativas a <strong>UIKit</strong> se ejecutan en el hilo principal. Si no sabéis a que me estoy refiriendo con esto, os recomiendo echar un vistazo al artículo <a href="http://www.migueldiazrubio.com/2013/01/08/desarrollo-ios-6-blocks-y-gcd-grand-central-dispatch/" target="_blank"><strong>Desarrollo iOS: Blocks y GCD (Grand Central Dispatch)</strong></a>.</p>
<h2>Crear eventos en el calendario del usuario</h2>
<p>Aunque no es posible la edición o borrado de eventos del usuario, si es posible crear nuevos eventos en el calendario del usuario, siempre que el usuario autorice a nuestra aplicación a acceder a los calendario (tal y como hemos hecho en el ejemplo anterior).</p>
<p>Para ello, vamos a crear en nuestra espartana interfaz un nuevo botón, para el cual definiremos un <strong>IBAction</strong> denominado <em>crearEvento</em>.</p>
<p>En dicho método incorporaremos el siguiente código:</p>

<div class="wp_codebox"><table><tr id="p111342"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
</pre></td><td class="code" id="p1113code42"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>IBAction<span style="color: #002200;">&#41;</span>crearEvento <span style="color: #002200;">&#123;</span>
&nbsp;
    <span style="color: #002200;">&#91;</span>store requestAccessToEntityType<span style="color: #002200;">:</span>EKEntityTypeEvent completion<span style="color: #002200;">:^</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span> granted, <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSError_Class/"><span style="color: #400080;">NSError</span></a> <span style="color: #002200;">*</span>error<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
&nbsp;
        <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span>granted<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
&nbsp;
            dispatch_async<span style="color: #002200;">&#40;</span>dispatch_get_main_queue<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>, <span style="color: #002200;">^</span><span style="color: #002200;">&#123;</span>
&nbsp;
            <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UIAlertView alloc<span style="color: #002200;">&#93;</span> initWithTitle<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Error&quot;</span> message<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Acceso denegado&quot;</span> delegate<span style="color: #002200;">:</span>self cancelButtonTitle<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Ok&quot;</span> otherButtonTitles<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span> show<span style="color: #002200;">&#93;</span>;
&nbsp;
            <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#41;</span>;
&nbsp;
        <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #002200;">&#123;</span>
&nbsp;
            EKEvent <span style="color: #002200;">*</span>event <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>EKEvent eventWithEventStore<span style="color: #002200;">:</span>store<span style="color: #002200;">&#93;</span>;
&nbsp;
            <span style="color: #11740a; font-style: italic;">// Configuramos la información basica del evento que vamos a crear</span>
            event.calendar <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>store defaultCalendarForNewEvents<span style="color: #002200;">&#93;</span>;
&nbsp;
            event.title <span style="color: #002200;">=</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Evento para mi calendario&quot;</span>;
&nbsp;
            <span style="color: #11740a; font-style: italic;">// set the start date to the current date/time and the event duration to two hours</span>
            <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSDate_Class/"><span style="color: #400080;">NSDate</span></a> <span style="color: #002200;">*</span>startDate <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSDate_Class/"><span style="color: #400080;">NSDate</span></a> date<span style="color: #002200;">&#93;</span>;
            event.startDate <span style="color: #002200;">=</span> startDate;
            event.endDate <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>startDate dateByAddingTimeInterval<span style="color: #002200;">:</span><span style="color: #2400d9;">3600</span> <span style="color: #002200;">*</span> <span style="color: #2400d9;">2</span><span style="color: #002200;">&#93;</span>;
&nbsp;
            <span style="color: #002200;">&#91;</span>store saveEvent<span style="color: #002200;">:</span>event span<span style="color: #002200;">:</span>EKSpanThisEvent commit<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span> error<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
&nbsp;
            dispatch_async<span style="color: #002200;">&#40;</span>dispatch_get_main_queue<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>, <span style="color: #002200;">^</span><span style="color: #002200;">&#123;</span>
&nbsp;
                <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UIAlertView alloc<span style="color: #002200;">&#93;</span> initWithTitle<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Error&quot;</span> message<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Se ha producido un error guardando el evento en el calendario&quot;</span> delegate<span style="color: #002200;">:</span>self cancelButtonTitle<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Ok&quot;</span> otherButtonTitles<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span> show<span style="color: #002200;">&#93;</span>;
&nbsp;
            <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#41;</span>;
&nbsp;
        <span style="color: #002200;">&#125;</span>
    <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Como se puede ver, es muy sencillo crear nuevos eventos en el calendario del usuario. Como veiamos al principio, tambien es posible crear nuevos calendarios específicos para nuestra aplicación. Aunque en este artículo no vamos a abordar esta posibilidad, os recomiendo leer la guía <strong>Calendar and Reminders Programming Guide</strong>.</p>
<p>Como siempre, os dejo el <a href="http://www.migueldiazrubio.com/wp-content/uploads/2013/05/Calendarios.zip">código del ejemplo</a> para que podáis descargarlo.</p>
<p>Espero que os haya gustado el artículo. ¡Nos vemos en el siguiente!
<div class="ptl_div"><a href="http://twitter.com/share" class="twitter-share-button" data-url="http://www.migueldiazrubio.com/2013/05/10/desarrollo-ios-accede-a-los-calendarios-con-el-framework-eventkit/" data-text="Desarrollo iOS: Accede a los calendarios con el framework EventKit" data-count="horizontal">Tweet</a></div>
<p>The post <a href="http://www.migueldiazrubio.com/2013/05/10/desarrollo-ios-accede-a-los-calendarios-con-el-framework-eventkit/">Desarrollo iOS: Accede a los calendarios con el framework EventKit</a> appeared first on <a href="http://www.migueldiazrubio.com">Miguel Diaz Rubio</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://www.migueldiazrubio.com/2013/05/10/desarrollo-ios-accede-a-los-calendarios-con-el-framework-eventkit/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Desarrollo iOS: Curso de Introducción a los Backends de Terceros</title>
		<link>http://www.migueldiazrubio.com/2013/05/09/desarrollo-ios-curso-de-introduccion-a-los-backends-de-terceros/</link>
		<comments>http://www.migueldiazrubio.com/2013/05/09/desarrollo-ios-curso-de-introduccion-a-los-backends-de-terceros/#comments</comments>
		<pubDate>Thu, 09 May 2013 08:00:58 +0000</pubDate>
		<dc:creator>migueldiazrubio</dc:creator>
				<category><![CDATA[Desarrollo iOS]]></category>

		<guid isPermaLink="false">http://www.migueldiazrubio.com/?p=1179</guid>
		<description><![CDATA[<p>Aprende todo lo que necesitas saber sobre los principal [...]</p><p>The post <a href="http://www.migueldiazrubio.com/2013/05/09/desarrollo-ios-curso-de-introduccion-a-los-backends-de-terceros/">Desarrollo iOS: Curso de Introducción a los Backends de Terceros</a> appeared first on <a href="http://www.migueldiazrubio.com">Miguel Diaz Rubio</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>Aprende todo lo que necesitas saber sobre los principales productos en <em>cloud</em> disponibles para utilizar como <strong>backends</strong> para tu app.</p>
<p><span id="more-1179"></span></p>
<h2>Introducción</h2>
<p>Desde hace unos años, prácticamente la totalidad de apps importantes del mercado, hacen uso de plataformas en la nube para permitir entre otras cosas, la sincronización entre varios dispositivos, creación de redes sociales temáticas, entornos colaborativos, etc.</p>
<p>Son muchas las aplicaciones como <strong>Facebook</strong>, <strong>Instagram</strong>, <strong>Twitter</strong>, <strong>WhatsApp</strong>, <strong>Line</strong>, <strong>Pocket</strong>, <strong>Flipboard</strong>, <strong>Foursquare</strong>, que no solo cuentan con una app para <strong>iPhone</strong> o <strong>iPad</strong>, sino que ademas, por su tipología, requieren un <strong>backend</strong> donde almacenar toda esa información en la nube, compartida por todos o algunos de los usuarios que la utilizan.</p>
<p>Si nuestra intención es crear aplicaciones digamos de tipo <em>offline</em>, no necesitamos nada de lo que vamos a comentar en este artículo, pero si nuestra idea para una app va mas allá muy posiblemente necesitemos utilizar este tipo de servicios en la nube.</p>
<h2>Servicios y funcionalidades</h2>
<p>Existen múltiples y con diversas funcionalidades: <strong>Amazon Web Services</strong>, <strong>Microsoft Windows Azure</strong>, <strong>Parse</strong> (recientemente adquirida por Facebook) y otras muchas.</p>
<p>Normalmente estos servicios on-line, ofrecen parte o la totalidad del siguiente <strong>catalogo de funcionalidades</strong>:</p>
<ul>
<li><span style="line-height: 13px;"><strong>Modelo de datos:</strong> capacidades para la creación de una BBDD online con la que poder interactuar desde los distintos dispositivos que tienen nuestra app.</span></li>
<li><strong>Sistemas de autenticación centralizados:</strong> que facilitan a nuestra app la creación de cuentas de usuario, autenticación, etc.</li>
<li><strong>Almacenamiento en la nube:</strong> capacidades para almacenar ficheros de todo tipo en la nube (fotografías, archivos, &#8230;), que puedan ser utilizados por nuestros usuarios.</li>
<li><strong>Notificaciones Push:</strong> nos permite enviar notificaciones de tipo push a nuestros usuarios siguiendo el criterio que queramos definir.</li>
<li><strong>Ejecución de código en el servidor:</strong> nos permite definir proceso que se ejecutan en el lado servidor.</li>
<li>Y otros muchos&#8230;</li>
</ul>
<h2>Costes y amortización</h2>
<p>Estos servicios normalmente son de pago, pero en muchos casos cuentan con versiones gratuitas que podemos utilizar si el volumen de tráfico y peticiones que tiene nuestra aplicación es moderado.</p>
<p>Tener siempre en cuenta, que si creamos una app donde el modelo de negocio este bien definido, y tenemos tantos usuarios que necesitamos pagar mensualmente una ampliación de servicio a <strong>Amazon</strong> o <strong>Parse</strong>, éste sera el menor de nuestros problemas, porque significará que la aplicación es de mucho éxito y si tiene un <strong>ROI</strong> claramente definido, no supondrá ningún problema asumir dicho coste.</p>
<h2>¿Como aprendo a utilizar estos servicios?</h2>
<p>Sin duda, aprender a utilizar todos estos servicios, o ser capaz de identificar cual es el mas idóneo para implementar en nuestra aplicación, es fruto de la práctica y de la experiencia con cada uno de ellos.</p>
<p>Normalmente todos estos servicios cuentan con una documentación medianamente extensa, la gran mayoría en inglés, pero sin duda éste puede ser un problema porque no es una labor sencilla y no hay demasiados tutoriales o ejemplos por internet.</p>
<p>Yo, después de darle muchas vueltas, he optado seguir el camino mas fácil y con menos riesgo, y voy a asistir como algunos me habréis oído comentar en <a href="http://www.twitter.com/migueldiazrubio" target="_blank"><strong>Twitter</strong> </a>al curso que organiza <strong>AGBO</strong> <a href="/redirect.php?url=agbo.biz/tech/curso-backends-terceros-apps/" target="_blank">&#8220;Curso de Introducción a los Backends de Terceros&#8221;</a>.</p>
<p>El temario del curso no puede ser mas atractivo:</p>
<p><strong>Amazon Web Services</strong></p>
<ul>
<li>Visión general de los servicios más significativos para un desarrollador iOS (S3, CDN, EC2, DynamoDB, etc..)</li>
<li>Cómo esarrollar contra AWS: AWS SDK for iOS (Instalación, configuración del SDK en xCode)</li>
<li>Práctica 1: App para hacer fotos almacenándolas en S3</li>
<li>Token Vending Machine o cómo usar credenciales temporales en nuestras Apps</li>
<li>Práctica 2: Extendiendo la App de Fotografía, usaremos una pequeña BD (DynamoDB) para añadir comentarios a las imágenes.</li>
<li>Costes</li>
</ul>
<p><strong> Microsoft Windows Azure</strong></p>
<ul>
<li>Visión general de los servicios más significativos para un desarrollador iOS (Queues, Storage, Tables, Mobile Services)</li>
<li>Caminos para desarrollar contra Azure: API REST vs Windos Azure Toolkil for iOS.</li>
<li>Práctica 1: Utilizando Mobile Services, usaremos una base de datos SQL Server para almacenar y consultar nuestras canciones favoritas.</li>
<li>Practica 2: Usaremos API REST para combinar el manejo de Tables y Storage tomando como punto de partida la App de fotos.</li>
<li>Costes</li>
</ul>
<p><strong> Parse</strong></p>
<ul>
<li>Visión general de los servicios de la plataforma</li>
<li>Instalación, configuración de un proyecto con el SDK de Parse</li>
<li>Práctica 1: Login &amp; Signup Views</li>
<li>Costes</li>
<li>Distribución de nuestras Apps controlada: TestFlight</li>
<li>Descripción del servicio</li>
<li>Comparación con la distribución ad-hoc que nos permite Apple</li>
<li>Práctica 1: Creación de perfil de distribución, invitación a testers, distribución de una App</li>
<li>Práctica 2: Explorando el Api de TestFlight – Logging Remoto – Symbolicated Crash Reports – OTA</li>
<li>Costes.</li>
</ul>
<p><strong> Mapas: No solo existe Google Maps</strong></p>
<ul>
<li>OpenStreetMaps: Alternativa Abierta</li>
<li>Configuración de un xCode usando MapBox o Route-me SDKs</li>
<li>Práctica 1: Uso de MapBox o directamente Route-me para localizar nuestra posición</li>
<li>Google Maps – Licenciamiento &amp; Características de la plataforma)</li>
<li>Práctica 2: Uso de mapas embebidos en nuestra App</li>
</ul>
<p><strong> ¿Qué hace mi app? ¿Cuántos usuarios usan una determinada funcionalidad?: Estadísticas integradas en las Apps</strong></p>
<ul>
<li>Visión general</li>
<li>Descripción de Google Analitycs for Mobile (GA) y Flurry Analitycs</li>
<li>Configuración de xCode para integrar GA en nuestras Apps</li>
<li>Práctica 1: Integración en nuestra App de fotografía GA.</li>
<li>Configuración de xCode para integrar Flurry Analitycs.</li>
<li>Práctica 2: Integración en nuestra App de fotografía con Flurry.</li>
<li>Comparación entre las dos plataformas y otras alternativas.</li>
</ul>
<p><strong> Cómo usar APNS sin desarrollar un servidor de notificaciones</strong></p>
<ul>
<li>Descripción del Apple Push Notification Service</li>
<li>Practica 1: Provisionar una App para usar APNS</li>
<li>Servicios de terceros que nos permiten hacer notificaciones “sin desarrollar”</li>
<li>Urban Airship</li>
<li>Practica 2: Incorporar el api de Urban Airship Push en la App de fotografías.</li>
</ul>
<p>Un fin de semana del <strong>31 de mayo al 2 de junio</strong>, repleto de conocimiento, donde salir con la maleta llena, con todo lo necesario para afrontar un proyecto de app en condiciones.</p>
<h2>Precio y promoción AGBO</h2>
<p>El precio el curso, considerando la calidad del docente y del temario a impartir, es mas que razonable. Os recomiendo echarle un vistazo a la web y a todos los detalles del curso.</p>
<p>Además, <strong>AGBO</strong> esta haciendo una promoción, con la que podéis haceros con una plaza completamente gratis. Podéis consultar toda la información en <a href="/redirect.php?url=agbo.biz/blog/backend-de-terceros-para-apps-gratis/" target="_blank"><strong>Curso Backend de Terceros para Apps ¡Gratis!</strong></a>.</p>
<p>Yo estaré en la convocatoria que se imparte los días <strong>31 de mayo, 1 de junio y 2 de junio</strong>. ¡Espero veros allí a muchos de vosotros y que podamos frikear un rato y tomarnos una caña!¡No tardéis, quedan muy pocas plazas!</p>
<p>A mi vuelta intentaré escribir algún artículo con los temas que mas interesantes me hayan  parecido, tal y como hice cuando asistí al <a href="/redirect.php?url=agbo.biz/tech/curso-ios-intermedio/" target="_blank"><strong>Curso iOS Intermedio</strong></a>, también en <strong>AGBO</strong> e impartido por <strong>Fernando Rodríguez</strong> (<a href="http://www.twitter.com/frr149" target="_blank">@frr149</a>).
<div class="ptl_div"><a href="http://twitter.com/share" class="twitter-share-button" data-url="http://www.migueldiazrubio.com/2013/05/09/desarrollo-ios-curso-de-introduccion-a-los-backends-de-terceros/" data-text="Desarrollo iOS: Curso de Introducción a los Backends de Terceros" data-count="horizontal">Tweet</a></div>
<p>The post <a href="http://www.migueldiazrubio.com/2013/05/09/desarrollo-ios-curso-de-introduccion-a-los-backends-de-terceros/">Desarrollo iOS: Curso de Introducción a los Backends de Terceros</a> appeared first on <a href="http://www.migueldiazrubio.com">Miguel Diaz Rubio</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://www.migueldiazrubio.com/2013/05/09/desarrollo-ios-curso-de-introduccion-a-los-backends-de-terceros/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Desarrollo iOS: Lidiando con las cookies en Objective-C</title>
		<link>http://www.migueldiazrubio.com/2013/05/07/desarrollo-ios-lidiando-con-las-cookies-en-objective-c/</link>
		<comments>http://www.migueldiazrubio.com/2013/05/07/desarrollo-ios-lidiando-con-las-cookies-en-objective-c/#comments</comments>
		<pubDate>Tue, 07 May 2013 08:00:01 +0000</pubDate>
		<dc:creator>pedromunoz</dc:creator>
				<category><![CDATA[Desarrollo iOS]]></category>

		<guid isPermaLink="false">http://www.migueldiazrubio.com/?p=1138</guid>
		<description><![CDATA[<p>Aprenderemos a lidiar con las cookies de navegación, en [...]</p><p>The post <a href="http://www.migueldiazrubio.com/2013/05/07/desarrollo-ios-lidiando-con-las-cookies-en-objective-c/">Desarrollo iOS: Lidiando con las cookies en Objective-C</a> appeared first on <a href="http://www.migueldiazrubio.com">Miguel Diaz Rubio</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>Aprenderemos a lidiar con las cookies de navegación, en aplicaciones donde utilicemos servicios web o componentes de tipo <strong>UIWebView</strong>.</p>
<p><span id="more-1138"></span></p>
<div class='et-box et-download'>
					<div class='et-box-content'>Desde hace unas semanas, estoy tratando de conseguir <b>colaboradores</b> para el blog, que me ayuden a dar perspectivas diferentes, y que ayuden a conservar la regularidad de publicación en la que estoy inmerso desde hace unos meses.</p>
<p>En esta ocasión es para mi un auténtico placer, ofreceros el siguiente artículo, cortesía de mi amigo <b>Pedro Muñoz</b> (<a href="https://twitter.com/Pmunoz08" target="_blank">@Pmunoz08</a>). Si alguna vez necesitáis apoyo profesional para el desarrollo de una aplicación para <b>iOS</b>, y necesitáis presupuesto, no dudéis en visitar su web y poneros en contacto con él. <a href="http://www.softpmc.com/" target="_blank">www.softpmc.com</a></div></div>
<div class='et-box et-shadow'>
					<div class='et-box-content'><b>Pedro Muñoz</b></p>
<p>Soy desarrollador freelance para <b>iPhone/ iPad</b> con sede en Madrid. Diplomado en Ingeniería de Sistemas. Desarrollador desde 1999, en 2009 cayó en mis manos un <b>iPhone 3G</b>, desde entonces he tratado de especializarme en el desarrollo de aplicaciones para <b>iOS</b> (iPhone / iPad) trabajando como desarrollador freelance. No he parado de bucear en el mundo de <b>Objective-C</b>, interesándome por todo lo relacionado en desarrollo iOS, blogs, foros de desarrolladores, eventos, librerías de terceros, en ese momento tuve claro que debía dar un giro a mi carrera profesional.</div></div>
<h2>Introducción</h2>
<p>Por norma general cuando desarrollamos una app que usa servicios web o accede a páginas a través de un UIWebView, las cookies de estas conexiones nos son transparentes, ya que son gestionadas de forma autónoma por el sistema o el framework que utilicemos para este tipo de acciones.</p>
<p>El servidor en el <em>response</em> envía un <strong>Set_Cookie</strong>, con el valor de la cookie y el cliente, en este caso la app, la almacena para enviarla cuando se envíen <em>requests</em> al dominio de la cookie.</p>
<p>Pero, ¿que pasa si quiero saber las cookies que tengo almacenadas para una app, reutilizar una cookie para otro dominio , eliminar una o todas las cookies, añadir una nueva o modificar una existente? Aquí nos empiezan a surgir dudas&#8230;</p>
<p>Bien, para estos casos tenemos a nuestro servicio desde la versión 2.0 de iOS <strong>NSHTTPCookie</strong> y <strong>NSHTTPCookieStorage</strong> que nos van a ayudar con estas tareas.</p>
<p><strong>NSHTTPCookieStorage:</strong> es un singleton que gestiona el almacenamiento de cookies, las cuales se mantienen sincronizadas entre procesos, pero a diferencia de <strong>OSX,</strong> en <strong>iOS</strong> las cookies no se comparten entre aplicaciones, aunque si la política para aceptarlas, al cambiar el valor de esta propiedad afectará a todas las aplicaciones. El valor por defecto es <strong>NSHTTPCookieAcceptPolicyAlways</strong>.</p>
<p><strong>NSHTTPCookie:</strong> representa una cookie <strong>HTTP</strong>. Es un objeto inmutable inicializado con un diccionario que contiene los atributos de la cookie. Entre los atributos podemos encontrar:</p>
<ul>
<li><span style="line-height: 13px;">Name</span></li>
<li>Value</li>
<li>Domain</li>
<li>ExpireDate</li>
<li>Path</li>
</ul>
<p>Todos los atributos tienen una constante asociada para clave del diccionario y de esta forma, es muy cómodo acceder a los distintos valores.</p>
<p>Visto un poco el escenario y de que disponemos,  vamos a centrarnos en situaciones concretas y ver como actuar. Al final del artículo tenéis un <em>link</em> a un proyecto de ejemplo del que he extraído las imágenes y código que uso a continuación.</p>
<h2>Listado de cookies</h2>
<p>Para obtener una relación de las cookies almacenadas para una app podemos hacer lo siguiente:</p>

<div class="wp_codebox"><table><tr id="p113849"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
</pre></td><td class="code" id="p1138code49"><pre class="objc" style="font-family:monospace;"><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/"><span style="color: #400080;">NSMutableArray</span></a> <span style="color: #002200;">*</span>cookies <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/"><span style="color: #400080;">NSMutableArray</span></a> new<span style="color: #002200;">&#93;</span>;
<span style="color: #a61390;">int</span> counter <span style="color: #002200;">=</span> <span style="color: #2400d9;">1</span>;
<span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSHTTPCookie_Class/"><span style="color: #400080;">NSHTTPCookie</span></a> <span style="color: #002200;">*</span>cookie <span style="color: #a61390;">in</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSHTTPCookieStorage_Class/"><span style="color: #400080;">NSHTTPCookieStorage</span></a> sharedHTTPCookieStorage<span style="color: #002200;">&#93;</span> cookies<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #002200;">&#91;</span>cookies addObject<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a>
                            stringWithFormat<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%d: Nombre = %@ <span style="color: #2400d9;">\n</span> Valor = %@<span style="color: #2400d9;">\n</span> Dominio = %@<span style="color: #2400d9;">\n</span> Path = %@ <span style="color: #2400d9;">\n</span> Caduca =%@&quot;</span>, counter<span style="color: #002200;">++</span>, cookie.name, cookie.value, cookie.domain, cookie.path, cookie.expiresDate<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
self.textView.text <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>cookies componentsJoinedByString<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;<span style="color: #2400d9;">\n</span><span style="color: #2400d9;">\n</span>&quot;</span><span style="color: #002200;">&#93;</span>;</pre></td></tr></table></div>

<p>Creamos un <strong>NSMutableArray</strong> “cookies” para almacenar las cookies del <strong>NSHTTPCookieStorage</strong>.<br />
Recorremos las cookies y creamos una cadena de strings con las propiedades que queremos mostrar, añadiéndolas a “cookies”.</p>
<p>Las mostramos en un <strong>UITextView</strong>.</p>
<p>Para probar que funciona el código anterior vamos a utilizar la web de la <strong>ATP</strong> <a href="http://es.atpworldtour.com" target="_blank">http://es.atpworldtour.com</a>, que nos devolverá unas cookies en el <em>response</em>.</p>
<p>Antes de visitar la web nuestro listado de cookies luce así:</p>
<p><img class="alignnone size-full wp-image-1143" alt="pedro01" src="http://www.migueldiazrubio.com/wp-content/uploads/2013/05/pedro01.png" width="301" height="534" /></p>
<p>&nbsp;</p>
<p>Después de visitar la página web, el resultado es:</p>
<p><img class="alignnone size-full wp-image-1144" alt="pedro02" src="http://www.migueldiazrubio.com/wp-content/uploads/2013/05/pedro02.png" width="380" height="674" /></p>
<p>Con estos sencillos pasos, ya tenemos nuestro listado de cookies.</p>
<h2>Modificar una cookie</h2>
<p>¿Como modificamos una cookie si es inmutable?. Pues lo que hacemos es crear una nueva a partir de la que queremos modificar y asignársela al <strong>NSHTTPCookieStorage</strong>. Para ello, lo que vamos a hacer es modificar el valor las cookies a “<em>New Value</em>”.</p>
<p>Si solo quisiéramos modificar una de las cookies, podríamos hacerlo comprobando su propiedad “<em>Name</em>”.</p>

<div class="wp_codebox"><table><tr id="p113850"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
</pre></td><td class="code" id="p1138code50"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSHTTPCookie_Class/"><span style="color: #400080;">NSHTTPCookie</span></a> <span style="color: #002200;">*</span>cookie <span style="color: #a61390;">in</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSHTTPCookieStorage_Class/"><span style="color: #400080;">NSHTTPCookieStorage</span></a> sharedHTTPCookieStorage<span style="color: #002200;">&#93;</span> cookies<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
&nbsp;
        <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableDictionary_Class/"><span style="color: #400080;">NSMutableDictionary</span></a> <span style="color: #002200;">*</span>cookieProperties <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>cookie.properties mutableCopy<span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#91;</span>cookieProperties setObject<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;New Value&quot;</span> forKey<span style="color: #002200;">:</span>NSHTTPCookieValue<span style="color: #002200;">&#93;</span>;
&nbsp;
        <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSHTTPCookie_Class/"><span style="color: #400080;">NSHTTPCookie</span></a> <span style="color: #002200;">*</span>newCookie <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSHTTPCookie_Class/"><span style="color: #400080;">NSHTTPCookie</span></a> alloc<span style="color: #002200;">&#93;</span> initWithProperties<span style="color: #002200;">:</span>cookieProperties<span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSHTTPCookieStorage_Class/"><span style="color: #400080;">NSHTTPCookieStorage</span></a> sharedHTTPCookieStorage<span style="color: #002200;">&#93;</span> setCookie<span style="color: #002200;">:</span>newCookie<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Después de esta modificación el listado de cookies mostraría lo siguiente:</p>
<p><img class="alignnone size-full wp-image-1145" alt="pedro03" src="http://www.migueldiazrubio.com/wp-content/uploads/2013/05/pedro03.png" width="301" height="534" /></p>
<p>Pero, ¿realmente se envía esto en la <em>request</em> que hacemos? Vamos a comprobarlo utilizando una  aplicación llamada <strong>Charles</strong>  <a href="http://www.charlesproxy.com" target="_blank">http://www.charlesproxy.com</a>, de lo mejor que he probado para capturar el tráfico de red. Además si nuestro dispositivo <strong>iOS</strong> está conectado a la misma red <strong>WIFI</strong> que nuestro ordenador,  podemos acceder a la configuración de la <strong>WIFI </strong>en el dispositivo, e indicar que vamos a utilizar nuestro ordenador como <em>proxy</em>, añadiendo tu <strong>IP</strong> local y el puerto <strong>8888</strong>.</p>
<p>De esta forma podrás captura el trafico de red del dispositivo fácilmente.</p>
<p>Esto sería lo que veríamos en la aplicación <strong>Charles</strong> antes de modificar las cookies:</p>
<p><img class="alignnone  wp-image-1146" alt="pedro04" src="http://www.migueldiazrubio.com/wp-content/uploads/2013/05/pedro04.png" width="496" height="344" /></p>
<p>Una vez modificadas las cookis, <strong>Charles</strong> sin embargo mostraría lo siguiente:</p>
<p><img class="alignnone  wp-image-1147" alt="pedro05" src="http://www.migueldiazrubio.com/wp-content/uploads/2013/05/pedro05.png" width="496" height="342" /></p>
<p>Como veis, la modificación de las cookies es real, y está siendo usada.</p>
<p>Si quisiéramos, podríamos también reutilizar una cookie para otro dominio. Para ello, tendríamos que crear una cookie igual a la que queremos reutilizar y cambiarle la propiedad “<em>Domain</em>”.</p>
<p>A priori, si pensamos en modificar una cookie, a muchos os vendrá a la cabeza la idea de modificar directamente el <strong>NSURLRequest</strong> o su equivalente en el framework que estés utilizando.  Esto tiene algunos inconvenientes que me gustaría contaros a continuación:</p>
<p>En primer lugar, <em>Header</em> con <em>Name</em> Cookie solo puede haber 1, por lo que si quieres modificar una cookie tendrías que reescribirlas todas incluida la modificada, si no estaríamos sobrescribiendo las cookies actuales. Las cookies, en el caso que nos ocupan, viajan en la <em>request</em> de la siguiente manera:</p>
<p>“Cookie: __utma=113228507.637317221.1367666511.1367666511.1367666511.1; __utmz=113228507.1367666511.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); “</p>
<p>Por tanto, sería bastante laboriosa la modificación de una de ellas.</p>
<p>Otro problema, es que <strong>NSURLRequest</strong> es inmutable, y por tanto, habría que utilizar <strong>NSMutableURLRequest, </strong>y quizás no dependa de nosotros o no tengamos acceso a este objeto, por lo que acabemos modificando un objeto en  una capa superior,  y al enviar la <em>request,</em> la cookie sea de nuevo sustituida por el contenido de <strong>NSHTTPCookieStorage</strong> y volvamos a estar como al principio.</p>
<h2>Eliminando las cookies</h2>
<p>Para eliminar una cookie utilizaremos el método <em>delete</em> de <strong>NSHTTPCookieStorage</strong>. Con este código eliminaremos todas las cookies de nuestra app:</p>

<div class="wp_codebox"><table><tr id="p113851"><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code" id="p1138code51"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSHTTPCookie_Class/"><span style="color: #400080;">NSHTTPCookie</span></a> <span style="color: #002200;">*</span>cookie <span style="color: #a61390;">in</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSHTTPCookieStorage_Class/"><span style="color: #400080;">NSHTTPCookieStorage</span></a> sharedHTTPCookieStorage<span style="color: #002200;">&#93;</span> cookies<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSHTTPCookieStorage_Class/"><span style="color: #400080;">NSHTTPCookieStorage</span></a> sharedHTTPCookieStorage<span style="color: #002200;">&#93;</span> deleteCookie<span style="color: #002200;">:</span>cookie<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Igualmente, si solo queremos eliminar una o varias cookies, podríamos filtrar por cualquiera de las propiedades de <strong>NSHTTPCookie</strong>: <em>Name, domain, expireDate</em>,….</p>
<h2>Añadiendo una nueva cookie</h2>
<p>A estas alturas, seguro que no tenéis problemas para añadir una nueva cookie, no obstante vamos a analizar los pasos que habría que dar para ello.</p>
<p>Vamos a crear una cookie, cuyo nombre va a ser “<em>customCookie</em>” y valor “<em>Custom Value</em>”, para que se añada a las que ya tenemos en la <em>request</em> al servidor, y le vamos a indicar el mismo dominio que tienen las demás “.atpworldtour.com”. De esta forma, nuestra nueva cookie se añadirá al resto en la <em>request</em>.</p>
<p>Veamos los pasos que deberemos seguir en nuestro código:</p>
<p>Creamos un diccionario para las propiedades de la cookie.</p>

<div class="wp_codebox"><table><tr id="p113852"><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code" id="p1138code52"><pre class="objc" style="font-family:monospace;"><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableDictionary_Class/"><span style="color: #400080;">NSMutableDictionary</span></a> <span style="color: #002200;">*</span>cookieProperties <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>@<span style="color: #002200;">&#123;</span>NSHTTPCookieName<span style="color: #002200;">:</span>    <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;CustomCookie&quot;</span>,
                                             NSHTTPCookieValue<span style="color: #002200;">:</span>     <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Custom value&quot;</span>,
                                             NSHTTPCookieDomain<span style="color: #002200;">:</span>    <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;.atpworldtour.com&quot;</span>,
                                             NSHTTPCookieExpires<span style="color: #002200;">:</span>   <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSDate_Class/"><span style="color: #400080;">NSDate</span></a> dateWithTimeIntervalSinceNow<span style="color: #002200;">:</span><span style="color: #2400d9;">64000</span><span style="color: #002200;">&#93;</span>,
                                             NSHTTPCookiePath<span style="color: #002200;">:</span>      <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;/”  }mutableCopy];</span></pre></td></tr></table></div>

<p>Creamos la cookie con el diccionario creado.</p>

<div class="wp_codebox"><table><tr id="p113853"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p1138code53"><pre class="objc" style="font-family:monospace;"><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSHTTPCookie_Class/"><span style="color: #400080;">NSHTTPCookie</span></a> <span style="color: #002200;">*</span>newCookie <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSHTTPCookie_Class/"><span style="color: #400080;">NSHTTPCookie</span></a> alloc<span style="color: #002200;">&#93;</span> initWithProperties<span style="color: #002200;">:</span>cookieProperties<span style="color: #002200;">&#93;</span>;</pre></td></tr></table></div>

<p>Añadimos la cookie a <strong>NSHTTPCookieStorage</strong>.</p>

<div class="wp_codebox"><table><tr id="p113854"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p1138code54"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSHTTPCookieStorage_Class/"><span style="color: #400080;">NSHTTPCookieStorage</span></a> sharedHTTPCookieStorage<span style="color: #002200;">&#93;</span> setCookie<span style="color: #002200;">:</span>newCookie<span style="color: #002200;">&#93;</span>;</pre></td></tr></table></div>

<p>Las cookies en nuestra siguiente <em>request</em> ahora serán:</p>
<p>“Cookie: NREUM=h=1367677984548&amp;r=42047&amp;p=0; __utma=113228507.1891220335.1367675684.1367675684.1367675684.1; __utmc=113228507; __utmz=113228507.1367675684.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); CustomCookie=New Value”</p>
<p>Como siempre, os dejamos un ejemplo que ha elaborado <strong>Pedro Muñoz</strong> con los conceptos aprendidos en este artículo para que <a href="http://www.migueldiazrubio.com/wp-content/uploads/2013/05/CrazyCookies.zip" target="_blank">podáis descargarlo</a>.</p>
<p><div class='et-box et-shadow'>
					<div class='et-box-content'><b>Pedro Muñoz</b></p>
<p>Soy desarrollador freelance para <b>iPhone/ iPad</b> con sede en Madrid. Diplomado en Ingeniería de Sistemas. Desarrollador desde 1999, en 2009 cayó en mis manos un <b>iPhone 3G</b>, desde entonces he tratado de especializarme en el desarrollo de aplicaciones para <b>iOS</b> (iPhone / iPad) trabajando como desarrollador freelance. No he parado de bucear en el mundo de <b>Objective-C</b>, interesándome por todo lo relacionado en desarrollo iOS, blogs, foros de desarrolladores, eventos, librerías de terceros, en ese momento tuve claro que debía dar un giro a mi carrera profesional.</div></div>
<div class="ptl_div"><a href="http://twitter.com/share" class="twitter-share-button" data-url="http://www.migueldiazrubio.com/2013/05/07/desarrollo-ios-lidiando-con-las-cookies-en-objective-c/" data-text="Desarrollo iOS: Lidiando con las cookies en Objective-C" data-count="horizontal">Tweet</a></div>
<p>The post <a href="http://www.migueldiazrubio.com/2013/05/07/desarrollo-ios-lidiando-con-las-cookies-en-objective-c/">Desarrollo iOS: Lidiando con las cookies en Objective-C</a> appeared first on <a href="http://www.migueldiazrubio.com">Miguel Diaz Rubio</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://www.migueldiazrubio.com/2013/05/07/desarrollo-ios-lidiando-con-las-cookies-en-objective-c/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Desarrollo iOS: Accede a los contactos con el framework AddressBook</title>
		<link>http://www.migueldiazrubio.com/2013/05/03/desarrollo-ios-accede-a-los-contactos-con-el-framework-addressbook/</link>
		<comments>http://www.migueldiazrubio.com/2013/05/03/desarrollo-ios-accede-a-los-contactos-con-el-framework-addressbook/#comments</comments>
		<pubDate>Fri, 03 May 2013 08:00:01 +0000</pubDate>
		<dc:creator>migueldiazrubio</dc:creator>
				<category><![CDATA[Desarrollo iOS]]></category>

		<guid isPermaLink="false">http://www.migueldiazrubio.com/?p=1092</guid>
		<description><![CDATA[<p>iOS 6 se toma muy en serio la privacidad del usuario. A [...]</p><p>The post <a href="http://www.migueldiazrubio.com/2013/05/03/desarrollo-ios-accede-a-los-contactos-con-el-framework-addressbook/">Desarrollo iOS: Accede a los contactos con el framework AddressBook</a> appeared first on <a href="http://www.migueldiazrubio.com">Miguel Diaz Rubio</a>.</p>]]></description>
				<content:encoded><![CDATA[<p><strong>iOS 6</strong> se toma muy en serio la privacidad del usuario. Accede a los contactos del iOS, utilizando<strong> AddressBook.framework</strong> y respetando estas nuevas políticas.</p>
<p><span id="more-1092"></span></p>
<p>Con la llegada de <strong>iOS 6</strong> aparece en nuestra aplicación de <strong>Ajustes</strong> un nuevo menú denominado <em>Privacidad</em>, que nos permite gestionar los permisos que otorgamos a aplicaciones de <strong>iOS</strong> para acceder a nuestros contenidos, más concretamente: GPS, contactos, calendarios, recordatorios, fotos, y cuentas de Twitter y Facebook.</p>
<p>De esta forma el usuario puede tener total control sobre estas configuraciones, e incluso modificarlas una vez autorizada o denegada una petición de acceso.</p>
<p>Para poder llevar a cabo este acceso a los contactos del dispositivo, vamos a utilizar un framework provisto por <strong>Apple</strong>, denominado <strong>AddressBook</strong>.</p>
<p>Vamos a crear una nueva aplicación, de tipo <em>Single View Application</em>, a la cual añadiremos el framework que indicábamos anteriormente, y donde nuestra única interfaz para este ejemplo será un <strong>UIButton</strong>, para el cual definiremos un <strong>IBAction</strong> cuyo método denominaremos <strong>obtenerContactos</strong>.</p>
<p>En primer lugar, vamos a crear una variable para albergar la referencia a nuestra agenda, dado que la vamos a utilizar en varios métodos de nuestra aplicación.</p>

<div class="wp_codebox"><table><tr id="p109258"><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code" id="p1092code58"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">@interface</span> ViewController <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
    ABAddressBookRef addressBookRef;
<span style="color: #002200;">&#125;</span>
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>

<p>La implementación del método obtenerContactos será la siguiente:</p>

<div class="wp_codebox"><table><tr id="p109259"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
</pre></td><td class="code" id="p1092code59"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>IBAction<span style="color: #002200;">&#41;</span>obtenerContactos <span style="color: #002200;">&#123;</span>
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Solicitamos al usuario acceso a los contactos (no funciona en el Simulador)</span>
    addressBookRef <span style="color: #002200;">=</span> ABAddressBookCreateWithOptions<span style="color: #002200;">&#40;</span><span style="color: #a61390;">NULL</span>, <span style="color: #a61390;">NULL</span><span style="color: #002200;">&#41;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Comprobamos el estado de permisos de usuario</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>ABAddressBookGetAuthorizationStatus<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">==</span> kABAuthorizationStatusNotDetermined<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        ABAddressBookRequestAccessWithCompletion<span style="color: #002200;">&#40;</span>addressBookRef, <span style="color: #002200;">^</span><span style="color: #002200;">&#40;</span>bool granted, CFErrorRef error<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
            <span style="color: #11740a; font-style: italic;">// Es la primera vez que accedemos a dichos contactos</span>
            NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Primer vez&quot;</span><span style="color: #002200;">&#41;</span>;
            <span style="color: #002200;">&#91;</span>self pintaContactos<span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#41;</span>;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">else</span> <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>ABAddressBookGetAuthorizationStatus<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">==</span> kABAuthorizationStatusAuthorized<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #11740a; font-style: italic;">// El usuario ya nos había autorizado previamente el acceso</span>
        NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Segundas veces&quot;</span><span style="color: #002200;">&#41;</span>;
        <span style="color: #002200;">&#91;</span>self pintaContactos<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">else</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #11740a; font-style: italic;">// El usuario ya nos había denegado previamente el acceso</span>
        NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Permiso denegado&quot;</span><span style="color: #002200;">&#41;</span>;
        <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UIAlertView alloc<span style="color: #002200;">&#93;</span> initWithTitle<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Error&quot;</span> message<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Permiso denegado!&quot;</span> delegate<span style="color: #002200;">:</span>self cancelButtonTitle<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Ok&quot;</span> otherButtonTitles<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span> show<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Como observaréis la solicitud de permisos al usuario es bien sencilla, y pueden producirse tres situaciones diferentes:</p>
<ul>
<li><span style="line-height: 13px;"><strong>El estado de la autorización no esta determinado:</strong> por tanto invocamos a la autorización mediante un bloque de finalización que nos permitirá invocar a nuestro método que pinta en el log los contactos una vez dispongamos de la autorización.</span></li>
<li><strong>El estado de la autorización se ha definido como permitida anteriormente:</strong> por tanto invocaremos a nuestro método que pinta contactos directamente.</li>
<li><strong>El estado de la autorización se ha definido como denegada anteriormente:</strong> mostraremos en pantalla un mensaje de error que permita al usuario entender lo ocurrido.</li>
</ul>
<p>Es muy importante tener en cuenta, que si utilizamos este ejemplo en el Simulador de <strong>XCode</strong> no observaremos este comportamiento, dado que solo es funcional en un dispositivo real. En el caso del simulador, siempre funcionará como si se hubiera aceptado el acceso a la agenda, no mostrando en ningún caso el aviso al usuario.</p>
<p>A continuación, vamos a implementar nuestro método <strong>pintaContactos</strong>:</p>

<div class="wp_codebox"><table><tr id="p109260"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
</pre></td><td class="code" id="p1092code60"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>pintaContactos <span style="color: #002200;">&#123;</span>
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Obtenemos todos los contactos del usuario en base a la referencia obtenida</span>
    CFArrayRef all <span style="color: #002200;">=</span> ABAddressBookCopyArrayOfAllPeople<span style="color: #002200;">&#40;</span>addressBookRef<span style="color: #002200;">&#41;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Obtenemos el total de contactos encontrados</span>
    CFIndex n <span style="color: #002200;">=</span> ABAddressBookGetPersonCount<span style="color: #002200;">&#40;</span>addressBookRef<span style="color: #002200;">&#41;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Recorremos todos los contactos</span>
    <span style="color: #a61390;">for</span><span style="color: #002200;">&#40;</span> <span style="color: #a61390;">int</span> i <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span> ; i <span style="color: #002200;">&amp;</span>lt; n ; i<span style="color: #002200;">++</span> <span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
        <span style="color: #11740a; font-style: italic;">// Obtenemos el contacto</span>
        ABRecordRef ref <span style="color: #002200;">=</span> CFArrayGetValueAtIndex<span style="color: #002200;">&#40;</span>all, i<span style="color: #002200;">&#41;</span>;
&nbsp;
        <span style="color: #11740a; font-style: italic;">// Obtenemos el nombre del contacto</span>
        <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span>firstName <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span>__bridge <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>ABRecordCopyValue<span style="color: #002200;">&#40;</span>ref, kABPersonFirstNameProperty<span style="color: #002200;">&#41;</span>;
&nbsp;
        <span style="color: #11740a; font-style: italic;">// Pintamos en el log el nombre del contacto</span>
        NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;First Name: %@&quot;</span>,firstName<span style="color: #002200;">&#41;</span>;
&nbsp;
        <span style="color: #11740a; font-style: italic;">// Obtenemos los teléfonos disponibles</span>
        ABMultiValueRef phoneNumberProperty <span style="color: #002200;">=</span> ABRecordCopyValue<span style="color: #002200;">&#40;</span>ref, kABPersonPhoneProperty<span style="color: #002200;">&#41;</span>;
        <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a> <span style="color: #002200;">*</span>phones <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span>__bridge <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>ABMultiValueCopyArrayOfAllValues<span style="color: #002200;">&#40;</span>phoneNumberProperty<span style="color: #002200;">&#41;</span>;
&nbsp;
        <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span>telefono <span style="color: #a61390;">in</span> phones<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
            <span style="color: #11740a; font-style: italic;">// Pintamos el teléfono del contacto</span>
            NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%@&quot;</span>,telefono<span style="color: #002200;">&#41;</span>;
        <span style="color: #002200;">&#125;</span>
&nbsp;
        <span style="color: #11740a; font-style: italic;">// Obtenemos los emails disponibles</span>
        ABMultiValueRef emailProperty <span style="color: #002200;">=</span> ABRecordCopyValue<span style="color: #002200;">&#40;</span>ref, kABPersonEmailProperty<span style="color: #002200;">&#41;</span>;
        <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a> <span style="color: #002200;">*</span>emails <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span>__bridge <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>ABMultiValueCopyArrayOfAllValues<span style="color: #002200;">&#40;</span>emailProperty<span style="color: #002200;">&#41;</span>;
&nbsp;
        <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span>email <span style="color: #a61390;">in</span> emails<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
            <span style="color: #11740a; font-style: italic;">// Pintamos el email del contacto</span>
            NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%@&quot;</span>,email<span style="color: #002200;">&#41;</span>;
        <span style="color: #002200;">&#125;</span>
    <span style="color: #002200;">&#125;</span>
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Convertimos a NSUInteger el total de contactos</span>
    NSUInteger total <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span>NSUInteger<span style="color: #002200;">&#41;</span>n;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Mostramos una alerta con el total de contactos encontrados</span>
    <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UIAlertView alloc<span style="color: #002200;">&#93;</span> initWithTitle<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Agenda&quot;</span> message<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> stringWithFormat<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Tienes un total de %d contactos&quot;</span>,total<span style="color: #002200;">&#93;</span> delegate<span style="color: #002200;">:</span>self cancelButtonTitle<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Ok&quot;</span> otherButtonTitles<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span> show<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Para acceder a cada una de las propiedades de un contacto, existen una serie de constantes como <strong>kABPersonFirstNameProperty</strong>, <strong>kABPersonPhoneProperty</strong> o <strong>kABPersonEmailProperty</strong> que nos hacen mas sencilla la labor.</p>
<p>Si queréis más información sobre el acceso a contactos a través de esta <strong>API</strong>, os recomiendo echar un vistazo a la guía <strong>Address Book Programming Guide for iOS</strong>, disponible en <a href="http://developer.apple.com" target="_blank"><strong>developer.apple.com</strong></a>.</p>
<p>Os dejo como siempre el <a href="http://www.migueldiazrubio.com/wp-content/uploads/2013/04/Contactos.zip">código del ejemplo</a>.</p>
<p>Espero que os haya gustado el artículo y ¡hasta el próximo!
<div class="ptl_div"><a href="http://twitter.com/share" class="twitter-share-button" data-url="http://www.migueldiazrubio.com/2013/05/03/desarrollo-ios-accede-a-los-contactos-con-el-framework-addressbook/" data-text="Desarrollo iOS: Accede a los contactos con el framework AddressBook" data-count="horizontal">Tweet</a></div>
<p>The post <a href="http://www.migueldiazrubio.com/2013/05/03/desarrollo-ios-accede-a-los-contactos-con-el-framework-addressbook/">Desarrollo iOS: Accede a los contactos con el framework AddressBook</a> appeared first on <a href="http://www.migueldiazrubio.com">Miguel Diaz Rubio</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://www.migueldiazrubio.com/2013/05/03/desarrollo-ios-accede-a-los-contactos-con-el-framework-addressbook/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Desarrollo iOS: Integra Google Analytics en tu app</title>
		<link>http://www.migueldiazrubio.com/2013/04/30/desarrollo-ios-integra-google-analytics-en-tu-app/</link>
		<comments>http://www.migueldiazrubio.com/2013/04/30/desarrollo-ios-integra-google-analytics-en-tu-app/#comments</comments>
		<pubDate>Tue, 30 Apr 2013 08:00:58 +0000</pubDate>
		<dc:creator>migueldiazrubio</dc:creator>
				<category><![CDATA[Desarrollo iOS]]></category>

		<guid isPermaLink="false">http://www.migueldiazrubio.com/?p=1020</guid>
		<description><![CDATA[<p>Analiza con Google Analytics el uso que hacen de tu apl [...]</p><p>The post <a href="http://www.migueldiazrubio.com/2013/04/30/desarrollo-ios-integra-google-analytics-en-tu-app/">Desarrollo iOS: Integra Google Analytics en tu app</a> appeared first on <a href="http://www.migueldiazrubio.com">Miguel Diaz Rubio</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>Analiza con <strong>Google Analytics</strong> el uso que hacen de tu aplicación los usuarios que la descargan, detectando las funcionalidades mas utilizadas entre otras cosas.</p>
<p><span id="more-1020"></span></p>
<h2>Herramientas de analítica Web</h2>
<p>Es bien conocido desde hace muchos años, que la analítica web ha permitido a los <em>webmasters</em> un mayor control sobre lo que ocurre en sus páginas web. Ahora es fácil saber si tenemos muchas visitas de España o del resto de países, en qué horario es cuando mas visitas tenemos, cual es la página más vista este mes, y un largo etcétera.</p>
<p><strong>¿Por qué no tener estas mismas ventajas para aplicaciones iOS?</strong></p>
<p>Pues eso es lo que ha debido pensar <strong>Google</strong> cuando ha incorporado a su producto <strong>Google Analytics</strong> la posibilidad de analizar la operativa en aplicaciones móviles. De hecho, los desarrolladores de <strong>iOS</strong> tenemos un <strong>SDK</strong> para hacernos mas fácil la vida.</p>
<h2>Google Analytics SDK</h2>
<p>Ahora mismo la versión estable es la 1.0. Sin embargo, <strong>Google</strong> ya esta trabajando en la <strong>versión 2.0</strong>, que se encuentra en fase beta y también podemos utilizar.</p>
<p>Para este artículo vamos a utilizar la <strong>versión 2.0 beta 4</strong>, que es la disponible en el momento en que escribo este artículo.</p>
<p>Lo podéis descargar desde aquí: <a href="https://developers.google.com/analytics/devguides/collection/ios/resources" target="_blank">https://developers.google.com/analytics/devguides/collection/ios/resources</a></p>
<p>Esta versión de <strong>Google Analytics</strong> nos va a permitir hacer seguimiento de entre otras, las siguientes acciones:</p>
<ul>
<li>El numero de usuarios activos que utilizan vuestra app.</li>
<li>Desde qué zonas geográficas se utiliza vuestra app.</li>
<li>Uso que hacen los usuarios de determinadas funcionalidades de la app.</li>
<li>Compras in-app.</li>
<li>El número y tipo de errores que hagan terminar nuestra app.</li>
<li>Y otras muchas métricas&#8230;</li>
</ul>
<h2>Dar de alta nuestra app en la web de Google Analytics</h2>
<p>Para poder disfrutar de todas estas ventajas, lo primero que tenemos que hacer es obtener un código de seguimiento para nuestra app, y para ello debemos dar de alta la aplicación en el portal de Google Analytics.</p>
<p>Si accedemos a la sección Listado de cuentas, veremos un botón para crear una nueva cuenta.</p>
<p><img class="alignnone  wp-image-1053" alt="googleanalitics-01" src="http://www.migueldiazrubio.com/wp-content/uploads/2013/04/googleanalitics-01.png" width="566" height="206" /></p>
<p>&nbsp;</p>
<p>Se mostrará un formulario sencillo que deberemos rellenar, donde deberemos en primer lugar indicar que somos una aplicación y no un sitio web.</p>
<p><img class="alignnone  wp-image-1054" alt="googleanalitics-02" src="http://www.migueldiazrubio.com/wp-content/uploads/2013/04/googleanalitics-02.png" width="561" height="447" /></p>
<p>&nbsp;</p>
<p>En la parte inferior deberemos indicar el nombre de cuenta que deseemos, que será lo que aparecerá en nuestro listado del portal.</p>
<p><img class="alignnone  wp-image-1055" alt="googleanalitics-03" src="http://www.migueldiazrubio.com/wp-content/uploads/2013/04/googleanalitics-03.png" width="561" height="307" /></p>
<p>&nbsp;</p>
<p>Al pulsar el botón inferior &#8220;Obtener ID de seguimiento&#8221; se mostrarán las condiciones del servicio, que deberemos aceptar.</p>
<p><img class="alignnone  wp-image-1056" alt="googleanalitics-04" src="http://www.migueldiazrubio.com/wp-content/uploads/2013/04/googleanalitics-04.png" width="605" height="323" /></p>
<p>&nbsp;</p>
<p>Tras estos sencillos pasos, se mostrará una pantalla donde ya tendremos nuestro ID de seguimiento, que será pieza fundamental para todo lo que vamos a hacer a continuación. Éste es el identificador real de nuestra aplicación, y es único.</p>
<p><img class="alignnone  wp-image-1057" alt="googleanalitics-05" src="http://www.migueldiazrubio.com/wp-content/uploads/2013/04/googleanalitics-05-1024x489.png" width="717" height="342" /></p>
<p><span style="font-size: 1.5em;">Integrar el SDK en nuestra aplicación</span></p>
<p>Una vez descargado el <strong>SDK</strong> de la web que os indicaba anteriormente, debemos añadir a nuestro proyecto todas las clases que contiene el directorio <i>Library</i>. Os recomiendo crear un nuevo grupo (carpeta) para ello y ubicar todas las clases dentro.</p>
<p>Como<strong> Google Analytics</strong> para <strong>iOS</strong> utiliza internamente <strong>algunos frameworks de iOS</strong>, debemos añadirlos a nuestro proyecto, en la sección &#8220;<em>target linked libraries</em>&#8221; como hemos hecho en otras ocasiones. Concretamente debemos incorporar los siguientes <strong>frameworks</strong>:</p>
<ul>
<li>libGoogleAnalytics.a</li>
<li>CoreData.framework</li>
<li>SystemConfiguration.framework</li>
</ul>
<p>Para inicializar el <em>tracker</em> de <strong>Google</strong> en nuestra app, deberemos incluir el siguiente código en el <strong>AppDelegate</strong> de nuestra aplicación (haciendo previamente import de la clase principal &#8220;<em>GAI.h</em>&#8220;):</p>

<div class="wp_codebox"><table><tr id="p102066"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code" id="p1020code66"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>application<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIApplication <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>application didFinishLaunchingWithOptions<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSDictionary_Class/"><span style="color: #400080;">NSDictionary</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>launchOptions <span style="color: #002200;">&#123;</span>
  <span style="color: #11740a; font-style: italic;">// Opcional: envia automáticamente excepciones no controladas de nuestra app a Google.</span>
  <span style="color: #002200;">&#91;</span>GAI sharedInstance<span style="color: #002200;">&#93;</span>.trackUncaughtExceptions <span style="color: #002200;">=</span> <span style="color: #a61390;">YES</span>;
  <span style="color: #11740a; font-style: italic;">// Opcional: establece 20 segundos como intervalo para comunicar con Google.</span>
  <span style="color: #002200;">&#91;</span>GAI sharedInstance<span style="color: #002200;">&#93;</span>.dispatchInterval <span style="color: #002200;">=</span> <span style="color: #2400d9;">20</span>;
  <span style="color: #11740a; font-style: italic;">// Opcional: activa el modo debug para obtener información adicional.</span>
  <span style="color: #002200;">&#91;</span>GAI sharedInstance<span style="color: #002200;">&#93;</span>.debug <span style="color: #002200;">=</span> <span style="color: #a61390;">YES</span>;
  <span style="color: #11740a; font-style: italic;">// Creamos la instancia del tracker indicando el ID de seguimiento que hemos obtenido anteriormente.</span>
  <span style="color: #a61390;">id</span> tracker <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>GAI sharedInstance<span style="color: #002200;">&#93;</span> trackerWithTrackingId<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;UA-YOUR-TRACKING-ID&quot;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Como se puede observar cuando instanciamos el <em>tracker</em>, se esta utilizando una <strong>sharedInstance</strong> (patrón Singleteon) que nos devolverá siempre la misma instancia, aunque llamemos en varias ocasiones y desde diferentes puntos de nuestra app.</p>
<h2>Hacer tracking de uno de nuestros View Controllers</h2>
<p>Para hacer <em>tracking</em> de una de las pantallas de nuestra aplicación, <strong>Google</strong> nos ofrece dos métodos distintos: automático o manual.</p>
<p>Si optamos por la opción automática, bastará con que nuestro <strong>View Controller</strong> extienda de la clase <strong>GAITrackedViewController</strong>, y que incluyamos el siguiente código en el método <strong>viewDidLoad</strong> del mismo:</p>

<div class="wp_codebox"><table><tr id="p102067"><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code" id="p1020code67"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>viewDidLoad <span style="color: #002200;">&#123;</span>
  <span style="color: #002200;">&#91;</span>super viewDidLoad<span style="color: #002200;">&#93;</span>;
  self.trackedViewName <span style="color: #002200;">=</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Pantalla Acerca de&quot;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Esta opción esta muy bien, pero habrá ocasiones en donde nos suponga un problema tener que heredar de dicha clase. Para ello, existe una segunda opción manual que consiste en invocar al <em>tracker</em> directamente. Para ello deberemos instanciarlo, e invocar al siguiente método del mismo:</p>

<div class="wp_codebox"><table><tr id="p102068"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p1020code68"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">&#91;</span>tracker sendView<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Pantalla Acerca de&quot;</span><span style="color: #002200;">&#93;</span>;</pre></td></tr></table></div>

<p>Con estos sencillos pasos, vamos a poder obtener mucha información acerca del uso que hacen los usuarios de nuestra aplicación.</p>
<h2>Para los que quieran un poquito más</h2>
<p>Si queremos obtener aún mas información sobre nuestra app, tal y como indicábamos al principio, tenemos algunas opciones bastante interesantes.</p>
<p>Por ejemplo, es posible que nos interese hacer tracking de cuando nuestros usuarios añaden una nueva tarea a nuestra aplicación de gestión de tareas. Pues bien, para ello tenemos el reporte de eventos. Os pongo un ejemplo a continuación:</p>

<div class="wp_codebox"><table><tr id="p102069"><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code" id="p1020code69"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">&#91;</span>tracker sendEventWithCategory<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Acción de usuario&quot;</span>
                     withAction<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Nueva tarea añadida&quot;</span>
                      withLabel<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span>
                      withValue<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;</pre></td></tr></table></div>

<p>También podemos registrar posibles errores que se produzcan excepciones en nuestra aplicación. Para ello, tenemos el siguiente método:</p>

<div class="wp_codebox"><table><tr id="p102070"><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code" id="p1020code70"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">@try</span> <span style="color: #002200;">&#123;</span>
  <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a> <span style="color: #002200;">*</span>resultados<span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self obtenerResultadosXML<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
<span style="color: #a61390;">@catch</span> <span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSException_Class/"><span style="color: #400080;">NSException</span></a> <span style="color: #002200;">*</span>exception<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
  <span style="color: #002200;">&#91;</span>tracker sendException<span style="color: #002200;">:</span><span style="color: #a61390;">NO</span> withNSException<span style="color: #002200;">:</span>exception<span style="color: #002200;">&#41;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Éste método enviara a <strong>Google Analytics</strong> la <i>description</i> de la excepción producida automáticamente.</p>
<p>Si queréis información más profunda sobre las posibilidades adicionales que ofrece el <strong>SDK</strong> os recomiendo que os deis una vuelta por la información disponible en la web del proyecto en <strong>Google</strong>: <a href="https://developers.google.com/analytics/devguides/collection/ios/v2/#headers" target="_blank">https://developers.google.com/analytics/devguides/collection/ios/v2/#headers</a></p>
<p>Espero que os haya gustado el artículo y que muy pronto lo integréis en vuestras aplicaciones.</p>
<p>Recordar seguirme en <a href="https://twitter.com/migueldiazrubio" target="_blank">twitter </a>para estar a atento a todas las novedades!</p>
<p>&nbsp;
<div class="ptl_div"><a href="http://twitter.com/share" class="twitter-share-button" data-url="http://www.migueldiazrubio.com/2013/04/30/desarrollo-ios-integra-google-analytics-en-tu-app/" data-text="Desarrollo iOS: Integra Google Analytics en tu app" data-count="horizontal">Tweet</a></div>
<p>The post <a href="http://www.migueldiazrubio.com/2013/04/30/desarrollo-ios-integra-google-analytics-en-tu-app/">Desarrollo iOS: Integra Google Analytics en tu app</a> appeared first on <a href="http://www.migueldiazrubio.com">Miguel Diaz Rubio</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://www.migueldiazrubio.com/2013/04/30/desarrollo-ios-integra-google-analytics-en-tu-app/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Snippets iOS: Obtener un identificador único del usuario (UUID)</title>
		<link>http://www.migueldiazrubio.com/2013/04/26/snippets-ios-obtener-un-identificador-unico-del-usuario-uuid/</link>
		<comments>http://www.migueldiazrubio.com/2013/04/26/snippets-ios-obtener-un-identificador-unico-del-usuario-uuid/#comments</comments>
		<pubDate>Fri, 26 Apr 2013 08:00:47 +0000</pubDate>
		<dc:creator>migueldiazrubio</dc:creator>
				<category><![CDATA[Snippets iOS]]></category>

		<guid isPermaLink="false">http://www.migueldiazrubio.com/?p=1070</guid>
		<description><![CDATA[<p>En algunas ocasiones puede que necesitemos identificar  [...]</p><p>The post <a href="http://www.migueldiazrubio.com/2013/04/26/snippets-ios-obtener-un-identificador-unico-del-usuario-uuid/">Snippets iOS: Obtener un identificador único del usuario (UUID)</a> appeared first on <a href="http://www.migueldiazrubio.com">Miguel Diaz Rubio</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>En algunas ocasiones puede que necesitemos identificar la instalación de nuestra aplicación en el dispositivo del usuario mediante un identificador único (UUID).</p>
<p><span id="more-1070"></span></p>
<h2>UDID (Unique Device Identifier)</h2>
<p><strong>UDID (Unique Device Identifier)</strong> era nuestro mejor candidato hasta hace bien poco. Sin embargo, con <strong>iOS 6</strong> Apple lanza al mercado una nueva forma de obtener un identificador de este tipo. En este caso se denomina <strong>UUID (Universally Unique Identifiers)</strong>.</p>
<h2>UUID (Universally Unique Identifiers)</h2>
<p>Este nuevo método, fue una propuesta de <strong>Apple</strong> para dar respuesta a la polémica formada alrededor de estos identificadores y de la violación de la privacidad que suponen.</p>
<p>Para que todo el mundo lo entienda, el identificador <strong>UDID</strong> identifica el dispositivo unívocamente. Sin embargo, el nuevo <strong>UUID</strong> es un identificado generado en base a información del dispositivo, y utiliza como parte de su algoritmo de generación el número de bloques de 100 nanosegundos transcurridos desde el <strong>15 de octubre de 1582</strong>.</p>
<p>Por esto último, si generamos consecutivamente dos identificadores, éstos serán distintos. Es por ello, que mas adelante veremos formas de conservar el valor obtenido inicialmente y conservarlo a lo largo del ciclo de vida de la aplicación.</p>
<h2>¿Como obtener el UUID desde mi código?</h2>
<p>Hasta ahora, para obtener el <strong>UDID</strong> hacíamos uso de un método de la case <strong>UIDevice</strong>:</p>

<div class="wp_codebox"><table><tr id="p107076"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p1070code76"><pre class="objc" style="font-family:monospace;"><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span>UDID <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UIDevice currentDevice<span style="color: #002200;">&#93;</span> uniqueIdentifier<span style="color: #002200;">&#93;</span>;</pre></td></tr></table></div>

<p>Esto nos devolvía una cadena hexadecimal de 40 caracteres como esta:<br />
<strong>6f6c9dc83d77134bca4n1c53l1202b395b05582b</strong></p>
<p>Sin embargo, a partir del <strong>1 de mayo de 2013</strong>, cualquier aplicación que haga uso de esta llamada a <em>uniqueIndentifier</em>, será rechazada.</p>
<p>En su lugar, si queremos dar soporte a versiones anteriores a <strong>iOS 6</strong> deberemos utilizar lo siguiente:</p>

<div class="wp_codebox"><table><tr id="p107077"><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code" id="p1070code77"><pre class="objc" style="font-family:monospace;">CFUUIDRef theUUID <span style="color: #002200;">=</span> CFUUIDCreate<span style="color: #002200;">&#40;</span><span style="color: #a61390;">NULL</span><span style="color: #002200;">&#41;</span>;
CFStringRef <span style="color: #a61390;">string</span> <span style="color: #002200;">=</span> CFUUIDCreateString<span style="color: #002200;">&#40;</span><span style="color: #a61390;">NULL</span>, theUUID<span style="color: #002200;">&#41;</span>;
CFRelease<span style="color: #002200;">&#40;</span>theUUID<span style="color: #002200;">&#41;</span>;
<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span>UUID <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span>__bridge_transfer <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span><span style="color: #a61390;">string</span>;</pre></td></tr></table></div>

<p>Si en nuestro caso, podemos únicamente dar compatibilidad a partir de <strong>iOS 6</strong>, podemos hacer uso de este otro método, mucho mas directo:</p>

<div class="wp_codebox"><table><tr id="p107078"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p1070code78"><pre class="objc" style="font-family:monospace;"><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span>UUID <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>NSUUID UUID<span style="color: #002200;">&#93;</span> UUIDString<span style="color: #002200;">&#93;</span>;</pre></td></tr></table></div>

<p>Esto generará una cadena hexadecimal separada por guiones del tipo:<br />
<strong>68753A44-4D6F-1226-9C60-0050E4C00067</strong></p>
<h2>¿Cómo conservo el UUID obtenido?</h2>
<p>Una de las opciones que <strong>Apple</strong> propone para conservar el <strong>UUID</strong> generado en la primera ejecución de la aplicación, es almacenarlo en el <strong>NSUserDefaults</strong>. Para ello, tendríamos algo como lo que sigue a continuación:</p>

<div class="wp_codebox"><table><tr id="p107079"><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code" id="p1070code79"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// Comprobamos la existencia en el NSUserDefaults de una variable UUID</span>
<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/"><span style="color: #400080;">NSUserDefaults</span></a> <span style="color: #002200;">*</span>prefs <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/"><span style="color: #400080;">NSUserDefaults</span></a> standardUserDefaults<span style="color: #002200;">&#93;</span>;
<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span>UUID <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>prefs stringForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;UUID&quot;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span>UUID<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
    <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span>miUUID <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>NSUUID UUID<span style="color: #002200;">&#93;</span> UUIDString<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>prefs setObject<span style="color: #002200;">:</span>miUUID forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;UUID&quot;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>De esta forma, y ejecutando este código en el arranque de nuestra aplicación, obtendremos un <strong>UUID</strong> la primera vez, y dicho <strong>UUID</strong> en las próximas ejecuciones.</p>
<p>Recordar cuando se vaya a cerrar la aplicación, y para evitar pérdida de la información guardada en el <strong>NSUserDefaults</strong>, hacer un <em>synchronize</em>:</p>

<div class="wp_codebox"><table><tr id="p107080"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p1070code80"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/"><span style="color: #400080;">NSUserDefaults</span></a> standardUserDefaults<span style="color: #002200;">&#93;</span> synchronize<span style="color: #002200;">&#93;</span>;</pre></td></tr></table></div>

<p>Para los más avanzados, existen otras opciones de persistencia de este <strong>UUID</strong>, mediante por ejemplo el Llavero (o <strong>Keychain</strong>), o incluso mediante <strong>iCloud</strong>, facilitando con éste último la posibilidad de compartir dicho <strong>UUID</strong> entre dos dispositivos del mismo usuario.</p>
<h2>¿Y entonces ya no hay ningún método para identificar un dispositivo unívocamente?</h2>
<p>Pues a raíz de esta problemática, han surgido otras alternativas, porque como dice el refrán español: <em>&#8220;hecha la ley, hecha la trampa&#8221;</em>. Por ejemplo, existen librerías en <strong>Github</strong> para obtener la <strong>MAC</strong> de la interfaz de red del dispositivo.</p>
<p>Personalmente, mi consejo sería que os hicierais la siguiente pregunta: ¿realmente lo necesito? La respuesta en muchos casos, os garantizo que será <strong>NO</strong>. La opción <strong>UUID</strong>, cubrirá vuestras necesidades en un 90% de los casos.</p>
<p>Espero que os haya gustado el snippet de hoy y ya sabéis que para cualquier duda, tenéis los comentarios más abajo.
<div class="ptl_div"><a href="http://twitter.com/share" class="twitter-share-button" data-url="http://www.migueldiazrubio.com/2013/04/26/snippets-ios-obtener-un-identificador-unico-del-usuario-uuid/" data-text="Snippets iOS: Obtener un identificador único del usuario (UUID)" data-count="horizontal">Tweet</a></div>
<p>The post <a href="http://www.migueldiazrubio.com/2013/04/26/snippets-ios-obtener-un-identificador-unico-del-usuario-uuid/">Snippets iOS: Obtener un identificador único del usuario (UUID)</a> appeared first on <a href="http://www.migueldiazrubio.com">Miguel Diaz Rubio</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://www.migueldiazrubio.com/2013/04/26/snippets-ios-obtener-un-identificador-unico-del-usuario-uuid/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Desarrollo iOS: Crea tu propio lector RSS con MWFeedParser</title>
		<link>http://www.migueldiazrubio.com/2013/04/23/desarrollo-ios-crea-tu-propio-lector-rss/</link>
		<comments>http://www.migueldiazrubio.com/2013/04/23/desarrollo-ios-crea-tu-propio-lector-rss/#comments</comments>
		<pubDate>Tue, 23 Apr 2013 08:00:06 +0000</pubDate>
		<dc:creator>migueldiazrubio</dc:creator>
				<category><![CDATA[Desarrollo iOS]]></category>

		<guid isPermaLink="false">http://www.migueldiazrubio.com/?p=1006</guid>
		<description><![CDATA[<p>En este artículo os voy a hablar de un framework que he [...]</p><p>The post <a href="http://www.migueldiazrubio.com/2013/04/23/desarrollo-ios-crea-tu-propio-lector-rss/">Desarrollo iOS: Crea tu propio lector RSS con MWFeedParser</a> appeared first on <a href="http://www.migueldiazrubio.com">Miguel Diaz Rubio</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>En este artículo os voy a hablar de un framework que he podido probar recientemente, que nos va a permitir crear un lector de <strong>RSS</strong>, de forma sencilla y ahorrándonos mucho del trabajo sucio.</p>
<p><span id="more-1006"></span></p>
<p>Este framework se llama <strong>MWFeedParser</strong> (<a href="https://github.com/mwaterfall/MWFeedParser">https://github.com/mwaterfall/MWFeedParser</a>) y su autor es<strong> Michael Waterfall</strong> (<a href="http://twitter.com/mwaterfall">@mwaterfall</a>).</p>
<h2>Un poco de teoria</h2>
<p>Principalmente la utilización de este framework se basa en el siguiente modelo de datos:</p>
<ul>
<li><strong>MWFeedParser:</strong> es el servicio que nos va a permitir realizar todas las operaciones de parseo con nuestro feed, que proporcionaremos como parámetro de tipo <em>NSURL</em>. Podemos configurar la recuperación de los datos en modo síncrono o asíncrono. Tambien podemos definir si queremos parsear todos los items recibidos, o bien solo la cabecera del feed.</li>
<li><span style="line-height: 13px;"><strong>MWFeedInfo:</strong> que contiene la información relativa al feed que queremos recuperar y parsear, y del cual obtiene los siguientes atributos: <em>title</em>, <em>link</em> y <em>summary</em>.</span></li>
<li><strong>MWFeedItem:</strong> representa cada uno de los artículos o elementos que se han recuperado del feed indicado. Para cada uno de estos items, podemos consultar la siguiente información: <em>title, link, date, updated, summary, content, enclosured</em> y <em>identifier</em>.</li>
</ul>
<p>Además de estas clases principales, el framework incluye algunos otros elementos interesantes, como una categoría para <strong>NSString</strong> denominada <strong>NSString+HTML</strong> que nos va a permitir hacer <em>encoding</em>/<em>decoding</em> de los tags HTML que contentan los campos que recuperemos del feed en cuestión.</p>
<p>Para el ejemplo que vamos a hacer a continuación, he utilizado <strong>Cocoapods</strong> para importar la librería <strong>MWFeedParser</strong>. Si no sabéis de qué estoy hablando, os recomiendo leer el siguiente artículo: <a href="http://www.migueldiazrubio.com/2013/01/02/desarrollo-ios-gestionar-dependencias-con-cocoapods/" target="_blank"><strong>Desarrollo iOS: Gestionar dependencias con Cocoapods</strong></a></p>
<h2>Nuestra interfaz</h2>
<p>Basicamente nuestra aplicación de ejemplo va a tener dos pantallas: un listado de los artículos encontrados en <strong>migueldiazrubio.com</strong> (<em>UITableViewController</em>), y una pantalla de detalle con el contenido del artículo seleccionado (<em>UIViewController</em> y <em>UIWebView</em>), ambos embebidos dentro de una navegación (<em>UINavigationController</em>).</p>
<p><a href="http://www.migueldiazrubio.com/wp-content/uploads/2013/04/Captura-de-pantalla-2013-04-14-a-las-13.35.22.png"><img class="alignnone  wp-image-1011" alt="Captura de pantalla 2013-04-14 a la(s) 13.35.22" src="http://www.migueldiazrubio.com/wp-content/uploads/2013/04/Captura-de-pantalla-2013-04-14-a-las-13.35.22-1024x450.png" width="614" height="270" /></a></p>
<p>En mi caso y para poder dotar de mas espacio a las etiquetas que mostraremos en nuestro <em>UITableViewController</em>, he decidido crear una celda personalizada, que he denominado <em>ArticuloCell</em> y que como veis unicamente tiene dos labels multilinea.</p>
<p>A continuación os muestro el código correspondiente a dicha celda:</p>
<h4>ArticuloCell.h</h4>

<div class="wp_codebox"><table><tr id="p100695"><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code" id="p1006code95"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">@interface</span> ArticuloCell <span style="color: #002200;">:</span> UITableViewCell
&nbsp;
<span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>weak, nonatomic<span style="color: #002200;">&#41;</span> IBOutlet UILabel <span style="color: #002200;">*</span>titulo;
<span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>weak, nonatomic<span style="color: #002200;">&#41;</span> IBOutlet UILabel <span style="color: #002200;">*</span>descripcion;
&nbsp;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>

<h2>Nuestro listado de artículos</h2>
<p>En primer lugar vamos a implementar toda la lógica correspondiente a nuestro <strong>ListadoArticulosViewController</strong>, que es el primer controlador que mostrará nuestra aplicación en pantalla, y que contiene una <em>UITableView</em> con todos los artículos encontrados en el feed del blog.</p>
<p>Dado que vamos a necesitar utilizar en este controlador nuestro <strong>MWFeedParser</strong>, debemos importar el framework en la cabecera, y definir nuestro controlador como delegado para el <strong>MWFeedParserDelegate</strong>:</p>

<div class="wp_codebox"><table><tr id="p100696"><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code" id="p1006code96"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &lt;MWFeedParser/MWFeedParser.h&gt;;</span>
&nbsp;
<span style="color: #a61390;">@interface</span> ListadoArticulosViewController <span style="color: #002200;">:</span> UITableViewController</pre></td></tr></table></div>

<p>A continuación en nuestro fichero de implementación, debemos definir el parser y una colección que nos permita almacenar los artículos que posteriormente pintaremos en el <strong>UITableView</strong>.</p>

<div class="wp_codebox"><table><tr id="p100697"><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code" id="p1006code97"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">@interface</span> ListadoArticulosViewController <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#123;</span>
    MWFeedParser <span style="color: #002200;">*</span>feedParser;
    <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/"><span style="color: #400080;">NSMutableArray</span></a> <span style="color: #002200;">*</span>listadoArticulos;
<span style="color: #002200;">&#125;</span>
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>

<p>Para empezar, deberemos hacer ciertos trabajos de inicialización en los métodos que corresponden al ciclo de vida de nuestro controlador:</p>

<div class="wp_codebox"><table><tr id="p100698"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
</pre></td><td class="code" id="p1006code98"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>viewDidLoad
<span style="color: #002200;">&#123;</span>
    <span style="color: #002200;">&#91;</span>super viewDidLoad<span style="color: #002200;">&#93;</span>;
&nbsp;
    <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span style="color: #400080;">NSURL</span></a> <span style="color: #002200;">*</span>feedURL <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span style="color: #400080;">NSURL</span></a> URLWithString<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;http://www.migueldiazrubio.com/feed/&quot;</span><span style="color: #002200;">&#93;</span>;
    feedParser <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>MWFeedParser alloc<span style="color: #002200;">&#93;</span> initWithFeedURL<span style="color: #002200;">:</span>feedURL<span style="color: #002200;">&#93;</span>;
&nbsp;
    feedParser.delegate <span style="color: #002200;">=</span> self;
&nbsp;
    feedParser.feedParseType <span style="color: #002200;">=</span> ParseTypeFull;
&nbsp;
    feedParser.connectionType <span style="color: #002200;">=</span> ConnectionTypeAsynchronously;
&nbsp;
    listadoArticulos <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/"><span style="color: #400080;">NSMutableArray</span></a> alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
&nbsp;
    UIRefreshControl <span style="color: #002200;">*</span>refreshControl <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UIRefreshControl alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #002200;">&#91;</span>refreshControl addTarget<span style="color: #002200;">:</span>self action<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>cargaArticulos<span style="color: #002200;">&#41;</span> forControlEvents<span style="color: #002200;">:</span>UIControlEventValueChanged<span style="color: #002200;">&#93;</span>;
    self.refreshControl <span style="color: #002200;">=</span> refreshControl;    
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>viewWillAppear<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>animated <span style="color: #002200;">&#123;</span>
    <span style="color: #002200;">&#91;</span>super viewWillAppear<span style="color: #002200;">:</span>animated<span style="color: #002200;">&#93;</span>;    
    <span style="color: #002200;">&#91;</span>self cargaArticulos<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>cargaArticulos <span style="color: #002200;">&#123;</span>
    <span style="color: #002200;">&#91;</span>feedParser parse<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Básicamente estamos inicializando el parser, configurando sus parámetros, y hemos creado un método <strong>cargaArticulos</strong> que será quien se encargue de invocar a nuestro parser para que comience la consulta del feed y su posterior parseo.</p>
<p>Recordar que para poder definir el <em>refreshControl</em> de nuestro <strong>UITableView</strong>, debemos indicarselo en el <em>Storyboard</em> en la pestaña <em>Attributes</em>, en el campo <em>Refreshing</em> con el valor <em>Enabled</em>:</p>
<p><a href="http://www.migueldiazrubio.com/wp-content/uploads/2013/04/Captura-de-pantalla-2013-04-14-a-las-13.49.32.png"><img class="alignnone  wp-image-1012" alt="Captura de pantalla 2013-04-14 a la(s) 13.49.32" src="http://www.migueldiazrubio.com/wp-content/uploads/2013/04/Captura-de-pantalla-2013-04-14-a-las-13.49.32.png" width="406" height="239" /></a></p>
<p>Al habernos definido como delegate del protocolo <strong>MWFeedParserDelegate</strong>, existen un total de 5 métodos, todos ellos opcionales, que podemos implementar en nuestro controlador:</p>

<div class="wp_codebox"><table><tr id="p100699"><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code" id="p1006code99"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>feedParserDidStart<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>MWFeedParser <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>parser;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>feedParser<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>MWFeedParser <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>parser didParseFeedInfo<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>MWFeedInfo <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>info;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>feedParser<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>MWFeedParser <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>parser didParseFeedItem<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>MWFeedItem <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>item;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>feedParserDidFinish<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>MWFeedParser <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>parser;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>feedParser<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>MWFeedParser <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>parser didFailWithError<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSError_Class/"><span style="color: #400080;">NSError</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>error;</pre></td></tr></table></div>

<p>El método <strong>feedParserDidStart</strong> se ejecutará cuando invoquemos el método parse del <strong>MWFeedParser</strong> y por tanto incluiremos la siguiente lógica:</p>

<div class="wp_codebox"><table><tr id="p1006100"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code" id="p1006code100"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>feedParserDidStart<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>MWFeedParser <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>parser <span style="color: #002200;">&#123;</span>
    NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Comienza el parseo&quot;</span><span style="color: #002200;">&#41;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Vaciamos el listado de artículos para evitar que se acumulen</span>
    <span style="color: #11740a; font-style: italic;">// en llamadas posteriores</span>
    <span style="color: #002200;">&#91;</span>listadoArticulos removeAllObjects<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Ponemos el marcha el refresh control</span>
    <span style="color: #002200;">&#91;</span>self.refreshControl beginRefreshing<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Como veis, comenzamos borrando todos los elementos que pudiera tener nuestro array y posteriormente activamos el icono de refresco de nuestro <strong>UIRefreshControl</strong>.</p>
<p>A continuación, lo primero que detectará el parser será la información del feed, e invocará al método <strong>didParseFeedInfo</strong>. Allí incluiremos el siguiente código que nos va a permitir cambiar el title de nuestro controlador, con el nombre del blog que estamos descargando:</p>

<div class="wp_codebox"><table><tr id="p1006101"><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code" id="p1006code101"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>feedParser<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>MWFeedParser <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>parser didParseFeedInfo<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>MWFeedInfo <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>info <span style="color: #002200;">&#123;</span>
    self.title <span style="color: #002200;">=</span> info.title;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>El siguiente paso que hará el parser es ir recuperando uno a uno los artículos disponibles en dicho feed, e invocando al método <strong>didParseFeedItem</strong>. Para ello, iremos guardando en nuestro array los items que vayamos recuperando de la siguiente manera:</p>

<div class="wp_codebox"><table><tr id="p1006102"><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code" id="p1006code102"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>feedParser<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>MWFeedParser <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>parser didParseFeedItem<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>MWFeedItem <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>item <span style="color: #002200;">&#123;</span>
    <span style="color: #11740a; font-style: italic;">// Añadimos al array el item descargado</span>
    <span style="color: #002200;">&#91;</span>listadoArticulos addObject<span style="color: #002200;">:</span>item<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Por último, cuando finalice el parseo de todos los artículos disponibles, se invocará el método <strong>feedParserDidFinish</strong>, donde incluiremos el siguiente código:</p>

<div class="wp_codebox"><table><tr id="p1006103"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code" id="p1006code103"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>feedParserDidFinish<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>MWFeedParser <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>parser <span style="color: #002200;">&#123;</span>
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Como ya ha finalizado el parse, denemos el parser</span>
    <span style="color: #002200;">&#91;</span>feedParser stopParsing<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Detenemos el refresh control</span>
    <span style="color: #002200;">&#91;</span>self.refreshControl endRefreshing<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Refrescamos el table view</span>
    <span style="color: #002200;">&#91;</span>self.tableView reloadData<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Como se puede observar, detenemos el parser, detenemos tambien el <strong>UIRefreshControl</strong>, y actualizamos el <strong>UITableView</strong> para que muestre la información cargada.</p>
<p>Para que nuestro <strong>UITableView</strong> pueda mostrar la información de nuestro array, deberemos evidentemente implementar los métodos correspondientes:</p>

<div class="wp_codebox"><table><tr id="p1006104"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="code" id="p1006code104"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#pragma mark UITableViewDelegate / UITableViewDataSource</span>
&nbsp;
<span style="color: #002200;">-</span><span style="color: #002200;">&#40;</span>UITableViewCell <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>tableView<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UITableView <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>tableView cellForRowAtIndexPath<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSIndexPath_Class/"><span style="color: #400080;">NSIndexPath</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>indexPath <span style="color: #002200;">&#123;</span>
    ArticuloCell <span style="color: #002200;">*</span>cell <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>tableView dequeueReusableCellWithIdentifier<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;ArticuloCell&quot;</span><span style="color: #002200;">&#93;</span>;
    MWFeedItem <span style="color: #002200;">*</span>item <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>listadoArticulos objectAtIndex<span style="color: #002200;">:</span>indexPath.row<span style="color: #002200;">&#93;</span>;
    cell.titulo.text <span style="color: #002200;">=</span> item.title;
    cell.descripcion.text <span style="color: #002200;">=</span> item.link;
    <span style="color: #a61390;">return</span> cell;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span><span style="color: #002200;">&#40;</span>NSInteger<span style="color: #002200;">&#41;</span>tableView<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UITableView <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>tableView numberOfRowsInSection<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>NSInteger<span style="color: #002200;">&#41;</span>section <span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">return</span> listadoArticulos.count;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Ya tenemos todo listo en nuestro listado, y podemos pasar a la pantalla de detalle.</p>
<h2>Nuestro detalle de un artículo seleccionado</h2>
<p>Dado que nuestro pantalla en el <strong>Storyboard</strong> cuenta con un <strong>UIWebView</strong>, deberemos indicar en nuestro controlador que nos hacemos cargo como delegados del mismo. Así mismo, deberemos implementar el método <strong>shouldStartLoadWithRequest</strong>:</p>

<div class="wp_codebox"><table><tr id="p1006105"><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code" id="p1006code105"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>webView<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIWebView <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>webView shouldStartLoadWithRequest<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURLRequest_Class/"><span style="color: #400080;">NSURLRequest</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>request navigationType<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIWebViewNavigationType<span style="color: #002200;">&#41;</span>navigationType <span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">return</span> <span style="color: #a61390;">YES</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Tambien deberemos contar con un objeto donde poder guardar desde la pantalla anterior el artículo para el cual queremos mostrar el detalle.</p>
<p>Con ello, nuestro fichero de cabecera <strong>DetalleViewController.h</strong> quedaría así:</p>

<div class="wp_codebox"><table><tr id="p1006106"><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code" id="p1006code106"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &lt;MWFeedParser/MWFeedParser.h&gt;;</span>
&nbsp;
<span style="color: #a61390;">@interface</span> DetalleViewController <span style="color: #002200;">:</span> UIViewController 
<span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>nonatomic, strong<span style="color: #002200;">&#41;</span> MWFeedItem <span style="color: #002200;">*</span>item;
<span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>weak, nonatomic<span style="color: #002200;">&#41;</span> IBOutlet UIWebView <span style="color: #002200;">*</span>webView;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>

<p>A continuación, implementaremos la logica que queremos que se ejecute cuando se muestre este controlador:</p>

<div class="wp_codebox"><table><tr id="p1006107"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
</pre></td><td class="code" id="p1006code107"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>viewWillAppear<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>animated
<span style="color: #002200;">&#123;</span>
    <span style="color: #002200;">&#91;</span>super viewWillAppear<span style="color: #002200;">:</span>animated<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #002200;">&#91;</span>self.webView setDelegate<span style="color: #002200;">:</span>self<span style="color: #002200;">&#93;</span>;
    self.title <span style="color: #002200;">=</span> self.item.title;
    <span style="color: #002200;">&#91;</span>self.webView loadHTMLString<span style="color: #002200;">:</span>self.item.content baseURL<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Para finalizar, cuando el usuario seleccione una de las celdas de nuestro <strong>UITableView</strong> queremos que en el controlador del detalle se muestre el contenido del artículo seleccionado. Para ello deberemos implementar el método <strong>prepareForSegue</strong> en el <strong>ListadoArticulosViewController.m</strong> para que pase como parametro el artículo seleccionado:</p>

<div class="wp_codebox"><table><tr id="p1006108"><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code" id="p1006code108"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>prepareForSegue<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIStoryboardSegue <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>segue sender<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>sender <span style="color: #002200;">&#123;</span>
    ArticuloCell <span style="color: #002200;">*</span>celda <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span>ArticuloCell <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>sender;
    MWFeedItem <span style="color: #002200;">*</span>item <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>listadoArticulos objectAtIndex<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>self.tableView indexPathForCell<span style="color: #002200;">:</span>celda<span style="color: #002200;">&#93;</span>.row<span style="color: #002200;">&#93;</span>;
    DetalleViewController <span style="color: #002200;">*</span>detalleVC <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span>DetalleViewController <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>segue.destinationViewController;
    <span style="color: #002200;">&#91;</span>detalleVC setItem<span style="color: #002200;">:</span>item<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<h2>Conclusiones</h2>
<p>Basta con navegar un poco por internet y por <strong>GitHub</strong> para encontrar fantásticas librerías como esta, que sin duda van a hacer que nuestras aplicaciones puedan centrarse en los detalles, y olvidarnos de las partes más engorrosas.</p>
<p>Pues nada, espero que os haya gustado el artículo, y recordar que si encontráis alguna librería que os gustaría que analizáramos aquí, hacérmelo saber.</p>
<p>Como siempre, <a href="http://www.migueldiazrubio.com/wp-content/uploads/2013/04/BlogParser.zip" target="_blank">os dejo aqui el enlace para descargar el ejemplo completo</a> por si queréis verlo con más detalle.
<div class="ptl_div"><a href="http://twitter.com/share" class="twitter-share-button" data-url="http://www.migueldiazrubio.com/2013/04/23/desarrollo-ios-crea-tu-propio-lector-rss/" data-text="Desarrollo iOS: Crea tu propio lector RSS con MWFeedParser" data-count="horizontal">Tweet</a></div>
<p>The post <a href="http://www.migueldiazrubio.com/2013/04/23/desarrollo-ios-crea-tu-propio-lector-rss/">Desarrollo iOS: Crea tu propio lector RSS con MWFeedParser</a> appeared first on <a href="http://www.migueldiazrubio.com">Miguel Diaz Rubio</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://www.migueldiazrubio.com/2013/04/23/desarrollo-ios-crea-tu-propio-lector-rss/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Snippets iOS: Métodos para recorrer colecciones</title>
		<link>http://www.migueldiazrubio.com/2013/04/19/snippets-ios-metodos-para-recorrer-colecciones/</link>
		<comments>http://www.migueldiazrubio.com/2013/04/19/snippets-ios-metodos-para-recorrer-colecciones/#comments</comments>
		<pubDate>Fri, 19 Apr 2013 08:00:10 +0000</pubDate>
		<dc:creator>migueldiazrubio</dc:creator>
				<category><![CDATA[Snippets iOS]]></category>

		<guid isPermaLink="false">http://www.migueldiazrubio.com/?p=994</guid>
		<description><![CDATA[<p>Existen muchos métodos para recorrer colecciones. Apren [...]</p><p>The post <a href="http://www.migueldiazrubio.com/2013/04/19/snippets-ios-metodos-para-recorrer-colecciones/">Snippets iOS: Métodos para recorrer colecciones</a> appeared first on <a href="http://www.migueldiazrubio.com">Miguel Diaz Rubio</a>.</p>]]></description>
				<content:encoded><![CDATA[<p><span style="font-size: 13px; line-height: 19px;">Existen muchos métodos para recorrer colecciones</span><span style="font-size: 13px; line-height: 19px;">. Aprende lo mejor de cada uno de ellos.</span></p>
<p><span id="more-994"></span></p>
<p>En este artículo vamos a hablar sobre los diferentes métodos existentes para recorrer colecciones en <strong>Objective-C</strong>.</p>
<h2>Métodos para recorrer colecciones</h2>
<p>Principalmente existen 4 métodos, que quizás podrían verse como la evolución cronológica de una misma problemática: bucle básico, <strong>NSEnumerator</strong>, <strong>NSFastEnumeration</strong>, y por último el reciente método mediante <strong>bloques</strong>. A continuación vamos a ir viendo ejemplos de cada uno de ellos, analizando cuales son las diferentes y qué debemos elegir en cada caso.</p>
<h2>Bucle básico (for)</h2>

<div class="wp_codebox"><table><tr id="p994115"><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code" id="p994code115"><pre class="objc" style="font-family:monospace;"><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a> <span style="color: #002200;">*</span>array <span style="color: #002200;">=</span> ...;
<span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span>NSUInteger i <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span> ; i &lt; <span style="color: #002200;">&#91;</span>array count<span style="color: #002200;">&#93;</span>; i<span style="color: #002200;">++</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
	<span style="color: #a61390;">id</span> objeto <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>array objectAtIndex<span style="color: #002200;">:</span>i<span style="color: #002200;">&#93;</span>;
	<span style="color: #11740a; font-style: italic;">// Hacemos lo que queramos con el objeto</span>
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Este es el mas simple de todos los métodos, y común a muchos lenguajes de programación, estamos ante un método que normalmente no se utilizará en aplicaciones para <strong>iOS</strong>. No esta mal, pero no es nada eficiente.</p>
<h2>NSEnumerator</h2>

<div class="wp_codebox"><table><tr id="p994116"><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code" id="p994code116"><pre class="objc" style="font-family:monospace;"><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSEnumerator_Class/"><span style="color: #400080;">NSEnumerator</span></a> <span style="color: #002200;">*</span>enumerador <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>array objectEnumerator<span style="color: #002200;">&#93;</span>;
<span style="color: #a61390;">id</span> objeto;
<span style="color: #a61390;">while</span><span style="color: #002200;">&#40;</span>objeto <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>enumerador nextObject<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
	<span style="color: #11740a; font-style: italic;">// Hacemos lo que queramos con el objeto</span>
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>En este caso, estamos empleando un <strong>enumerador</strong> (Lo que sería en <strong>Java</strong> un objeto <strong>Iterator</strong>), que nos permite no tener que analizar previamente y durante el transcurso del recorrido, el tamaño del array o el elemento en que nos encontramos.</p>
<p>Aunque esto supone una clara ventaja de rendimiento, supone así mismo una desventaja en algunos casos, como es no contar con el índice en el que nos encontramos.</p>
<h2>NSFastEnumeration</h2>

<div class="wp_codebox"><table><tr id="p994117"><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code" id="p994code117"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span> objeto <span style="color: #a61390;">in</span> array<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
	<span style="color: #11740a; font-style: italic;">// Hacemos lo que queramos con el objeto</span>
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>En este tercer caso, la enumeración es aún mas rápida que la anterior, y ademas estamos reduciendo considerablemente el tamaño del código. Sin embargo, y aunque efectivamente su rendimiento es superior al anterior, seguimos encontrándonos con el problema del índice.</p>

<div class="wp_codebox"><table><tr id="p994118"><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code" id="p994code118"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">for</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span> key <span style="color: #a61390;">in</span> diccionario<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
	<span style="color: #a61390;">id</span> objeto <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>dictionario objectForKey<span style="color: #002200;">:</span>key<span style="color: #002200;">&#93;</span>;
        <span style="color: #11740a; font-style: italic;">// Hacemos lo que queramos con el objeto</span>
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Además, en el caso de estar aplicando esto mismo a un <strong>NSDictionary</strong>, ya sea mediante el método <strong>NSEnumerator</strong> o bien <strong>NSFastEnumeration</strong>, en ambos casos estaríamos ante un mismo problema: en la iteración recuperaríamos únicamente el <strong>key</strong> del diccionario, y sería necesaria una segunda llamada para obtener el <strong>objeto</strong> asociado a dicho <strong>key</strong>. Esta segunda llamada echa por tierra la eficiencia aportada por <strong>NSFastEnumeration</strong>.</p>
<h2>Mediante bloques: enumerateObjectsUsingBlock</h2>
<p>En este caso, estaríamos haciendo uso de <strong>bloques</strong>, lo cual obliga al usuario a tener al menos<strong> iOS 4 </strong>(¿quedará alguien con <strong>iOS 3</strong>?).</p>
<p>El código quedaría como sigue:</p>

<div class="wp_codebox"><table><tr id="p994119"><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code" id="p994code119"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">&#91;</span>array enumerateObjectsUsingBlock<span style="color: #002200;">:</span> <span style="color: #002200;">^</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span> objeto, NSUInteger indice, <span style="color: #a61390;">BOOL</span> <span style="color: #002200;">*</span>stop<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #11740a; font-style: italic;">// Hacemos lo que queramos con el objeto</span>
<span style="color: #002200;">&#125;</span><span style="color: #002200;">&#93;</span>;</pre></td></tr></table></div>

<p>Como se puede ver, en este caso cubrimos mucho de los comentado anteriormente. Tenemos acceso al índice gratuitamente, y ademas contamos con una variable <strong>BOOL</strong> que nos permite salir de la sentencia de control en cualquier momento, como si de un <strong>break</strong> se tratase.</p>

<div class="wp_codebox"><table><tr id="p994120"><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code" id="p994code120"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">&#91;</span>diccionario enumerateKeysAndObjectsUsingBlock<span style="color: #002200;">:</span> <span style="color: #002200;">^</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span> key, <span style="color: #a61390;">id</span> objeto, <span style="color: #a61390;">BOOL</span> <span style="color: #002200;">*</span>stop<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #11740a; font-style: italic;">// Hacemos lo que queramos con el objeto</span>
<span style="color: #002200;">&#125;</span><span style="color: #002200;">&#93;</span>;</pre></td></tr></table></div>

<p>En el caso de <strong>NSDictionary</strong>, podemos ver que de nuevo contamos con una gran ventaja, y es la capacidad de recuperar los <strong>key</strong> y los <strong>value</strong> del diccionario de forma simultanea y sin código adicional. Esto supone un ahorro considerable.</p>
<h2>Resumen final</h2>
<p>Pues aunque llegados a este punto del artículo, todos podáis estar pensando que la mejor opción es la última, quizás debe ser algo que valoréis en cada caso. En enumeraciones muy sencillas, el recorrer mediante un bloque, puede tener un rendimiento inferior a <strong>NSFastEnumeration</strong>, y en casos en que nos encontremos con <strong>NSDictionary</strong> puede que el mejor camino si sean los bloques.</p>
<p>Quizás los dos primeros métodos si podrían descartarse en el día a día.</p>
<p>Tratar de lograr un código lo más limpio posible, y adaptar las posibilidades que <strong>Apple</strong> nos ofrece, a cada caso concreto en vuestros desarrollos. Ese creo que puede ser, el mejor consejo.
<div class="ptl_div"><a href="http://twitter.com/share" class="twitter-share-button" data-url="http://www.migueldiazrubio.com/2013/04/19/snippets-ios-metodos-para-recorrer-colecciones/" data-text="Snippets iOS: Métodos para recorrer colecciones" data-count="horizontal">Tweet</a></div>
<p>The post <a href="http://www.migueldiazrubio.com/2013/04/19/snippets-ios-metodos-para-recorrer-colecciones/">Snippets iOS: Métodos para recorrer colecciones</a> appeared first on <a href="http://www.migueldiazrubio.com">Miguel Diaz Rubio</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://www.migueldiazrubio.com/2013/04/19/snippets-ios-metodos-para-recorrer-colecciones/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
	</channel>
</rss>
