<?xml version='1.0' encoding='UTF-8'?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/" xmlns:blogger="http://schemas.google.com/blogger/2008" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-33066466</atom:id><lastBuildDate>Wed, 06 Aug 2025 10:45:59 +0000</lastBuildDate><category>genexus</category><category>desarrollo</category><category>reflexiones</category><category>útiles</category><category>tecnología</category><category>eventos</category><category>google</category><category>internet</category><category>iphone</category><category>uruguay</category><category>objective-c</category><category>web 2.0</category><category>genexus extensions</category><category>genexus rocha</category><category>curiosidades</category><category>sugerencias</category><category>blog</category><category>astronomía</category><category>gx_meeting</category><category>libros</category><category>presentaciones</category><category>apple</category><category>microsoft</category><category>c#</category><category>ciencia</category><category>collaborative proyects</category><category>open source</category><category>user controls</category><category>varios</category><category>apps</category><category>celulares</category><category>email</category><category>genexus_x_ev2</category><category>ipad</category><category>mac_os_x</category><category>televisión</category><category>almacenamiento</category><category>firefox</category><category>flickr</category><category>ruby</category><category>running</category><category>twitter</category><category>xcode</category><category>educación</category><category>facebook</category><category>fotografía</category><category>fútbol</category><category>linux</category><category>música</category><category>redes sociales</category><category>rss</category><category>ruby_on_rails</category><category>subversion</category><category>ted</category><category>testeo</category><category>windows</category><category>android</category><category>asp.net</category><category>git</category><category>nintendo</category><category>office</category><category>openId</category><category>películas</category><category>php</category><category>piensopienso</category><category>reconocimientos</category><category>seguridad</category><category>tags</category><title>Blog de Marcos Crispino</title><description>Sobre desarrollo de software, tecnología, y algunas otras cosas</description><link>http://mcrispino.blogspot.com/</link><managingEditor>noreply@blogger.com (Unknown)</managingEditor><generator>Blogger</generator><openSearch:totalResults>320</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><item><guid isPermaLink="false">tag:blogger.com,1999:blog-33066466.post-5229427327799207615</guid><pubDate>Sat, 04 Oct 2014 22:20:00 +0000</pubDate><atom:updated>2014-10-04T19:20:00.493-03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">libros</category><category domain="http://www.blogger.com/atom/ns#">reflexiones</category><title>No hemos cambiado nada</title><description>Dentro de unos días, en Uruguay vamos a tener elecciones parlamentarias y presidenciales. Como siempre en estos casos hay campaña y hay temas que se destacan por sobre otros.&lt;br /&gt;
&lt;br /&gt;
Uno de los temas a los que más importancia se le ha dado, es el de la seguridad pública. Más allá de los argumentos y posturas que cada uno pueda tener, me interesaba comentar una frase que leí hace poco.&lt;br /&gt;
&lt;br /&gt;
Para ponerle un poco de contexto, es una frase en medio de un diálogo, que transcribo:&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;i&gt;- ¿Hablan ustedes del asesinato [...]?&lt;br /&gt;- Sí. ¿Ha oído usted hablar de este crimen?&lt;br /&gt;- ¿Cómo no? Ha ocurrido en las cercanías de la casa donde me hospedo.&lt;br /&gt;- ¿Conoce usted los detalles?&lt;br /&gt;- Los detalles, no, pero este asunto me interesa por la cuestión general que plantea. &lt;b&gt;Dejemos a un lado el aumento incesante de la criminalidad durante los últimos cinco años en las clases bajas&lt;/b&gt;. [...]&lt;/i&gt;&lt;/blockquote&gt;
Y resalto &quot;&lt;i&gt;&lt;b&gt;el aumento incesante de la criminalidad durante los últimos cinco años&lt;/b&gt;&lt;/i&gt;&quot;. Parece sin duda una frase sacada del debate previo a las elecciones. De hecho, podría ser una frase de cualquier debate electoral de cualquier parte del mundo, de los últimos tiempos.&lt;br /&gt;
&lt;br /&gt;
Nosotros, los que vivimos de la tecnología, pensamos que el mundo cambia muy rápido. Sin embargo, hay cosas que no cambian...&lt;br /&gt;
&lt;br /&gt;
De hecho, este diálogo es de la novela &lt;a href=&quot;http://www.amazon.com/gp/product/B005EGQSP6/ref=as_li_tl?ie=UTF8&amp;amp;camp=1789&amp;amp;creative=390957&amp;amp;creativeASIN=B005EGQSP6&amp;amp;linkCode=as2&amp;amp;tag=blodemarcri-20&amp;amp;linkId=NQOUVCCR5D3RDW73&quot;&gt;Crimen y Castigo&lt;/a&gt;, escrita en Rusia en 1866 por &lt;a href=&quot;http://es.wikipedia.org/wiki/Fi%C3%B3dor_Dostoyevski&quot;&gt;Fiódor Dostoyevsky&lt;/a&gt;, y todo parece indicar que hace 150 años, tenían más o menos los mismos problemas que tenemos hoy en día.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;</description><link>http://mcrispino.blogspot.com/2014/10/no-hemos-cambiado-nada.html</link><author>noreply@blogger.com (Unknown)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-33066466.post-5311897863698122013</guid><pubDate>Thu, 02 Oct 2014 14:57:00 +0000</pubDate><atom:updated>2014-10-02T11:57:05.877-03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">eventos</category><category domain="http://www.blogger.com/atom/ns#">genexus</category><title>GX24</title><description>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdZAYnaTY0RYJWAAqSv8K5lcYaTgGI2EWSgDjloqYQFYYxn6iY5p26eKS0QrZHLSGxqZRfdEG8X7xWEF-vpY7YoC2UGZkZhkuytXTeBN36MaCQEoIcCgnv1Qspz9sDnlRgHHZ0/s1600/GX24.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdZAYnaTY0RYJWAAqSv8K5lcYaTgGI2EWSgDjloqYQFYYxn6iY5p26eKS0QrZHLSGxqZRfdEG8X7xWEF-vpY7YoC2UGZkZhkuytXTeBN36MaCQEoIcCgnv1Qspz9sDnlRgHHZ0/s1600/GX24.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Se terminó otro Encuentro GeneXus, el número 24 en esta oportunidad. Otra vez un muy buen evento con una organización impecable y charlas de muy buen nivel.&lt;br /&gt;
&lt;br /&gt;
Hubo muchas charlas interesantes, no pude ver todas las que quería así que ahora me tengo que poner al día.&lt;br /&gt;
&lt;br /&gt;
Sobre la temática de las charlas, vi que hubo muchas charlas sobre diseño. Es una opinión subjetiva, pero creo que muchas más que en eventos anteriores. No creo que sea casualidad que se hable tanto de diseño: en la medida que maduran las plataformas (Smart Devices en particular, pero también Web) y los usuarios se acostumbran a aplicaciones de mejor nivel de diseño, nos exige a nosotros los desarrolladores de aplicaciones a pensar más en este tema.&lt;br /&gt;
&lt;br /&gt;
Una conclusión a la que todos llegan, es que el diseño tiene que ser parte del desarrollo de la aplicación desde el primer momento, y no ser algo que se agrega luego de terminar la funcionalidad.&lt;br /&gt;
&lt;br /&gt;
También vi que hubo muchas charlas sobre &quot;cloud computing&quot;, otro tema que cobra cada vez más importancia.&lt;br /&gt;
&lt;br /&gt;
Con respecto a mi charla, creo que salió bien. El tema era &quot;Sincronización en aplicaciones Offline&quot;, y la idea era hacer una charla de unos 15 minutos y luego dejar otros 15 para preguntas. Debo reconocer que me daba un poco de miedo que no hubiera preguntas, o que fueran muy específicas o de errores puntuales que alguien pudiera tener. Pero por suerte no, las preguntas fueron lo suficientemente generales y de buen nivel, así que todo bien :)&lt;br /&gt;
&lt;br /&gt;
Si quieren ver &lt;a href=&quot;http://www5.genexus.com/Meeting2014/Schedule.aspx?87#30/09/14:3585&quot;&gt;la charla, está disponible en el sitio del evento&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;</description><link>http://mcrispino.blogspot.com/2014/10/gx24.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdZAYnaTY0RYJWAAqSv8K5lcYaTgGI2EWSgDjloqYQFYYxn6iY5p26eKS0QrZHLSGxqZRfdEG8X7xWEF-vpY7YoC2UGZkZhkuytXTeBN36MaCQEoIcCgnv1Qspz9sDnlRgHHZ0/s72-c/GX24.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-33066466.post-5114874077549184631</guid><pubDate>Wed, 14 May 2014 21:49:00 +0000</pubDate><atom:updated>2014-05-14T18:49:30.277-03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">running</category><title>I Maratón de Montevideo</title><description>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzPoFDXla3LUrksYQxN9rChcXynBoBiRT_zPtlv1WZp6N944GGxvSLuwzPlqDKr1wnVvdzG-IgcRNx47WaF2LXyuxI6yfYYABu_cTYK438H4oYOPLs16-jcSEXYy04d3MZ5kNt/s1600/Medalla.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzPoFDXla3LUrksYQxN9rChcXynBoBiRT_zPtlv1WZp6N944GGxvSLuwzPlqDKr1wnVvdzG-IgcRNx47WaF2LXyuxI6yfYYABu_cTYK438H4oYOPLs16-jcSEXYy04d3MZ5kNt/s1600/Medalla.png&quot; height=&quot;200&quot; width=&quot;150&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
El pasado domingo 11 de mayo de 2014 se llevó a cabo la primer edición de la &lt;a href=&quot;http://maraton.montevideo.gub.uy/&quot;&gt;Maratón de Montevideo&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Con un tiempo de 4 horas y 43 minutos logré completar el recorrido de 42.195 metros, por lo que ahora puedo decir que soy maratonista :)&lt;br /&gt;
&lt;br /&gt;
Por qué correr una maratón es una pregunta que me han hecho bastante. Seguramente haya tantas respuestas como corredores, en mi caso lo que quería era demostrarme a mi mismo que era capaz de hacerlo. &lt;a href=&quot;http://blog.marcoscrispino.com/2013/04/mi-primer-media-maraton.html&quot;&gt;Habiendo corrido 21 kilómetros en 2013&lt;/a&gt;, parecía un desafío interesante.&lt;br /&gt;
&lt;br /&gt;
No me había puesto meta de tiempo, sabía que bajar de 4 horas y media iba a ser difícil por los tiempos que estaba haciendo en los entrenamientos, y esperaba poder hacerlo en menos de 5 horas. El límite máximo, puesto por la organización, era de 6 horas.&lt;br /&gt;
&lt;br /&gt;
Hablando del entrenamiento, fueron 16 semanas de actividad cada vez más exigente, con 4 actividades semanales y llegando a correr más de 60 kilómetros por semana, con un máximo de 32km en una oportunidad. Es un entrenamiento bastante duro, pero totalmente necesario para lograr completar la carrera.&lt;br /&gt;
&lt;br /&gt;
La organización de la carrera fue impecable. La carrera largó en hora, el circuito estuvo bien señalizado con carteles para los kilómetros, los puntos de hidratación estuvieron siempre bien abastecidos con agua, Gatorade, frutas y gel de carbohidratos como estaba planificado. La única queja tal vez es que demoraron mucho en publicar la información oficial, pero del día de la carrera no tengo ninguna queja.&lt;br /&gt;
&lt;br /&gt;
&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;float: right; margin-left: 1em; text-align: right;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://www.facebook.com/photo.php?fbid=10200967532270295&amp;amp;set=a.10200967470868760.1073741994.1826030705&amp;amp;type=3&amp;amp;src=https%3A%2F%2Ffbcdn-sphotos-g-a.akamaihd.net%2Fhphotos-ak-frc3%2Ft1.0-9%2F10264415_10200967532270295_5936186634513446733_n.jpg&amp;amp;size=960%2C645&quot; imageanchor=&quot;1&quot; style=&quot;clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_W7kd2XMl4VWGpIlY86C5d39AzQKKZmyYizG2J4IuC0eJezOQmnrhnWZekChR62mfYMCKuaBe_DzqtKT9VhH5ZVKoIapwQBIgHhKNhuRX02C9T7aeHG1BPxQ8V8XxxYMqWG9M/s1600/Carrera.jpg&quot; height=&quot;215&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Foto por &lt;a href=&quot;https://www.facebook.com/mauricio.ramirez.3388&quot;&gt;Mauricio Ramirez&lt;/a&gt;, via Facebook&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
De la carrera en sí, estuvo bueno el &lt;a href=&quot;http://maraton.montevideo.gub.uy/recorridos.html&quot;&gt;recorrido&lt;/a&gt;, bien la gente que acompaño y alentaba todo a lo largo del trayecto, y la verdad que el clima también acompañó, salvo por un poco de viento en contra a la ida por la Rambla.&lt;br /&gt;
&lt;br /&gt;
Me llamó la atención que había mucha gente acompañando a algún corredor en bicicleta, pero si veían que alguien paraba o podía precisar algo, en seguida le preguntaban si estaba bien y si necesitaba agua o fruta.&lt;br /&gt;
&lt;br /&gt;
Con respecto a mi desempeño iba bien hasta pasado el kilómetro 30, venía con un tiempo de unos 6 minutos por kilómetro, pero en ese punto me di contra &lt;a href=&quot;http://en.wikipedia.org/wiki/Hitting_the_wall&quot;&gt;el famoso “muro”&lt;/a&gt; y tuve que caminar un poco para recuperarme. Desde ahí hice corriendo las partes llanas, pero con las subidas no pude, las tuve que hacer caminando. De todas formas el tiempo estuvo dentro de lo que esperaba, así que quedé muy conforme.&lt;br /&gt;
&lt;br /&gt;
Terminé obviamente muy cansado y los días siguientes a la carrera estuve (estoy) con bastante dolor en las piernas (no saben lo que se sufre subiendo un piso por escalera al otro día...), pero como decía un cartel en la carrera “el dolor se va, la gloria es para siempre” :)&lt;br /&gt;
&lt;br /&gt;
Realmente una experiencia recomendable, para hacerlo al menos una vez en la vida… Por lo menos para aquellos que corren y quieren exigirse más.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;</description><link>http://mcrispino.blogspot.com/2014/05/i-maraton-de-montevideo.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzPoFDXla3LUrksYQxN9rChcXynBoBiRT_zPtlv1WZp6N944GGxvSLuwzPlqDKr1wnVvdzG-IgcRNx47WaF2LXyuxI6yfYYABu_cTYK438H4oYOPLs16-jcSEXYy04d3MZ5kNt/s72-c/Medalla.png" height="72" width="72"/><thr:total>2</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-33066466.post-3123161297440058952</guid><pubDate>Fri, 11 Apr 2014 13:13:00 +0000</pubDate><atom:updated>2014-04-11T10:13:34.907-03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">genexus</category><category domain="http://www.blogger.com/atom/ns#">objective-c</category><category domain="http://www.blogger.com/atom/ns#">user controls</category><title>Disparo de eventos desde un User Control GeneXus en iOS</title><description>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9chhW4XqmBFb3WdF1NJaKf7MuQa_DalJtj-eZwmLBijh58s1HFjgZpVh67qBR_jr4W8ppQoOUP9yc-kDv2jXMw85HnAF-Udmf5fMAZviN-XmNZlr8DVXUF_KFLP3r3ExlzLJY/s1600/GXLogo.gif&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9chhW4XqmBFb3WdF1NJaKf7MuQa_DalJtj-eZwmLBijh58s1HFjgZpVh67qBR_jr4W8ppQoOUP9yc-kDv2jXMw85HnAF-Udmf5fMAZviN-XmNZlr8DVXUF_KFLP3r3ExlzLJY/s1600/GXLogo.gif&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Los &lt;a href=&quot;http://wiki.genexus.com/commwiki/servlet/hwikibypageid?5273&quot;&gt;User Controls en GeneXus&lt;/a&gt; permiten extender la funcionalidad provista por los generadores, para resolver escenarios de User Interface que no están resueltos en los controles estandar. Hay varios controles interesantes en el &lt;a href=&quot;http://marketplace.genexus.com/home.aspx?UserControls,es&quot;&gt;Marketplace&lt;/a&gt;, principalmente para Web pero &lt;a href=&quot;http://marketplace.genexus.com/productsearch.aspx?tag%3a%22Smart+Devices%22,0&quot;&gt;también para Smart Devices&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Si bien estos User Controls se utilizan mayormente para cambiar el aspecto visual de las aplicaciones, puede haber casos donde sea necesario ejecutar código del usuario.&lt;br /&gt;
&lt;br /&gt;
En iOS esto es muy fácil de hacer, si la implementación del control hereda de la clase GXControlBase o alguna de sus clases derivadas.&lt;br /&gt;
&lt;br /&gt;
Hay dos forma de hacerlo: disparando una acción del panel o disparando un evento del control.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Disparar una acción del panel&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Para disparar una acción definida en el panel donde se encuentra el User Control, alcanza con incluir el siguiente código:&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;tt&gt;
[self fireActionWithName:actionName userInterfaceContext:nil withEntityData:nil];&lt;/tt&gt;&lt;/blockquote&gt;
donde &lt;i&gt;self&lt;/i&gt; es la implementación del user control y &lt;i&gt;actionName&lt;/i&gt; es el nombre del evento como se definió en GeneXus.&lt;br /&gt;
&lt;br /&gt;
Para poder disparar esta acción, obviamente necesitamos conocer el nombre de la misma. Puede ser fijo (y estar documentado...) o se puede configurar en una propiedad.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Disparar un evento del control&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Otra forma de hacerlo es definiendo un evento en el User Control.&lt;br /&gt;
&lt;br /&gt;
Para esto, debemos indicar en la definición del control que define un evento. Esto se hace en el archivo .control, y la forma de hacerlo es muy simple:&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;tt&gt;
&amp;lt;Events&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Event&amp;gt;NombreDelEvento&amp;lt;/Event&amp;gt;&lt;br /&gt;&amp;lt;/Events&amp;gt;&lt;/tt&gt;&lt;/blockquote&gt;
Luego, en el código GeneXus, podemos escribir:&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;tt&gt;
Event Control.NombreDelEvento&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;br /&gt;EndEvent&lt;/tt&gt;&lt;/blockquote&gt;
Para dispararlo desde el código Objective-C, también en este caso es una línea&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;tt&gt;
[self fireControlEvent:@&quot;NombreDelEvento&quot; userInterfaceContext:nil withEntityData:nil];&lt;/tt&gt;&lt;/blockquote&gt;
Un ejemplo de esto último lo pueden ver en el control SD Paged Grid, que define un evento PageChanged.&lt;br /&gt;
&lt;br /&gt;
Si bien las dos opciones son equivalentes en cuanto a funcionalidad, creo que es mejor la segunda porque queda más fácil de entender el código GeneXus y facilita al usuario la posibilidad de encontrar esta funcionalidad de nuestro control.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;</description><link>http://mcrispino.blogspot.com/2014/04/disparo-de-eventos-desde-un-user.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9chhW4XqmBFb3WdF1NJaKf7MuQa_DalJtj-eZwmLBijh58s1HFjgZpVh67qBR_jr4W8ppQoOUP9yc-kDv2jXMw85HnAF-Udmf5fMAZviN-XmNZlr8DVXUF_KFLP3r3ExlzLJY/s72-c/GXLogo.gif" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-33066466.post-9123434139008532053</guid><pubDate>Tue, 25 Mar 2014 20:20:00 +0000</pubDate><atom:updated>2014-03-25T17:20:51.972-03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">desarrollo</category><category domain="http://www.blogger.com/atom/ns#">genexus</category><category domain="http://www.blogger.com/atom/ns#">iphone</category><title>Cómo hacer una aplicación para iOS en 45 minutos</title><description>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7ndUKAXXktPlCC0mGJ2UJ09mjknEkXVvefeAuYXd-HCy5rxbexROV0d7WuGC0EVYIux1dGVOEO4pxzu3FaGUDtMBb2PZNx5lqTyuFs39ifgZjpYVyntDJuLzo3yirUdXqlvkI/s3200/ios-logo.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7ndUKAXXktPlCC0mGJ2UJ09mjknEkXVvefeAuYXd-HCy5rxbexROV0d7WuGC0EVYIux1dGVOEO4pxzu3FaGUDtMBb2PZNx5lqTyuFs39ifgZjpYVyntDJuLzo3yirUdXqlvkI/s3200/ios-logo.png&quot; height=&quot;79&quot; width=&quot;120&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Es verdad, lo reconozco, el título de la nota es un poco tendencioso&lt;sup&gt;(1)&lt;/sup&gt;... Pero también es verdad lo que dice, que pude hacer una aplicación e instalarla en mi teléfono en 45 minutos, desde la idea hasta tenerla en ejecución.&lt;br /&gt;
&lt;br /&gt;
La aplicación es muy simple, obviamente. Necesitaba tener algunas notas para una presentación que iba a ser sin PPTs, para no olvidarme de decir nada.&lt;br /&gt;
&lt;br /&gt;
En realidad me hubiera servido cualquier aplicación de notas, pero se me ocurrió que podría ser divertido hacer la aplicación, y con &lt;a href=&quot;http://www.genexus.com/&quot;&gt;GeneXus&lt;/a&gt; es realmente fácil, así que me animé.&lt;br /&gt;
&lt;br /&gt;
La aplicación tiene dos entidades con sus respectivos &quot;work with&quot;: Presentaciones y Notas. Las Presentaciónes tienen un Título, las Notas tienen un Titulo y una Descripción. Solo eso.&lt;br /&gt;
&lt;br /&gt;
La otra pantalla que tiene la aplicación es el &quot;modo presentación&quot;, donde se elige la presentación que voy a hacer y se muestran las notas en un &lt;a href=&quot;http://wiki.genexus.com/commwiki/servlet/hwikibypageid?17302&quot;&gt;Paged Grid&lt;/a&gt;, el título más grande y la descripción al pie. Para pasar de una nota a la siguiente, se hace un gesto de &quot;swipe&quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEZ5XJfrsbgyha-s8F1ibCogMUEAsITo-fg_c0-qp4sI6Q8qDzA1ymUttllc-Es2h0mkUzlhpS_y819oYfpBtJXwG3L0POnpNjNZbxABPu6n19ai4AWHPVTfB6y9eKTuZ2clEa/s3200/PresentationNotesApp.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEZ5XJfrsbgyha-s8F1ibCogMUEAsITo-fg_c0-qp4sI6Q8qDzA1ymUttllc-Es2h0mkUzlhpS_y819oYfpBtJXwG3L0POnpNjNZbxABPu6n19ai4AWHPVTfB6y9eKTuZ2clEa/s3200/PresentationNotesApp.png&quot; height=&quot;200&quot; width=&quot;106&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Lo otro que es interesante, es que la aplicación es 100% &lt;a href=&quot;http://wiki.genexus.com/commwiki/servlet/hwikibypageid?20286&quot;&gt;offline&lt;/a&gt;. De hecho, si la hubiese querido hacer online hubiera sido más difícil, porque tendría que haber usado &lt;a href=&quot;http://wiki.genexus.com/commwiki/servlet/hwikibypageid?24746&quot;&gt;seguridad&lt;/a&gt; o como mínimo agregar el &lt;a href=&quot;http://wiki.genexus.com/commwiki/servlet/hwikibypageid?20198&quot;&gt;Device Id&lt;/a&gt; a todas las tablas para saber a quién corresponde cada presentación.&lt;br /&gt;
&lt;br /&gt;
No intenté pasarla a Android, pero en cuanto a UI es todo por defecto, así que debería funcionar bien sin mucho esfuerzo.&lt;br /&gt;
&lt;br /&gt;
Si a alguien le interesa la puedo publicar en algún GeneXus Server...&lt;br /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;sup&gt;(1)&lt;/sup&gt;En realidad no se puede considerar una aplicación terminada, porque le faltan los iconos e imágenes, y todo el proceso de publicación en el Store, pero la aplicación está funcionando y cumple con su objetivo.</description><link>http://mcrispino.blogspot.com/2014/03/como-hacer-una-aplicacion-para-ios-en.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7ndUKAXXktPlCC0mGJ2UJ09mjknEkXVvefeAuYXd-HCy5rxbexROV0d7WuGC0EVYIux1dGVOEO4pxzu3FaGUDtMBb2PZNx5lqTyuFs39ifgZjpYVyntDJuLzo3yirUdXqlvkI/s72-c/ios-logo.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-33066466.post-950777586346648852</guid><pubDate>Thu, 20 Feb 2014 22:16:00 +0000</pubDate><atom:updated>2014-02-20T20:16:00.219-02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">desarrollo</category><category domain="http://www.blogger.com/atom/ns#">objective-c</category><title>Operador condicional ternario en Objective-C</title><description>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOSetojcLobUZ8Rnv1UmjQ4A6HFN7kvj4gGvJS1GGhDII9eYV6AIlk2jOKqEONBqFd2_OZRvzqOhXZg5Wh_pUZUQOirL2559dbpI75rsKjggMIl52Dx8OwlSZii0e5hiFv1fJ8/s1600/xcode_logo.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOSetojcLobUZ8Rnv1UmjQ4A6HFN7kvj4gGvJS1GGhDII9eYV6AIlk2jOKqEONBqFd2_OZRvzqOhXZg5Wh_pUZUQOirL2559dbpI75rsKjggMIl52Dx8OwlSZii0e5hiFv1fJ8/s1600/xcode_logo.png&quot; height=&quot;120&quot; width=&quot;120&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
En la muchos lenguajes de programación (en los que provienen de C al menos...) existe un operador condicional ternario de la forma&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;tt&gt;
&lt;i&gt;condición&lt;/i&gt; ? &lt;i&gt;expresión1&lt;/i&gt; : &lt;i&gt;expresión2&lt;/i&gt;&lt;/tt&gt;&lt;/blockquote&gt;
que evalúa la &lt;i&gt;condición&lt;/i&gt;, y el resultado de la expresión completa será &lt;i&gt;expresión1&lt;/i&gt; o &lt;i&gt;expresión2&lt;/i&gt; según el la condición evalúe a &lt;i&gt;true&lt;/i&gt; o &lt;i&gt;false&lt;/i&gt; respectivamente.&lt;br /&gt;
&lt;br /&gt;
En Objecive-C, la &lt;i&gt;condición&lt;/i&gt; debe ser evaluable como una expresión booleana, por lo que se puede usar un objeto, y en ese caso el significado es el mismo que preguntar si el objeto es distinto de &lt;i&gt;nil&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
Por otro lado, Objective-C adopta una convención del compilador GCC (según &lt;a href=&quot;http://stackoverflow.com/a/8760625/135050&quot;&gt;esta respuesta&lt;/a&gt; en StackOverflow), donde la &lt;i&gt;expresión1&lt;/i&gt; es opciona, pudiendo escribir&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;tt&gt;
&lt;i&gt;condición&lt;/i&gt; ? : &lt;i&gt;expresión2&lt;/i&gt;&lt;/tt&gt;&lt;/blockquote&gt;
y en ese caso, si la &lt;i&gt;condición&lt;/i&gt; es verdadera, será además el resultado de la expresión completa.&lt;br /&gt;
&lt;br /&gt;
¿Para qué sirve todo esto? Sirve por ejemplo para escribir una asignación cuando el valor asignado puede ser &lt;i&gt;nil&lt;/i&gt; y en ese caso queremos asignar un valor por defecto. Algo así:&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;tt&gt;
id obj = someValue ? : @&quot;&quot;;&lt;/tt&gt;&lt;/blockquote&gt;
Creo que el código queda bastante más simple y entendible (una vez que conocemos como funciona el operador) que hacerlo con if:&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;tt&gt;
id obj = someValue;&lt;br /&gt;
if (!obj) {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; obj = @&quot;&quot;;&lt;br /&gt;
} &lt;/tt&gt;&lt;/blockquote&gt;
También tiene la ventaja que la expresión se evalúa una sola vez, lo cual es útil cuando la expresión puede ser compleja, y necesario cuando la expresión puede tener efectos secundarios.&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;tt&gt;
id obj = [[some complicated] expresion] ? : @&quot;&quot;;&lt;/tt&gt;&lt;/blockquote&gt;
Por último, al escribir solamente una vez la expresión que queremos evaluar, eliminamos código duplicado lo que, como todos sabemos, es fuente de errores.&lt;br /&gt;
&lt;br /&gt;</description><link>http://mcrispino.blogspot.com/2014/02/operador-condicional-ternario-en.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOSetojcLobUZ8Rnv1UmjQ4A6HFN7kvj4gGvJS1GGhDII9eYV6AIlk2jOKqEONBqFd2_OZRvzqOhXZg5Wh_pUZUQOirL2559dbpI75rsKjggMIl52Dx8OwlSZii0e5hiFv1fJ8/s72-c/xcode_logo.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-33066466.post-4763236178351622728</guid><pubDate>Thu, 09 Jan 2014 18:03:00 +0000</pubDate><atom:updated>2014-01-09T16:03:54.603-02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">desarrollo</category><category domain="http://www.blogger.com/atom/ns#">genexus</category><category domain="http://www.blogger.com/atom/ns#">iphone</category><category domain="http://www.blogger.com/atom/ns#">útiles</category><title>Finanzas.app</title><description>Como comentaba &lt;a href=&quot;https://twitter.com/rorro&quot;&gt;Rodrigo&lt;/a&gt; en su blog &lt;a href=&quot;http://neuronafinanciera.com/registro-de-gastos-2/&quot;&gt;Neurona Financiera&lt;/a&gt;, el registro de nuestros gastos es fundamental si queremos tener controladas nuestras finanzas. Yo también pasé como él por varias etapas: una planilla Excel, un programa Visual Fox Pro hecho con GeneXus 9.0 que después migró a .Net, una aplicación web en Google App Engine.&lt;br /&gt;
&lt;br /&gt;
Finanzas.app es la siguiente iteración en este ciclo, está desarrollada en &lt;a href=&quot;http://wiki.gxtechnical.com/commwiki/servlet/hwikibypageid?23693&quot;&gt;GeneXus Tilo B3&lt;/a&gt;, y es una aplicación que funciona completamente desconectada.&lt;br /&gt;
&lt;br /&gt;
El hecho de que sea Offline es el punto fuerte de la aplicación. Seguramente no se compara en funcionalidad con las alternativas (por ejemplo &lt;a href=&quot;http://www.zetasoftware.com/zetacuentas&quot;&gt;ZetaCuentas&lt;/a&gt; por nombrar otra hecha con GeneXus), pero me permite tener los datos locales sin que intervenga un tercero. No me considero extremadamente paranoico, pero cuando hablamos de dinero, prefiero no darle la información a otros...&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Cómo obtener la aplicación&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
La aplicación la estoy desarrollando para uso personal, por lo que no me interesa distribuirla en formato binario. Esto implica que no está en mis planes publicarla en los Stores, ya que eso requiere de un trabajo que no me aporta valor en esta etapa.&lt;br /&gt;
&lt;br /&gt;
Sin embargo, sí creo que puede resultar útil a otras personas, por lo que estoy dejando disponible la base de conocimiento en un GeneXus Server. La licencia que decidí usar es la de &lt;a href=&quot;http://en.wikipedia.org/wiki/MIT_License&quot;&gt;MIT&lt;/a&gt; como &lt;a href=&quot;http://blog.marcoscrispino.com/2013/12/licencias-de-software-libre-cual-usar.html&quot;&gt;comentaba hace unos días en el blog&lt;/a&gt;, porque creo que es la menos restrictiva en cuanto a lo que se puede hacer con los fuentes.&lt;br /&gt;
&lt;br /&gt;
La URL para obtenerla es: &lt;a href=&quot;http://open.genexusserver.com/tilo/home.aspx?FinanzasOffline,0&quot;&gt;http://open.genexusserver.com/tilo/home.aspx?FinanzasOffline,0&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
La aplicación está funcionando en mi iPhone con iOS 7, no la probé en otras plataformas ni en otros dispositivos...&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Modelo de datos&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
En cuanto al modelo de datos, es muy sencilla, consiste solamente de cuatro tablas: Movimientos, Monedas, Rubros y Tipos de Rubro.&lt;br /&gt;
&lt;br /&gt;
La tabla principal es donde se registran los Movimientos, que están compuestos por una Fecha, un Origen y un Destino. Tanto el origen como el destino consisten de una Moneda, un Rubro y un Importe.&lt;br /&gt;
&lt;br /&gt;
Así por ejemplo, un movimiento puede ser: Fecha: 9/1/2014, Origen: $100 efectivo, Destino: $100 almuerzo. El origen es de donde sale la plata, el destino es a donde va.&lt;br /&gt;
&lt;br /&gt;
Sobre las Monedas no hay mucho para decir, tienen un nombre, un símbolo y una descrpción corta para usar en el ingreso rápido (ver más adelante la explicación).&lt;br /&gt;
&lt;br /&gt;
Los Rubros tienen una descripción y un Tipo de Rubro, que es una forma de agruparlos. A su vez cada Tipo de Rubro puede ser un Ingreso, un Gasto o un Activo (es decir dinero; contadores abstenerse, seguramente el nombre no es el adecuado).&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&amp;nbsp;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgi4Kdq8zvWCNynrFk8rBPDtWYTpvSiX63TGPKxcq4oETGUGeHgnRKkWoz1QtjlH-GvuIXYuWD_RrzrEKdDVpk9IhImrVwDfFETJfegYtncgMyaFhiDxFxmaYO_LIxWreru2ok8/s1600/Finanzas_ModeloDatos.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgi4Kdq8zvWCNynrFk8rBPDtWYTpvSiX63TGPKxcq4oETGUGeHgnRKkWoz1QtjlH-GvuIXYuWD_RrzrEKdDVpk9IhImrVwDfFETJfegYtncgMyaFhiDxFxmaYO_LIxWreru2ok8/s1600/Finanzas_ModeloDatos.png&quot; height=&quot;161&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;b&gt;Ingreso rápido&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
En cuanto a funcionalidad tampoco hay mucho para decir. La característica principal es el &quot;Ingreso rápido&quot;, que agiliza mucho el registro de movimientos. Esto es fundamental para que no nos resulte pesado el registro, para que no dejemos de usar la aplicación.&lt;br /&gt;
&lt;br /&gt;
De hecho, el ingreso rápido es la primer pantalla que nos encontramos al abrir la aplicación. Allí vamos a ver simplemente dos campos: una fecha y una descripción.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4WetmbUO2c93ToxgE4rdXmoMuSNNPtWCGoJKk5n3t-pUzYQCi-gP750ay0YrGU46lQ3wCMXjkbJIOYzJTHmqd5DtiJ1z1OeDXzDDzT11xdaylS-YbBf-km6aoKElS-rUiglOt/s1600/Finanzas_IngRapido.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4WetmbUO2c93ToxgE4rdXmoMuSNNPtWCGoJKk5n3t-pUzYQCi-gP750ay0YrGU46lQ3wCMXjkbJIOYzJTHmqd5DtiJ1z1OeDXzDDzT11xdaylS-YbBf-km6aoKElS-rUiglOt/s1600/Finanzas_IngRapido.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
La descripción debe tener el siguiente formato:&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;i&gt;&amp;lt;moneda origen&amp;gt; &amp;lt;importe origen&amp;gt; &amp;lt;rubro origen&amp;gt;, &amp;lt;moneda destino&amp;gt; &amp;lt;importe destino&amp;gt; &amp;lt;rubro destino&amp;gt;&lt;/i&gt;&lt;/blockquote&gt;
con las siguientes reglas:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;la &lt;i&gt;&amp;lt;moneda origen&amp;gt;&lt;/i&gt; se puede omitir, y en dicho caso se usa la moneda por defecto (que se configura en los parámetros de la aplicación)&lt;/li&gt;
&lt;li&gt;el &lt;i&gt;&amp;lt;rubro origen&amp;gt;&lt;/i&gt; se puede omitir, en cuyo caso se usa el rubro por defecto&lt;/li&gt;
&lt;li&gt;la &lt;i&gt;&amp;lt;moneda destino&amp;gt;&lt;/i&gt; se puede omitir, en cuyo caso se usa la &lt;i&gt;&amp;lt;moneda origen&amp;gt;&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;el &lt;i&gt;&amp;lt;importe destino&amp;gt;&lt;/i&gt; se puede omitir, en cuyo caso se usa el &lt;i&gt;&amp;lt;importe origen&amp;gt;&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;el &lt;i&gt;&amp;lt;rubro destino&amp;gt;&lt;/i&gt; se puede omitir, en cuyo caso se usa el rubro por defecto&lt;/li&gt;
&lt;li&gt;para las monedas se usa la descripción corta que es un Character(3)&lt;/li&gt;
&lt;li&gt;para los rubros se busca por LIKE, y se queda con el primero que encuentra &lt;/li&gt;
&lt;/ul&gt;
Esto permite que el ingreso sea muy sencillo. En el ejemplo que ponía antes, lo único que tengo que escribir es: &quot;100, alm&quot;, suponiendo que el rubro por defecto es Efectivo y la moneda es Pesos.&lt;br /&gt;
&lt;br /&gt;
Si quiero registrar un retiro de $1000 del banco, tengo que escribir simplemente &quot;1000 banco&quot;; y si quisiera que fuera en dólares (suponiendo que la descripción corta es &quot;usd&quot;) debería escribir &quot;usd 1000 banco&quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Configuración inicial&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Evidentemente la organización de nuestras finanzas es algo bastante personal, por lo que los rubros que cada uno defina serán los que le sirvan.&lt;br /&gt;
&lt;br /&gt;
Podemos hacer la carga inicial de forma manual usando los &quot;work with&quot;, pero esto puede ser bastante tediosos. Para facilitar la tarea, hay un data provider en la KB (llamado DatosInicialesRubros) que hace la carga inicial de Rubros y Tipos de Rubro, que cada uno deberá modificar de acuerdo a sus necesidades.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Consultas&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
La aplicación por el momento tiene solamente dos consultas: Resumen mensual y Saldos&lt;br /&gt;
&lt;br /&gt;
El Resumen mensual muestra por Tipo de Rubro y Moneda, todos los movimientos que sean Ingreso o Gasto del mes. Se puede consultar para el mes actual y para el mes anterior.&lt;br /&gt;
&lt;br /&gt;
La consulta de Saldos muestra por Rubro y Moneda para aquellos rubros que son de Activos, el saldo a la fecha especificada. La fecha puede ser hoy, el mes anterior o el año anterior.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Estado actual y futuro&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Esta aplicación es la que estoy usando para el registro de gastos, desde el 1º de enero dejé de usar la aplicación que tenía antes. Por lo tanto, puedo decir que la aplicación está en producción y con el sello de calidad:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfDJo91pTk9cwuYP_-Ewd3xyerQSx6ctP6vOcmSP4i8HgqJRNl9JOBFo6F7EljzXqePA_NWaYZ66uuoK3Gk718PQlUz_od3gPhn8M3ZvGsGserPLugsoZI2HCviFqZIz2VwkWV/s1600/works-on-my-machine.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfDJo91pTk9cwuYP_-Ewd3xyerQSx6ctP6vOcmSP4i8HgqJRNl9JOBFo6F7EljzXqePA_NWaYZ66uuoK3Gk718PQlUz_od3gPhn8M3ZvGsGserPLugsoZI2HCviFqZIz2VwkWV/s1600/works-on-my-machine.png&quot; height=&quot;116&quot; width=&quot;120&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
A futuro quedan sin dudas cosas a mejorar. Le falta mucho de estética, de lo que no me he preocupado por ahora, y también le falta en cuanto a funcionalidad.&lt;br /&gt;
&lt;br /&gt;
Si alguien la prueba y quiere colaborar, puede pasarme los cambios que (si los apruebo) yo los publico en el GXServer. Si encuentran problemas y no los quieren arreglar... me avisan que los iré corrigiendo en la medida que tenga tiempo de hacerlo.&lt;br /&gt;
&lt;br /&gt;</description><link>http://mcrispino.blogspot.com/2014/01/finanzasapp.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgi4Kdq8zvWCNynrFk8rBPDtWYTpvSiX63TGPKxcq4oETGUGeHgnRKkWoz1QtjlH-GvuIXYuWD_RrzrEKdDVpk9IhImrVwDfFETJfegYtncgMyaFhiDxFxmaYO_LIxWreru2ok8/s72-c/Finanzas_ModeloDatos.png" height="72" width="72"/><thr:total>4</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-33066466.post-7689601141743380481</guid><pubDate>Mon, 23 Dec 2013 14:42:00 +0000</pubDate><atom:updated>2013-12-23T12:42:09.745-02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">desarrollo</category><category domain="http://www.blogger.com/atom/ns#">genexus</category><category domain="http://www.blogger.com/atom/ns#">ipad</category><category domain="http://www.blogger.com/atom/ns#">iphone</category><category domain="http://www.blogger.com/atom/ns#">útiles</category><title>Respaldo de la base de datos Offline en iTunes</title><description>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOSetojcLobUZ8Rnv1UmjQ4A6HFN7kvj4gGvJS1GGhDII9eYV6AIlk2jOKqEONBqFd2_OZRvzqOhXZg5Wh_pUZUQOirL2559dbpI75rsKjggMIl52Dx8OwlSZii0e5hiFv1fJ8/s1600/xcode_logo.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOSetojcLobUZ8Rnv1UmjQ4A6HFN7kvj4gGvJS1GGhDII9eYV6AIlk2jOKqEONBqFd2_OZRvzqOhXZg5Wh_pUZUQOirL2559dbpI75rsKjggMIl52Dx8OwlSZii0e5hiFv1fJ8/s1600/xcode_logo.png&quot; height=&quot;120&quot; width=&quot;120&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
El &lt;a href=&quot;http://wiki.gxtechnical.com/commwiki/servlet/hwikibypageid?23673&quot;&gt;escenario principal&lt;/a&gt; para las aplicaciones Offline que generamos con GeneXus, se tiene un componente en el servidor donde se centralizan los datos ingresados en cada uno de los dispositivos.&lt;br /&gt;
&lt;br /&gt;
En este escenario no es imprescindible hacer un respaldo de la base de datos Offline, ya que la misma siempre se puede volver a construir a partir de los datos del servidor.&lt;br /&gt;
&lt;br /&gt;
Sin embargo, el generador Offline permite otro escenario donde sí puede ser importante tener respaldo de los datos: cuando la aplicación es completamente Offline y no tiene componente en el servidor. &lt;br /&gt;
&lt;br /&gt;
Si bien acceder al sistema de archivos del iPhone se puede, no hay una forma &quot;nativa&quot; de hacerlo. Hay aplicaciones que exponen dicho sistema de archivos a la Mac o al PC, pero en general tienen algún costo.&lt;br /&gt;
&lt;br /&gt;
En particular para la base de datos Offline, como se almacena en la carpeta Documents que es una carpeta especial dentro de la aplicación, es posible copiar el archivo desde iTunes &lt;a href=&quot;http://support.apple.com/kb/PH12118&quot;&gt;como se explica en este documento de Apple&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Para lograr esto, simplemente debemos agregar una nueva clave al archivo .plist del proyecto generado (o se puede cambiar el template si lo vamos a querer siempre...). La clave que se debe agregar es &lt;i&gt;UIFileSharingEnabled&lt;/i&gt; con valor &lt;i&gt;YES&lt;/i&gt;. La forma de hacerlo &lt;a href=&quot;https://developer.apple.com/library/ios/documentation/Miscellaneous/Conceptual/iPhoneOSTechOverview/CoreServicesLayer/CoreServicesLayer.html#//apple_ref/doc/uid/TP40007898-CH10-SW30&quot;&gt;está explicada en este documento&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Cabe aclarar que si se hace un respaldo completo del dispositivo mediante iTunes, este archivo también se respalda. Lo que se explica en esta nota es cómo respaldar solo este archivo si quisieramos hacerlo...&lt;br /&gt;
&lt;br /&gt;</description><link>http://mcrispino.blogspot.com/2013/12/respaldo-de-la-base-de-datos-offline-en.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOSetojcLobUZ8Rnv1UmjQ4A6HFN7kvj4gGvJS1GGhDII9eYV6AIlk2jOKqEONBqFd2_OZRvzqOhXZg5Wh_pUZUQOirL2559dbpI75rsKjggMIl52Dx8OwlSZii0e5hiFv1fJ8/s72-c/xcode_logo.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-33066466.post-3082261231519131049</guid><pubDate>Tue, 10 Dec 2013 14:08:00 +0000</pubDate><atom:updated>2013-12-10T12:08:41.564-02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">open source</category><title>Licencias de software libre, ¿cuál usar?</title><description>Quisiera conocer la opinión de gente que sepa más que yo del tema de licencias de software libre, para saber cuál conviene usar.&lt;br /&gt;
&lt;br /&gt;
Lo que quiero es distribuir algo&lt;sup&gt;(1)&lt;/sup&gt; de la forma menos restrictiva posible, es decir, que quien lo quiera usar lo use para lo que más le convenga, y si lo quiere distribuir, vender, usar de ejemplo, o lo que sea, lo pueda hacer.&lt;br /&gt;
&lt;br /&gt;
En la &lt;a href=&quot;http://en.wikipedia.org/wiki/Comparison_of_free_and_open-source_software_licenses&quot;&gt;página de Wikipedia sobre el tema&lt;/a&gt; tiene varias de estas licencias, muchas de ellas no las conozco.&lt;br /&gt;
&lt;br /&gt;
De las que aparecen ahí, las que más me convencen por las cosas que permiten y por ser conocidas son la de &lt;a href=&quot;http://en.wikipedia.org/wiki/Apache_License&quot;&gt;Apache&lt;/a&gt;, la de &lt;a href=&quot;http://en.wikipedia.org/wiki/BSD_license&quot;&gt;BSD&lt;/a&gt; y la de &lt;a href=&quot;http://en.wikipedia.org/wiki/MIT_License&quot;&gt;MIT&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
También entiendo que existe el concepto de &quot;copyleft&quot; que no se muy bien como juega en todo esto.&lt;br /&gt;
&lt;br /&gt;
Por el momento me inclino por la de MIT, pero acepto sugerencias :)&lt;br /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;(1) Para que no quede demasiado misterioso, se trata de una KB GeneXus correspondiente a una aplicación para Smart Devices. Nada demasiado complicado, es de uso personal, pero que pienso puede servirle a alguien más... Ya habrá más novedades.&lt;/span&gt;</description><link>http://mcrispino.blogspot.com/2013/12/licencias-de-software-libre-cual-usar.html</link><author>noreply@blogger.com (Unknown)</author><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-33066466.post-7253272579171216085</guid><pubDate>Fri, 15 Nov 2013 22:25:00 +0000</pubDate><atom:updated>2013-11-15T20:25:00.296-02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">desarrollo</category><category domain="http://www.blogger.com/atom/ns#">xcode</category><category domain="http://www.blogger.com/atom/ns#">útiles</category><title>Xcode: debug de aplicaciones que usan localización</title><description>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOSetojcLobUZ8Rnv1UmjQ4A6HFN7kvj4gGvJS1GGhDII9eYV6AIlk2jOKqEONBqFd2_OZRvzqOhXZg5Wh_pUZUQOirL2559dbpI75rsKjggMIl52Dx8OwlSZii0e5hiFv1fJ8/s1600/xcode_logo.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;120&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOSetojcLobUZ8Rnv1UmjQ4A6HFN7kvj4gGvJS1GGhDII9eYV6AIlk2jOKqEONBqFd2_OZRvzqOhXZg5Wh_pUZUQOirL2559dbpI75rsKjggMIl52Dx8OwlSZii0e5hiFv1fJ8/s200/xcode_logo.png&quot; width=&quot;120&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Para la versión Beta 3 de &lt;a href=&quot;http://wiki.gxtechnical.com/commwiki/servlet/hwikibypageid?20247&quot;&gt;GeneXus Tilo&lt;/a&gt; (a liberarse cerca de fin de año...), estuve trabajando en una funcionalidad que llamamos Proximity Alerts, que es parte de la &lt;a href=&quot;http://wiki.gxtechnical.com/commwiki/servlet/hwikibypageid?16432&quot;&gt;Geolocation API&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
No es el objetivo de esta nota explicar la funcionalidad, pero merece por lo menos un comentario. Consiste básicamente en definir regiones dadas por un punto geográfico y un radio en metros, y cuando el dispositivo ingresa a una de estas regiones se dispara un evento en la aplicación.&lt;br /&gt;
&lt;br /&gt;
La funcionalidad en sí no es difícil de implementar, pero es bastante difícil hacer debug... Por suerte y gracias a &lt;a href=&quot;https://twitter.com/finthamoussu&quot;&gt;Fabián&lt;/a&gt;, aprendí algunas cosas de Xcode y del simulador de iOS que facilitan un poco la tarea.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Xcode&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
En Xcode, en el Scheme de la aplicación (Product &amp;gt; Scheme &amp;gt; Edit Scheme... &amp;gt; tab Options) tenemos la opción de decirle a la aplicación que inice en una ubicación determinada, y también tenemos la posibilidad de pasarle un archivo GPX para que el simulador vaya cambiando de ubicación siguiendo una ruta.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg80h1cuwtJS7G3yyt8JTrYKplKhsKFgrcgkhiF7y8mCooKT6GrEIfVtIgehcqNGNaAFLE1P3HjfbemfiuvGiowJtEx-Cutp90lzU7T85uEq8zFUN0nz-V9DpUPAtmcuqVeI_eS/s1600/XcodeScheme1.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;216&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg80h1cuwtJS7G3yyt8JTrYKplKhsKFgrcgkhiF7y8mCooKT6GrEIfVtIgehcqNGNaAFLE1P3HjfbemfiuvGiowJtEx-Cutp90lzU7T85uEq8zFUN0nz-V9DpUPAtmcuqVeI_eS/s320/XcodeScheme1.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Los archivos GPX son simplemente archivos XML con información geográfica, y se pueden crear de forma muy simple con una aplicación gratuita en el App Store llamada &lt;a href=&quot;https://itunes.apple.com/ca/app/gpx-creator/id535468654?mt=8&quot;&gt;GPX Creator&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Otra configuración que está en el Scheme, pero esta vez en el tab Info, es que la aplicación no inicie automáticamente cuando le damos Run en Xcode, sino que espere a que el desarrollador la inicie de forma manual. Esto como dato anecdótico, porque no nos sirvió para lo que queríamos.&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;b&gt;iOS Simulator&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
En el simulador también tenemos la opción de configurar la ubicación, pero una vez que la aplicación ya está corriendo. Esto se hace en la opción de menú Depurar &amp;gt; Ubicación (no se por qué Xcode está en inglés y el simulador en español...)&lt;br /&gt;
&lt;br /&gt;
En este caso, las opciones son usar una ubicación predeterminada o usar una definida por nosotros.&lt;br /&gt;
&lt;br /&gt;
La diferencia con la configuración en Xcode, es que entre las ubicaciones predeterminadas ya hay algunas que son una serie de puntos por los que va pasando.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Conclusión&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Siempre es bueno conocer las herramientas que usamos y más cuando tienen funcionalidades que son útiles en casos puntuales y no son demasiado fáciles de encontrar. Por eso me pareció interesante compartir esto. &lt;br /&gt;
&lt;br /&gt;
De todas formas, más allá de estas opciones que sirvieron para avanzar en la solución, hubo algo que no pudimos hacer: que el simulador se &quot;moviera&quot; en una ruta cuando la aplicación no está corriendo. Así que de todas formas para probar la funcionalidad tuve que salir a caminar con el teléfono...&lt;br /&gt;
&lt;br /&gt;</description><link>http://mcrispino.blogspot.com/2013/11/xcode-debug-de-aplicaciones-que-usan.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOSetojcLobUZ8Rnv1UmjQ4A6HFN7kvj4gGvJS1GGhDII9eYV6AIlk2jOKqEONBqFd2_OZRvzqOhXZg5Wh_pUZUQOirL2559dbpI75rsKjggMIl52Dx8OwlSZii0e5hiFv1fJ8/s72-c/xcode_logo.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-33066466.post-4862314184734780245</guid><pubDate>Mon, 07 Oct 2013 22:21:00 +0000</pubDate><atom:updated>2013-10-07T20:21:00.262-02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">genexus</category><category domain="http://www.blogger.com/atom/ns#">presentaciones</category><title>Diapositivas y video de mi charla en el #GX23</title><description>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLwNqUhcyNHHlVsRUUN2uRctTWiTlq-pA3rPhuqFvZUk_XlytWHSou4tn2LCY5wXH9qKuXGw3OyllkYrIKgSA97xUXYsGm1eda5uMyfHLY8zoHGjX5SiXpnjpaKWaqFA2BY0R-/s1600/GX23.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLwNqUhcyNHHlVsRUUN2uRctTWiTlq-pA3rPhuqFvZUk_XlytWHSou4tn2LCY5wXH9qKuXGw3OyllkYrIKgSA97xUXYsGm1eda5uMyfHLY8zoHGjX5SiXpnjpaKWaqFA2BY0R-/s1600/GX23.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
El &lt;a href=&quot;http://www.genexus.com/encuentro2013/gx23-materiales?es,0,,3199&quot;&gt;video de la charla&lt;/a&gt; lo pueden ver en el sitio del evento.&lt;br /&gt;
&lt;br /&gt;
Las diapositivas están también ahí, pero también &lt;a href=&quot;http://sdrv.ms/1cnTElY&quot;&gt;las subí a SkyDrive&lt;/a&gt; que funciona mejor que SlideShare, que no respeta el orden de aparición de los elementos de la diapositiva.&lt;br /&gt;
&lt;br /&gt;
Solo las diapositivas capaz que no dicen mucho, pueden ver las notas en cada una (creo que están bien... no las revisé en la versión final).</description><link>http://mcrispino.blogspot.com/2013/10/diapositivas-y-video-de-mi-charla-en-el.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLwNqUhcyNHHlVsRUUN2uRctTWiTlq-pA3rPhuqFvZUk_XlytWHSou4tn2LCY5wXH9qKuXGw3OyllkYrIKgSA97xUXYsGm1eda5uMyfHLY8zoHGjX5SiXpnjpaKWaqFA2BY0R-/s72-c/GX23.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-33066466.post-5818253714325348813</guid><pubDate>Thu, 03 Oct 2013 13:43:00 +0000</pubDate><atom:updated>2013-10-03T13:42:45.982-03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">eventos</category><category domain="http://www.blogger.com/atom/ns#">genexus</category><title>Resumen del #GX23</title><description>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLwNqUhcyNHHlVsRUUN2uRctTWiTlq-pA3rPhuqFvZUk_XlytWHSou4tn2LCY5wXH9qKuXGw3OyllkYrIKgSA97xUXYsGm1eda5uMyfHLY8zoHGjX5SiXpnjpaKWaqFA2BY0R-/s1600/GX23.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLwNqUhcyNHHlVsRUUN2uRctTWiTlq-pA3rPhuqFvZUk_XlytWHSou4tn2LCY5wXH9qKuXGw3OyllkYrIKgSA97xUXYsGm1eda5uMyfHLY8zoHGjX5SiXpnjpaKWaqFA2BY0R-/s1600/GX23.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Terminó otro &lt;a href=&quot;http://www.genexus.com/encuentro2013&quot;&gt;encuentro GeneXus&lt;/a&gt;. Como siempre fueron tres días de mucha actividad, de ver cosas nuevas, de reencontrarse con gente, de salir de la rutina.&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Otra vez, como todos los años, con una organización impecable. Todas las charlas (las que vi yo al menos) respetaron el horario. Lleva mucho esfuerzo hacer que todo salga bien, hacer que del otro lado ni siquiera nos demos cuenta de todo lo que hay atrás. Así que mis felicitaciones a quienes participaron de la organización.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Con respecto al contenido, hubo sin duda mucha variedad. Mi interés eran obviamente las charlas de Smart Devices, y en particular las que daba la comunidad.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Así es que fui a las charlas de DVelop (&lt;a href=&quot;http://www.genexus.com/encuentro2013/gx23-materiales?es,0,,3163&quot;&gt;What 2 Listen&lt;/a&gt;, &lt;a href=&quot;http://www.genexus.com/encuentro2013/gx23-materiales?es,0,,3231&quot;&gt;SD+&lt;/a&gt;), a la que dio Armando Cardozo de Simplifica sobre &lt;a href=&quot;http://www.genexus.com/encuentro2013/gx23-materiales?es,0,,3204&quot;&gt;oportunidades y desafíos&lt;/a&gt;, y a la de Marcos Abellón y Matías Preciozzi sobre &lt;a href=&quot;http://www.genexus.com/encuentro2013/gx23-materiales?es,0,,3236&quot;&gt;reconocimiento facial y realidad aumentada&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;div&gt;
La conclusión de estas charlas, es que se están haciendo cosas muy interesantes con el generador, y que una aplicación exitosa puede surgir de una idea, de una necesidad personal, y lograr tener alcance mundial. Creo que la oportunidad para la comunidad está, la herramienta está, ideas seguro que hay, así que falta nada más animarse.&lt;/div&gt;
&lt;div&gt;
&lt;/div&gt;
&lt;br /&gt;
También hubo varias charlas interesantes dadas por gente de Artech. Si están en el tema creo que es casi obligatorio verlas. Quería destacar algunas que vi yo. La de Sebastián del Rio sobre &lt;a href=&quot;http://www.genexus.com/encuentro2013/gx23-materiales?es,0,,3219&quot;&gt;las cosas que se pueden hacer de interfaz de usuario&lt;/a&gt; y la de Franklin Buitrón sobre &lt;a href=&quot;http://www.genexus.com/encuentro2013/gx23-materiales?es,0,,3253&quot;&gt;user experience&lt;/a&gt;. También las de Pablo Mazzilli que contó el &lt;a href=&quot;http://www.genexus.com/encuentro2013/gx23-materiales?es,0,,3175&quot;&gt;modelo atrás de las aplicaciones offline&lt;/a&gt;, y la de Leonardo Piñeyro que mostró &lt;a href=&quot;http://www.genexus.com/encuentro2013/gx23-materiales?es,0,,3198&quot;&gt;como trabajar con aplicaciones offline en GeneXus&lt;/a&gt;, y se animó a hacer la demo en vivo :)&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
El otro tema que me interesaba era ver la opinión que generaba el tema de las aplicaciones offline, funcionalidad en la que estuvimos trabajando fuerte el último año. Por suerte las charlas que dimos sobre el tema fueron a sala llena, y además fue una de las cosas que más nos preguntaron en el cara a cara de Smart Devices y en las sesiones de &quot;coaching&quot;.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
A propósito del &quot;coaching&quot;, fue una propuesta nueva en este evento que fue bien recibida ya que concurrió bastante gente. Hay cosas para mejorar, por ejemplo la forma de ordenarnos, o tratar de que no se convierta en un lugar donde reportar errores del generador, pero creo que estuvo bueno y que este tipo de actividades aportan valor.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Con respecto a &lt;a href=&quot;http://www.genexus.com/encuentro2013/gx23-materiales?es,0,,3199&quot;&gt;mi charla&lt;/a&gt; me fue bastante bien, como decía vino mucha gente y después vino gente a hacerme preguntas y comentarios, por lo que género interés.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Así que a modo de resumen, la comunidad ya demostró que se pueden hacer cosas interesantes a partir de una idea, y me sirvió para confirmar que el tema que estamos trabajando despierta interés. Es decir, fue un muy buen evento.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
¡Nos vemos en el #GX24! :)&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;hr /&gt;
Actualización, 3 de octubre de 2013, 13:42 - Corrección a los links para que apunten a los videos de las charlas.</description><link>http://mcrispino.blogspot.com/2013/10/resumen-del-gx23.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLwNqUhcyNHHlVsRUUN2uRctTWiTlq-pA3rPhuqFvZUk_XlytWHSou4tn2LCY5wXH9qKuXGw3OyllkYrIKgSA97xUXYsGm1eda5uMyfHLY8zoHGjX5SiXpnjpaKWaqFA2BY0R-/s72-c/GX23.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-33066466.post-6599724429245370128</guid><pubDate>Sat, 21 Sep 2013 23:03:00 +0000</pubDate><atom:updated>2013-09-22T17:51:18.038-03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">eventos</category><category domain="http://www.blogger.com/atom/ns#">genexus</category><title>Charla de Offline Applications en el #GX23</title><description>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimnRrgliUMVbla0c3D-4bE5LCeRLyf3qBlVEeDyGCtlIEWfdYoc_NrzNDKDARAeltpqJa1LqB-bMClHjNt0f3BMmHeZyRaxP1rUzYAHLYB_2CPBrQqwab7l6jiu3e6hHQCWBQG/s1600/GX23.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimnRrgliUMVbla0c3D-4bE5LCeRLyf3qBlVEeDyGCtlIEWfdYoc_NrzNDKDARAeltpqJa1LqB-bMClHjNt0f3BMmHeZyRaxP1rUzYAHLYB_2CPBrQqwab7l6jiu3e6hHQCWBQG/s1600/GX23.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Este año en el &lt;a href=&quot;http://www.genexus.com/encuentro2013/&quot;&gt;Encuentro GeneXus &lt;/a&gt;voy a estar dando una charla sobre aplicaciones Offline para dispositivos móviles.&lt;br /&gt;
&lt;br /&gt;
Todavía no está la grilla con los horarios, pero &lt;a href=&quot;http://www5.genexus.com/main4/evviewpresession_23.aspx?S%3b178%3b64%3b830%3b5%3b1%3bO%3b,43,68,3199&quot;&gt;pueden ver la descripción de la charla&lt;/a&gt; en la &lt;a href=&quot;http://www.genexus.com/encuentro2013/gx23-lista-preliminar&quot;&gt;lista preliminar &lt;/a&gt;en el sitio del encuentro.&lt;br /&gt;
&lt;br /&gt;
El tema de aplicaciones Offline es nuevo en GeneXus Tilo. Aunque ya había algo que se mostró en el evento pasado, este año está mucho más completa la funcionalidad, por lo que los invito a quienes les interese a ver las charlas sobre el tema.&lt;br /&gt;
&lt;br /&gt;
Además de mi charla va a haber otras 3, que van a estar en la misma sala y una a continuación de la otra, así que se pueden agendar todo el &quot;track&quot;. Pueden ver más información de estas charlas en los siguientes links:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www5.genexus.com/main4/evviewpresession_23.aspx?S%3b178%3b64%3b830%3b5%3b1%3bO%3b,43,68,3175&quot;&gt;Aplicaciones Offline para Smart Devices: Visión General&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www5.genexus.com/main4/evviewpresession_23.aspx?S%3b178%3b64%3b830%3b5%3b1%3bO%3b,43,68,3124&quot;&gt;Fuerza de ventas móvil utilizando tabletas Android e integrada con SAP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www5.genexus.com/main4/evviewpresession_23.aspx?S%3b178%3b64%3b830%3b5%3b1%3bO%3b,43,68,3198&quot;&gt;Aplicaciones Offline para Smart Devices: Arquitectura y desarrollo con GeneXus&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description><link>http://mcrispino.blogspot.com/2013/09/charla-de-offline-applications-en-el.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimnRrgliUMVbla0c3D-4bE5LCeRLyf3qBlVEeDyGCtlIEWfdYoc_NrzNDKDARAeltpqJa1LqB-bMClHjNt0f3BMmHeZyRaxP1rUzYAHLYB_2CPBrQqwab7l6jiu3e6hHQCWBQG/s72-c/GX23.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-33066466.post-3319238515361708190</guid><pubDate>Fri, 30 Aug 2013 14:06:00 +0000</pubDate><atom:updated>2013-08-30T11:32:08.801-03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">desarrollo</category><category domain="http://www.blogger.com/atom/ns#">genexus</category><category domain="http://www.blogger.com/atom/ns#">seguridad</category><title>Seguridad en aplicaciones GeneXus</title><description>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9chhW4XqmBFb3WdF1NJaKf7MuQa_DalJtj-eZwmLBijh58s1HFjgZpVh67qBR_jr4W8ppQoOUP9yc-kDv2jXMw85HnAF-Udmf5fMAZviN-XmNZlr8DVXUF_KFLP3r3ExlzLJY/s1600/GXLogo.gif&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9chhW4XqmBFb3WdF1NJaKf7MuQa_DalJtj-eZwmLBijh58s1HFjgZpVh67qBR_jr4W8ppQoOUP9yc-kDv2jXMw85HnAF-Udmf5fMAZviN-XmNZlr8DVXUF_KFLP3r3ExlzLJY/s1600/GXLogo.gif&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;span id=&quot;goog_1817448932&quot;&gt;&lt;/span&gt;&lt;span id=&quot;goog_1817448933&quot;&gt;&lt;/span&gt;En la &lt;a href=&quot;http://gugmontevideo.wordpress.com/2013/08/19/reunion-gug-uruguay-montevideo-2908-latu/&quot;&gt;reunión de ayer del GUG Montevideo&lt;/a&gt;, &lt;a href=&quot;https://twitter.com/elrosti&quot;&gt;Diego Rostagnol&lt;/a&gt; hizo una presentación sobre seguridad en aplicaciones GeneXus que estuvo interesante.&lt;br /&gt;
&lt;br /&gt;
La charla generó una discusión que estuvo buena, porque se plantearon posibles problemas de seguridad en distintos niveles de la aplicación. Diego planteó algunos casos que yo en particular no había considerado, y creo que los aportes del público sirvieron para aclarar otros que tal vez no estaban del todo correctos.&lt;br /&gt;
&lt;br /&gt;
No me considero un experto en seguridad ni mucho menos, pero igual quería dejar escrito acá más o menos los temas que se hablaron ayer, más que nada porque creo que estos temas son muy importantes y en general no se le dedica el tiempo suficiente.&lt;br /&gt;
&lt;br /&gt;
GeneXus resuelve una buena parte de los problemas de seguridad, y eso es muy bueno, pero también tiene un lado negativo: como GeneXus resuelve cosas de forma automática, podemos pensar que está todo resuelto. Y eso no es así.&lt;br /&gt;
&lt;br /&gt;
Veamos los puntos que surgieron ayer de la reunión, y algún otro que puede haber faltado.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;La propiedad Encrypt URL Parameters no evita que se pueda acceder a otros registros&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Diego lo mostró ayer en una demo: una URL encriptada se puede desencriptar fácilmente si se conoce el SiteKey o SessionKey que se usa para encriptar.&lt;br /&gt;
&lt;br /&gt;
El problema es que GeneXus usa una clave por defecto, que si no la cambiamos, cualquiera la conoce...&lt;br /&gt;
&lt;br /&gt;
Ver &lt;a href=&quot;http://wiki.gxtechnical.com/commwiki/servlet/hwikibypageid?8068&quot;&gt;la documentación en el Wiki&lt;/a&gt; por más información.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Un campo oculto o &quot;disabled&quot; en un Web Panel no garantiza que no se modifique&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Recuerden que el HTML está del lado del cliente, y en general los navegadores permiten modificarlo.&lt;br /&gt;
&lt;br /&gt;
Lo que mostró ayer Diego fue un filtro que el usuario no debería modificar porque no tiene permisos, pero que va como un combo con Enabled = false en el form del Web Panel, que igual se puede modificar y ver los datos que se supone que el usuario no tiene permisos.&lt;br /&gt;
&lt;br /&gt;
Esto en realidad era así porque estaba mal resuelto, se tiene que hacer el control en el for each y no asumir que lo que viene del cliente es válido. Pero de todas formas, es interesante como ejemplo. &lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;HTTPS es obligatorio&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Es obligatorio por lo menos en dos lugares:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;pantalla de login Web, o cualquier otro objeto web que tenga que mandar datos sensibles del usuario&lt;/li&gt;
&lt;li&gt;servicios REST de las aplicaciones SD.&lt;/li&gt;
&lt;/ul&gt;
En realidad, hoy en día &lt;a href=&quot;http://www.codinghorror.com/blog/2012/02/should-all-web-traffic-be-encrypted.html&quot;&gt;no hay ningún buen motivo para no poner HTTPS&lt;/a&gt; en toda la aplicación. En algún momento pudo haber diferencia de performance por agregarle el encriptado, pero hoy en día es algo mínimo.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;GAM por si solo no resuelve la seguridad&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
El &lt;a href=&quot;http://wiki.gxtechnical.com/commwiki/servlet/hwikibypageid?14960&quot;&gt;GAM&lt;/a&gt; es un gran avance con respecto a lo que teníamos antes, USENLO!&lt;br /&gt;
&lt;br /&gt;
Lo que había antes, era cada uno programando su esquema de seguridad a mano. Pero igual, GAM por si solo, no resuelve el problema. &lt;br /&gt;
&lt;br /&gt;
En particular, si no usamos HTTPS, cualquiera que pueda ver el tráfico entre el dispositivo y el servidor, puede &quot;robar&quot; el token de autenticación y usarlo sin haberse logueado.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Nunca guarden la contraseña del usuario en su aplicación&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
En serio, no lo hagan. Si están guardando contraseñas, &lt;a href=&quot;http://www.codinghorror.com/blog/2007/09/youre-probably-storing-passwords-incorrectly.html&quot;&gt;lo están haciendo mal&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Hay otras formas de autenticar usuarios, contra Google, Facebook, Twitter, OpenId, o lo que sea...&lt;br /&gt;
&lt;br /&gt;
Si de todas formas tienen que guardar usuarios y contraseñas, nunca, nunca, NUNCA, las guarden en texto plano. Tampoco usen algoritmos de encriptación, las contraseñas jamás se tienen que poder desencriptar.&lt;br /&gt;
&lt;br /&gt;
La forma de guardar contraseñas es usando algún algoritmo de hash, pero averigüen antes cuál es seguro (MD5 no lo es), y si pueden apliquen el algoritmo varias veces y agregándole algún código extra que solo conoce la aplicación.&lt;br /&gt;
&lt;br /&gt;
Pero de nuevo, seguramente si guardan contraseñas lo están haciendo mal...&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Security Scanner&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
No se habló nada en la charla de ayer, pero hay &lt;a href=&quot;http://marketplace.genexus.com/product.aspx?securityscanner,es&quot;&gt;una extensión en el Marketplace&lt;/a&gt;, que sirve para detectar posibles problemas de seguridad en las aplicaciones.&lt;br /&gt;
&lt;br /&gt;
En particular no la he usado, pero se que hay gente que sí, y que sirve. Les recomiendo que por lo menos la miren y evaluen si les sirve.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Conclusión&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
La seguridad es un tema delicado.&lt;br /&gt;
&lt;br /&gt;
Lo peor que podemos hacer es confiarnos que está todo resuelto, porque no es así. GeneXus ayuda mucho en varios puntos, pero tenemos que trabajar también nosotros para que las aplicaciones sean realmente seguras.&lt;br /&gt;
&amp;nbsp; </description><link>http://mcrispino.blogspot.com/2013/08/seguridad-en-aplicaciones-genexus.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9chhW4XqmBFb3WdF1NJaKf7MuQa_DalJtj-eZwmLBijh58s1HFjgZpVh67qBR_jr4W8ppQoOUP9yc-kDv2jXMw85HnAF-Udmf5fMAZviN-XmNZlr8DVXUF_KFLP3r3ExlzLJY/s72-c/GXLogo.gif" height="72" width="72"/><thr:total>3</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-33066466.post-5913811157665137462</guid><pubDate>Sun, 18 Aug 2013 17:49:00 +0000</pubDate><atom:updated>2013-08-19T12:26:01.037-03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">c#</category><category domain="http://www.blogger.com/atom/ns#">desarrollo</category><category domain="http://www.blogger.com/atom/ns#">objective-c</category><category domain="http://www.blogger.com/atom/ns#">reflexiones</category><title>async/await en C# 5.0</title><description>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUDI-TifeA5MaS0nsAJdlVIP84gN5lIOxV5Vl4PT-I9W53_w4BLACLLeTafF-QWE0Iv88rCTNO2nVt7M4fqI8DgIrr5SwHiIkGFGThh0_YXH3JXFhrhaBDjZLmB8YjUEGeCKfM/s1600/LogoAspNet.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;77&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUDI-TifeA5MaS0nsAJdlVIP84gN5lIOxV5Vl4PT-I9W53_w4BLACLLeTafF-QWE0Iv88rCTNO2nVt7M4fqI8DgIrr5SwHiIkGFGThh0_YXH3JXFhrhaBDjZLmB8YjUEGeCKfM/s200/LogoAspNet.png&quot; width=&quot;120&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Personalmente no he hecho nada demasiado serio con C# (sí programo, pero no es ni cerca mi lenguaje principal), pero es un lenguaje que me resulta sumamente interesante. Ya había hablado en este blog sobre &lt;a href=&quot;http://draft.blogger.com/En%20la%20%C3%BAltima%20versi%C3%B3n%20de%20C#,%20se%20agregaron%20dos%20nuevos%20comandos:%20async%20y%20await.&quot;&gt;las mejoras que trajeron las versiones 3.0 y 4.0&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
En la última versión de C#, la 5.0 que salió con VisualStudio 2012, se agregaron dos nuevos comandos: &lt;i&gt;async&lt;/i&gt; y &lt;i&gt;await&lt;/i&gt;. De hecho, es de las pocas cosas nuevas que vinieron con esta versión.&lt;br /&gt;
&lt;br /&gt;
Debo reconocer que al principio no le di mucha importancia, hasta que leí este artículo de Miguel de Icaza que me dejó pensando en el tema:&amp;nbsp;&lt;a href=&quot;http://tirania.org/blog/archive/2013/Aug-15.html&quot;&gt;Callbacks as our Generations&#39; Go To Statement&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;¿Cómo funcionan los comandos async/await? &lt;sup&gt;(1)&lt;/sup&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Cuando se declara un método como &lt;i&gt;async&lt;/i&gt;, lo que le estamos diciendo al compilador es que el método puede detener su ejecución en cualquier momento mediante el uso de un comando &lt;i&gt;await&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
A su vez, un método declarado como &lt;i&gt;async&lt;/i&gt; tiene que devolver un objeto de tipo &lt;i&gt;Task&lt;/i&gt; o &lt;i&gt;Task&amp;lt;T&amp;gt;&lt;/i&gt; según su valor de retorno &quot;real&quot; sea &lt;i&gt;void&lt;/i&gt; o &lt;i&gt;T&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
Cuando un método llama a otro que fue declarado como &lt;i&gt;async&lt;/i&gt;, tiene la opción de llamarlo y esperar prefijando el llamado con el comando &lt;i&gt;await&lt;/i&gt;, o puede seguir ejecutando cosas que son independientes, y guardarse la &lt;i&gt;Task&lt;/i&gt; devuelta por el método para esperar más adelante.&lt;br /&gt;
&lt;br /&gt;
Algo así:&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;tt&gt;
public void TestAsyncCall()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp; &amp;nbsp; Task t1 = SomeLongTaskAsync();&lt;br /&gt;&amp;nbsp; &amp;nbsp; await AnotherLongTaskAsync();&lt;br /&gt;&amp;nbsp; &amp;nbsp; await t1;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;ShowCompletionMessage();&lt;br /&gt;}&lt;/tt&gt;&lt;/blockquote&gt;
Por último, cuando un método queda a la espera de un comando &lt;i&gt;await&lt;/i&gt;, pasa la ejecución al llamador para que pueda continuar con otra cosa, o quedar a su vez esperando en otro &lt;i&gt;await&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
En principio, visto así, no parece ser algo que nos vaya a cambiar la vida. Pero si uno lo piensa en relación al trabajo que puede dar resolver estos temas de forma manual, se da cuenta con la simpleza que lo lograron resolver y cuanto trabajo puede ahorrar.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Comparación con Objective-C&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
En Objective-C, y en particular para iOS desde la versión 4 en adelante, lo más parecido que tenemos es &lt;a href=&quot;http://en.wikipedia.org/wiki/Grand_Central_Dispatch&quot;&gt;Grand Central Dispatch&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Supongamos que queremos tener una tarea que ejecute en background, y luego mostrar un mensaje de que terminó. Para eso, tenemos que escribir algo así:&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;tt&gt;
dispatch_queue_t current_queue = dispatch_get_current_queue();&lt;br /&gt;dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{&lt;br /&gt;&amp;nbsp; &amp;nbsp; NSError *error = [self someLongOperation];&lt;br /&gt;&amp;nbsp; &amp;nbsp; dispatch_async(current_queue, ^{&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; [[UIAlertView alertForError:error] show];&lt;br /&gt;&amp;nbsp; &amp;nbsp; });&lt;br /&gt;});&lt;/tt&gt;&lt;/blockquote&gt;
&lt;div&gt;
No es mala la solución, pero no tiene la simplicidad que tiene la de C#... Nótese que la mayor parte del código (en este caso, no siempre es así), es para decirle que ejecute de forma asincrónica. En C# lo escribiría tal vez así:&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;tt&gt;
Error err = await SomeLongOperation;&lt;br /&gt;ShowError(err);&lt;/tt&gt;&lt;/blockquote&gt;
Además puede tener algunos problemas.&lt;br /&gt;
&lt;br /&gt;
Como estamos usando &lt;i&gt;dispatch_async&lt;/i&gt;, si queremos esperar a que el llamado termine (como con el &lt;i&gt;await&lt;/i&gt;), hay que hacerlo usando semáforos.&lt;br /&gt;
&lt;br /&gt;
La alternativa podría ser usar &lt;i&gt;dispatch_sync&lt;/i&gt;, pero en ese caso siempre estamos bloqueando, no tengo forma de seguir con ambas ejecuciones en paralelo. Además como el &lt;i&gt;dispatch_sync&lt;/i&gt; puede usar el mismo &lt;i&gt;thread&lt;/i&gt; de ejecución que el llamador, puedo potencialmente bloquear el &lt;i&gt;thread&lt;/i&gt; de UI, cosa que no se debe hacer en ningún caso.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Conclusión&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Me pareció una muy buena solución la de C#, creo que es bastante superior a las alternativas que se que tenemos en otros lenguajes.&lt;br /&gt;
&lt;br /&gt;
También me resultó muy interesante el artículo de Miguel de Icaza. Si van al final del artículo hay un link a otro artículo que explica como otra persona implementó una especie de tutorial de su aplicación usando Mono y async/await. Vale la pena leerlo.&lt;br /&gt;
&lt;br /&gt;
Me gustaría saber como se resuelve el tema de la ejecución asincrónica en otros lenguajes, así que agradezco cualquier comentario al respecto.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Actualización, 19/8/2013&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Me corrige &lt;a href=&quot;https://twitter.com/finthamoussu&quot;&gt;Fabián&lt;/a&gt;, y en parte tiene razón,&amp;nbsp; que GCD no es lo mejor para eso, que en Objective-C es más fácil usar &lt;i&gt;NSOperationQueue&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
Tiene razón en que es de más alto nivel que GCD, y facilita el tema de las dependiencias entre tareas (no se precisa usar semáforos), pero de todas formas se precisa bastante más código que en C# y la lógica queda partida en varios bloques, con saltos en la ejecución entre uno y otro.&lt;br /&gt;
&lt;br /&gt;
En resumen, el argumento se mantiene: las construcciones &lt;i&gt;async&lt;/i&gt; y &lt;i&gt;await&lt;/i&gt; de C# facilitan mucho la tarea y hacen el código más fácil de leer.&lt;/div&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;sup&gt;(1)&lt;/sup&gt;&amp;nbsp;Es una interpretación libre de lo que pude leer e investigar... si me equivoco, agradezco me corrijan.&lt;br /&gt;
&lt;br /&gt;</description><link>http://mcrispino.blogspot.com/2013/08/asyncawait-en-c-50.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUDI-TifeA5MaS0nsAJdlVIP84gN5lIOxV5Vl4PT-I9W53_w4BLACLLeTafF-QWE0Iv88rCTNO2nVt7M4fqI8DgIrr5SwHiIkGFGThh0_YXH3JXFhrhaBDjZLmB8YjUEGeCKfM/s72-c/LogoAspNet.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-33066466.post-1890347264752372306</guid><pubDate>Tue, 16 Jul 2013 16:50:00 +0000</pubDate><atom:updated>2013-07-16T13:50:02.665-03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">desarrollo</category><category domain="http://www.blogger.com/atom/ns#">genexus</category><category domain="http://www.blogger.com/atom/ns#">iphone</category><category domain="http://www.blogger.com/atom/ns#">útiles</category><title>Consultar la base de datos offline en iOS</title><description>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrivA9DUOMshBPeEMcUfP25XUtJBabG_qJ6JXanmsIfl7zeLAfFIyBALsu4ICDO92ZIuCOXY83atADp6YVNy8uq1yYluL3e0ESkxnLWmGhopwDj68GWhqPJVN6b4wKzRHVvpU5/s1600/GXLogo.gif&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrivA9DUOMshBPeEMcUfP25XUtJBabG_qJ6JXanmsIfl7zeLAfFIyBALsu4ICDO92ZIuCOXY83atADp6YVNy8uq1yYluL3e0ESkxnLWmGhopwDj68GWhqPJVN6b4wKzRHVvpU5/s1600/GXLogo.gif&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Hace unos días se liberó la versión &lt;a href=&quot;http://wiki.gxtechnical.com/commwiki/servlet/hwikibypageid?22217&quot;&gt;Beta 1 de GeneXus Tilo&lt;/a&gt;, que tiene como una de sus características principales la posibilidad de generar &lt;a href=&quot;http://wiki.gxtechnical.com/commwiki/servlet/hwikibypageid?22228&quot;&gt;aplicaciones Offline para Smart Devices&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Algo que puede resultar útil, sobre todo cuando estamos diagnosticando algún problema, es poder consultar directamente la base de datos.&lt;br /&gt;
&lt;br /&gt;
En iOS no es algo evidente como hacer esto, por lo que lo dejo escrito acá por si alguien lo precisa. Esto sirve para el Simulator, no en un dispositivo...&lt;br /&gt;
&lt;br /&gt;
Lo primero que debemos hacer es obtener la ruta al archivo SQLite. Para eso, debemos ejecutar la aplicación desde Xcode en el Simualtor. Debemos ejecutarla desde Xcode y no desde GeneXus, para así tener la opción de hacer &lt;i&gt;debug&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
Ponemos un &lt;i&gt;breakpoint&lt;/i&gt; en algún punto por el que sepamos que va a pasar la aplicación (puede ser un procedure o el data provider asociado a un panel), y cuando se detiene, en la consola, escribimos:&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;tt&gt;
po [[GXDBManager sharedInstance] databasePath]&lt;/tt&gt;&lt;/blockquote&gt;
Ese comando nos va a dar la ruta donde está el archivo SQLite con la base de datos, va a ser algo de la forma:&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;tt&gt;
$0 = 0x0c871630 /Users/mcrispino/Library/Application Support/iPhone Simulator/6.1/Applications/1030E975-21FE-4C3F-8D4C-4836D8C34CEF/Documents/CM_Ios.sqlite&lt;/tt&gt;&lt;/blockquote&gt;
pero con otra ruta evidentemente, ya que depende de la aplicación.&lt;br /&gt;
&lt;br /&gt;
Copiamos la ruta completa, desde el &quot;/Users&quot; hasta el &quot;.sqlite&quot; inclusive, abrimos la aplicación Terminal.app, y ahí escribimos&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;tt&gt;
sqlite3 &quot;&amp;lt;ruta_completa&amp;gt;&quot;&lt;/tt&gt;&lt;/blockquote&gt;
donde &amp;lt;ruta_completa&amp;gt; es la ruta copiada en el punto anterior. Las comillas son importantes, porque la ruta puede tener espacios en blanco.&lt;br /&gt;
&lt;br /&gt;
Una vez hecho esto, vamos a estar en la consola de SQLite, en la base de datos de nuestra aplicación. Ahí podemos hacer consultas SQL como lo haríamos normalmente en cualquier otro DBMS (respetando la sintaxis de SQLite, por supuesto). Por ejemplo:&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;tt&gt;
select * from Products;&lt;/tt&gt;&lt;/blockquote&gt;
Para terminar, un par de comandos útiles:&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;tt&gt;.tables&lt;/tt&gt;, lista las tablas que hay en la base de datos&lt;br /&gt;
&lt;tt&gt;.exit&lt;/tt&gt;, sale de la consola de SQLite :)&lt;/blockquote&gt;
</description><link>http://mcrispino.blogspot.com/2013/07/consultar-la-base-de-datos-offline-en.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrivA9DUOMshBPeEMcUfP25XUtJBabG_qJ6JXanmsIfl7zeLAfFIyBALsu4ICDO92ZIuCOXY83atADp6YVNy8uq1yYluL3e0ESkxnLWmGhopwDj68GWhqPJVN6b4wKzRHVvpU5/s72-c/GXLogo.gif" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-33066466.post-872085097141505373</guid><pubDate>Mon, 17 Jun 2013 17:31:00 +0000</pubDate><atom:updated>2013-06-17T14:31:13.661-03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">apps</category><category domain="http://www.blogger.com/atom/ns#">genexus</category><title>Metro México DF 2.0, primer aplicación Offline con iOS</title><description>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBTwZ9TKi_yG1bd7A43ufw4hDT3OE2s183RXGKCQIkbePEW9GCmyAtEZj7Ty8llKju3YFrXUzXOxn5I_4KZKK85PGyXsI8DK6fntWJq9Ve4JW2P7nxqqnnevq9lnhCLLvF-6RO/s1600/MetroDF.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBTwZ9TKi_yG1bd7A43ufw4hDT3OE2s183RXGKCQIkbePEW9GCmyAtEZj7Ty8llKju3YFrXUzXOxn5I_4KZKK85PGyXsI8DK6fntWJq9Ve4JW2P7nxqqnnevq9lnhCLLvF-6RO/s1600/MetroDF.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Hace unos días, se liberó la versión 2.0 de la aplicación del &lt;a href=&quot;https://itunes.apple.com/hk/app/metro-mexico-df/id529815225?mt=8&quot;&gt;Metro de México DF para iOS&lt;/a&gt;, hecha con &lt;a href=&quot;http://www.genexus.com/gx/tilo&quot;&gt;GeneXus Tilo&lt;/a&gt;, y que tiene como novedad que incorpora la funcionalidad de generación Offline de esta versión. Hasta donde sé&lt;sup&gt;(1)&lt;/sup&gt;, esta es la primera aplicación Offline en iOS con GeneXus.&lt;br /&gt;
&lt;br /&gt;
La generación Offline para aplicaciones de Smart Devices es una de las &lt;a href=&quot;http://wiki.gxtechnical.com/commwiki/servlet/hwikibypageid?20286&quot;&gt;características principales de la versión Tilo&lt;/a&gt;, de la cual estamos por liberar una beta que agrega esta funcionalidad para iOS.&lt;br /&gt;
&lt;br /&gt;
Por &quot;aplicaciones Offline&quot; en este caso, entendemos aplicaciones que tienen una base de datos en el dispositivo (SQLite, tanto en iOS como en Android), y tienen generación de código del lado del cliente, por lo que pueden funcionar completamente desconectadas del servidor.&lt;br /&gt;
&lt;br /&gt;
En la versión Evolution 2 lo más parecido, es el caché de datos, que permitía acceder a los mismos a pesar de no tener conexión, pero no permitía ejecutar código del lado del cliente ni realizar modificaciones en la base de datos.&lt;br /&gt;
&lt;br /&gt;
En particular la aplicación del Metro DF usa varias características del nuevo generador.&lt;br /&gt;
&lt;br /&gt;
Para empezar, tiene todos los datos embebido en el SQLite, por lo que los accesos son mucho más rápidos.&lt;br /&gt;
&lt;br /&gt;
Además se hace uso del generador de Objective-C, por lo que todos los cálculos se realizan locales, no hay ninguna llamada al servidor por ejemplo para calcular las rutas entre dos estaciones dadas.&lt;br /&gt;
&lt;br /&gt;
También se realizan modificaciones a la base de datos mediante procedimientos, para cálculos internos, aunque esto no es visible para el usuario final ya que no hay ningún formulario de entrada de datos.&lt;br /&gt;
&lt;br /&gt;
Otra cosa para destacar es que en la aplicación se usó la sincronización automática de datos (del servidor al cliente), para la carga inicial de datos en el SQLite, que luego se agregaron a la aplicación compilada (para evitar que cada instalación tenga que sincronizar).&lt;br /&gt;
&lt;br /&gt;
Como decía, en breve vamos a tener una beta liberada para que puedan probar esta funcionalidad. No es una versión completa, porque quedan cosas por hacer, pero por lo menos tenemos la certeza de que ya hay un conjunto de aplicaciones que se pueden hacer. Y para muestra, ya pueden bajar la &lt;a href=&quot;https://itunes.apple.com/hk/app/metro-mexico-df/id529815225?mt=8&quot;&gt;aplicación del Metro de México DF&lt;/a&gt;&lt;sup&gt;(2)&lt;/sup&gt; &lt;br /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;sup&gt;(1) &lt;/sup&gt;Dado que el generador no está liberado, creo estar bastante seguro de que no hay otra aplicación liberada para iOS que use base de datos Offline. Si me equivoco, me avisan :)&lt;br /&gt;
&lt;sup&gt;(2) &lt;/sup&gt;La aplicación tiene algunos puntos a mejorar, por lo que se va a estar subiendo una nueva versión, pero igual me pareció destacable que la aplicación ya esté en producción...</description><link>http://mcrispino.blogspot.com/2013/06/metro-mexico-df-20-primer-aplicacion.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBTwZ9TKi_yG1bd7A43ufw4hDT3OE2s183RXGKCQIkbePEW9GCmyAtEZj7Ty8llKju3YFrXUzXOxn5I_4KZKK85PGyXsI8DK6fntWJq9Ve4JW2P7nxqqnnevq9lnhCLLvF-6RO/s72-c/MetroDF.png" height="72" width="72"/><thr:total>2</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-33066466.post-2466028774620173280</guid><pubDate>Thu, 13 Jun 2013 22:53:00 +0000</pubDate><atom:updated>2013-06-13T19:53:00.501-03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">desarrollo</category><category domain="http://www.blogger.com/atom/ns#">genexus</category><category domain="http://www.blogger.com/atom/ns#">útiles</category><title>Literales de tipo Date y DateTime en GeneXus</title><description>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrivA9DUOMshBPeEMcUfP25XUtJBabG_qJ6JXanmsIfl7zeLAfFIyBALsu4ICDO92ZIuCOXY83atADp6YVNy8uq1yYluL3e0ESkxnLWmGhopwDj68GWhqPJVN6b4wKzRHVvpU5/s1600/GXLogo.gif&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrivA9DUOMshBPeEMcUfP25XUtJBabG_qJ6JXanmsIfl7zeLAfFIyBALsu4ICDO92ZIuCOXY83atADp6YVNy8uq1yYluL3e0ESkxnLWmGhopwDj68GWhqPJVN6b4wKzRHVvpU5/s1600/GXLogo.gif&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Cuando programamos, ya sea en GeneXus o en cualquier otro lenguaje, es muy común usar literales en el código, para valores conocidos o especiales de la aplicación.&lt;br /&gt;
&lt;br /&gt;
Por ejemplo, si voy a hacer una suma de varios registros, inicializo la variable en cero:&lt;br /&gt;
&lt;blockquote&gt;
&lt;tt&gt;
&amp;amp;suma = 0&lt;/tt&gt;&lt;/blockquote&gt;
O si estoy por ejemplo en una transacción y quiero saber si estoy en modo Insert, puedo preguntar&lt;br /&gt;
&lt;blockquote&gt;
&lt;tt&gt;if &amp;amp;Mode = &#39;INS&#39;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; ... &lt;br /&gt;
endif&lt;/tt&gt;&lt;/blockquote&gt;
(nota: es un ejemplo... lo recomendable en este caso es usar el dominio enumerado TrnMode) &lt;br /&gt;
&lt;br /&gt;
En GeneXus hay unos cuantos tipos de datos, pero podríamos decir que los principales son cuatro: números, strings, booleanos y fechas (o fecha-hora para ser más precisos).&lt;br /&gt;
&lt;br /&gt;
Para los tres primeros, es bien sabido como expresar literales, ¿pero para las fechas?&lt;br /&gt;
&lt;br /&gt;
Esta funcionalidad creo que no es muy conocida, pero en GeneXus también se pueden escribir literales de fechas, utilizando el caracter # como delimitador (así como usamos las comillas simples o dobles para los strings).&lt;br /&gt;
&lt;br /&gt;
Así por ejemplo, las siguientes expresiones son válidas:&lt;br /&gt;
&lt;blockquote&gt;
&lt;tt&gt;&amp;amp;date = #2013-06-13#&lt;br /&gt;
&amp;amp;dateTime = #2013-06-13 06:23p#&lt;/tt&gt;&lt;/blockquote&gt;
Por más información, pueden ver la &lt;a href=&quot;http://wiki.gxtechnical.com/commwiki/servlet/hwikibypageid?4372&quot;&gt;documentación oficial en el Wiki&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Esto en sí no parece tener demasiadas ventajas con respecto a usar las funciones &lt;a href=&quot;http://wiki.gxtechnical.com/commwiki/servlet/hwikibypageid?7627&quot;&gt;YMDtoD&lt;/a&gt; y &lt;a href=&quot;http://wiki.gxtechnical.com/commwiki/servlet/hwikibypageid?7626&quot;&gt;YMDHMStoT&lt;/a&gt;, pero hay un caso donde sí en necesario usarlos: cuando queremos hacer un call dinámico a un objeto SD, que recibe una fecha por parámetro. Por ejemplo:&lt;br /&gt;
&lt;blockquote&gt;
&lt;tt&gt;&amp;amp;callObject = &quot;sd:MiObjetoSD?#2013-06-13#&quot;&lt;br /&gt;
call(&amp;amp;callObject)&lt;/tt&gt;&lt;/blockquote&gt;
En todo caso, es una herramienta más de la que disponemos a la hora de escribir nuestras aplicaciones en GeneXus.&lt;br /&gt;
&lt;br /&gt;</description><link>http://mcrispino.blogspot.com/2013/06/literales-de-tipo-date-y-datetime-en.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrivA9DUOMshBPeEMcUfP25XUtJBabG_qJ6JXanmsIfl7zeLAfFIyBALsu4ICDO92ZIuCOXY83atADp6YVNy8uq1yYluL3e0ESkxnLWmGhopwDj68GWhqPJVN6b4wKzRHVvpU5/s72-c/GXLogo.gif" height="72" width="72"/><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-33066466.post-8557111659536591358</guid><pubDate>Tue, 11 Jun 2013 23:09:00 +0000</pubDate><atom:updated>2013-06-11T20:09:00.404-03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">apple</category><category domain="http://www.blogger.com/atom/ns#">iphone</category><title>iOS 7</title><description>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEge2uOhmggXW06zW3HE-F6JFByvHcy4EEJKOthg6RR7UieXA8aCp3GqnbKYzxADHbxfNd-qsIAZP6IuMceMs-v6TDqysCbNs7s8nYOpgV_tR6cSP0wC3PC-I4KnIyqdB3e0pXct/s1600/iOS7.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEge2uOhmggXW06zW3HE-F6JFByvHcy4EEJKOthg6RR7UieXA8aCp3GqnbKYzxADHbxfNd-qsIAZP6IuMceMs-v6TDqysCbNs7s8nYOpgV_tR6cSP0wC3PC-I4KnIyqdB3e0pXct/s1600/iOS7.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
En el día de ayer Apple presentó la nueva versión de iOS, que ya se puede obtener en versión beta y estará disponible más adelante este año.&lt;br /&gt;
&lt;br /&gt;
La presentación se puede ver completa &lt;a href=&quot;http://www.apple.com/apple-events/june-2013/&quot;&gt;en el sitio de Apple&lt;/a&gt;, donde tambiéan anunciaron una nueva versión de OS X (con poca cosa nueva...), nuevas MacBook Air y una nueva Mac Pro. Si quieren ver el &lt;a href=&quot;http://www.apple.com/ios/ios7/&quot;&gt;video de presentación de iOS 7&lt;/a&gt; específicamente (no la presentación), también lo pueden hacer.&lt;br /&gt;
&lt;br /&gt;
Si bien se esperaba que el nuevo diseño en iOS 7 fuera más &quot;flat&quot; que en versiones anteriores, creo que con lo que mostraron se pasaron para el otro lado...&lt;br /&gt;
&lt;br /&gt;
Todavía no instalé la beta, y dudo que lo vaya a hacer. Eventualmente voy a terminar actualizando, pero el diseño de esta nueva versión me parece mucho más descuidado que en iOS 6.&lt;br /&gt;
&lt;br /&gt;
Por ejemplo, &lt;a href=&quot;https://itunes.apple.com/us/app/wwdc/id640199958?ls=1&amp;amp;mt=8&quot;&gt;la aplicación del WWDC&lt;/a&gt; que liberaron hace unos días para el evento de desarrolladores, tiene &quot;tabs&quot; en la barra de navegación que se ven así:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKvtXMH3GyiK1oTnUwjB3K3VVgQhqwkPiHKAVo_ZvyKif7sbKTSHaNHKvPtKAxHgt8zRoNY3LmQdsrEU8kgiEeHXtgsPtd1ZUpVn6u2MnTgyYQraPil4g0Kvog1g2-F2958qH9/s1600/navBar_iOS6.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKvtXMH3GyiK1oTnUwjB3K3VVgQhqwkPiHKAVo_ZvyKif7sbKTSHaNHKvPtKAxHgt8zRoNY3LmQdsrEU8kgiEeHXtgsPtd1ZUpVn6u2MnTgyYQraPil4g0Kvog1g2-F2958qH9/s1600/navBar_iOS6.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
En contraste, por ejemplo la aplicación de Calendario en iOS 6, tiene botones similares en la &quot;toolbar&quot;, que se ven así:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdNi-Xr3R2Do_s49riBOFoZPrCodWRpEBs6sdRgAurzktUbuYGi7-AzsDAiaD-vPmRkmAU4nctJEgpuYn8UkujJLn2JZQN2JMAnYRdN8zB1AkchAWpDUe0xE4Z8TfTVKcpZsbN/s1600/calendar_iOS6.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdNi-Xr3R2Do_s49riBOFoZPrCodWRpEBs6sdRgAurzktUbuYGi7-AzsDAiaD-vPmRkmAU4nctJEgpuYn8UkujJLn2JZQN2JMAnYRdN8zB1AkchAWpDUe0xE4Z8TfTVKcpZsbN/s1600/calendar_iOS6.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Entre estos dos diseños, ya se nota la diferencia. En la aplicación del WWDC se le saca el aspecto redondeado a los botones y a la barra misma.&lt;br /&gt;
&lt;br /&gt;
Sin embargo, a pesar que podía ser esperable algo similar para iOS 7, hicieron un cambio mucho más grande.&lt;br /&gt;
&lt;br /&gt;
En iOS 7, ese mismo componente de UI se ve así:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDV71fZLW0PV1n4jMPVf0VKBiWlYv3cxlzKhS2VikGILwxkM3g5uDgtbPzdoE6W_Cin1Ri9JwOtzFfMGM5_5m_eQ2q2zghuT0tNhzvrm_d7eUSdFTpib6FHddHu6ta_wOIfE0j/s1600/navBar_iOS7.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDV71fZLW0PV1n4jMPVf0VKBiWlYv3cxlzKhS2VikGILwxkM3g5uDgtbPzdoE6W_Cin1Ri9JwOtzFfMGM5_5m_eQ2q2zghuT0tNhzvrm_d7eUSdFTpib6FHddHu6ta_wOIfE0j/s1600/navBar_iOS7.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
En temas de diseño, evidentemente es una cuestión de gustos... pero el estilo &quot;flat&quot; que eligieron me resulta bastante malo.&lt;br /&gt;
&lt;br /&gt;
En fin... Ya veremos el próximo año cuando anuncien el porcentaje de adopción de iOS 7, a ver si se acerca al que tiene iOS 6 hoy en día (que es del 93% de acuerdo a la presentación de ayer).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;</description><link>http://mcrispino.blogspot.com/2013/06/ios-7.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEge2uOhmggXW06zW3HE-F6JFByvHcy4EEJKOthg6RR7UieXA8aCp3GqnbKYzxADHbxfNd-qsIAZP6IuMceMs-v6TDqysCbNs7s8nYOpgV_tR6cSP0wC3PC-I4KnIyqdB3e0pXct/s72-c/iOS7.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-33066466.post-8184776389600861146</guid><pubDate>Thu, 16 May 2013 16:28:00 +0000</pubDate><atom:updated>2013-05-16T13:29:28.502-03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">genexus</category><category domain="http://www.blogger.com/atom/ns#">user controls</category><title>Realidad Aumentada en aplicaciones iOS con GeneXus</title><description>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMtqQrmrMEB3ZfBSFdomeSIeD5m-5_8kcUXTB_s_BpvFlF0hJpUnB569OrX_6Jj-aGeWpByhmUZtk-xBpqY4_ZTWReNp0JFNDqaPb3wkdJHOJlxyM0vauQ3hLhSbSj9vSI0bvq/s1600/ArTur.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMtqQrmrMEB3ZfBSFdomeSIeD5m-5_8kcUXTB_s_BpvFlF0hJpUnB569OrX_6Jj-aGeWpByhmUZtk-xBpqY4_ZTWReNp0JFNDqaPb3wkdJHOJlxyM0vauQ3hLhSbSj9vSI0bvq/s1600/ArTur.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Hace un tiempo, &lt;a href=&quot;https://twitter.com/gmilano&quot;&gt;Gastón&lt;/a&gt; hablaba sobre &lt;a href=&quot;http://genexus-sd.blogspot.com/2013/03/8-reasons-why-model-driven-development.html&quot;&gt;las ventajas del &quot;Model Driven Development&quot;&lt;/a&gt;, y una de las que menciona es la extensibilidad.&lt;br /&gt;
&lt;br /&gt;
Hoy sin duda esto queda demostrado, gracias a aplicaciones como &lt;a href=&quot;https://itunes.apple.com/es/app/artur-mvd/id556465581?mt=8&quot;&gt;ArTur MVD&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
ArTur MVD es una guía turística de Montevideo para iOS y Android, desarrollada por la gente de &lt;a href=&quot;http://www.devxtend.com/&quot;&gt;DevXtend&lt;/a&gt;. Fue premiada durante el &lt;a href=&quot;http://www.genexus.com/encuentro2011/noticias?es&quot;&gt;XXI Encuentro GeneXus&lt;/a&gt; (año 2011), y en su momento incluía una función de reconocimiento de monumentos, para lo cual alcanzaba con tomar una foto del monumento, y la aplicación nos mostraba la información del mismo.&lt;br /&gt;
&lt;br /&gt;
Hace unos días subieron una nueva versión al App Store, que incluye la funcionalidad de realidad aumentada. Cuando uno apunta la cámara del dispositivo en una determinada dirección, muestra los restaurantes, comercios, hoteles, etc. que hay en esa dirección, dentro de un radio de 5 kilómetros.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgv9iWUC5EXKd-u8zVUSh8OwtJVzA5xzVrEvFTTpAbZzB7x_-Obv7rA8-bN8N94rdO7OuXKYqp_z55Ga-HBMsAP64GG3nz3bBqfBx03JH9psVPOyPMZmM9Yjh5ojir5nWEF_m8D/s1600/ArTurScreenshot.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgv9iWUC5EXKd-u8zVUSh8OwtJVzA5xzVrEvFTTpAbZzB7x_-Obv7rA8-bN8N94rdO7OuXKYqp_z55Ga-HBMsAP64GG3nz3bBqfBx03JH9psVPOyPMZmM9Yjh5ojir5nWEF_m8D/s320/ArTurScreenshot.png&quot; width=&quot;213&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
La aplicación está hecha con &lt;a href=&quot;http://www.genexus.com/genexus-x-evolution-2/genexus-x-evolution-2?en&quot;&gt;GeneXus X Evolution 2&lt;/a&gt;, y la funcionalidad de realidad aumentada está provista por un user control desarrollado por la misma gente de DevXtend, que usa la información de &quot;geolocation&quot; de los items de un grid, la posición actual y la orientación del dispositivo, para saber que información debe mostrar.&lt;br /&gt;
&lt;br /&gt;
El control por ahora lo tienen solamente para iOS, pero están trabajando también en una versión para Android. Además, estará disponible en el Marketplace para que lo pueda utilizar cualquiera (aclaro que desconozco como será el licenciamiento, si será pago o no...).&lt;br /&gt;
&lt;br /&gt;
En la &lt;a href=&quot;http://showcase.genexus.com/app.aspx?arturmvd,en&quot;&gt;página correspondiente del Showcase&lt;/a&gt; pueden ver un video del control en acción.&lt;br /&gt;
&lt;br /&gt;</description><link>http://mcrispino.blogspot.com/2013/05/realidad-aumentada-en-aplicaciones-ios.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMtqQrmrMEB3ZfBSFdomeSIeD5m-5_8kcUXTB_s_BpvFlF0hJpUnB569OrX_6Jj-aGeWpByhmUZtk-xBpqY4_ZTWReNp0JFNDqaPb3wkdJHOJlxyM0vauQ3hLhSbSj9vSI0bvq/s72-c/ArTur.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-33066466.post-4185088222104567501</guid><pubDate>Mon, 22 Apr 2013 14:16:00 +0000</pubDate><atom:updated>2013-04-22T11:18:27.383-03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">running</category><title>Mi primer media maratón</title><description>En el día de ayer corrí por primera vez una media maratón (21 kilómetros). Capaz que esta mal que yo lo diga, pero fue todo un logro :)&lt;br /&gt;
&lt;br /&gt;
No hace mucho que empecé a correr, menos de tres años, y la verdad si en ese momento me hubieran dicho que iba a poder correr esa distancia, no les hubiera creído.&lt;br /&gt;
&lt;br /&gt;
Hoy creo que con el entrenamiento adecuado, cualquiera puede correr la distancia que se proponga (salvo por algún impedimento médico, obviamente). Ayer por ejemplo, la edición de 10km de la carrera, la corrió un hombre con dos muletas...&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;
El entrenamiento&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Desde antes de empezar a prepararme para la media maratón, ya estaba usando una aplicación que se llama &lt;a href=&quot;http://runkeeper.com/&quot;&gt;RunKeeper&lt;/a&gt;, que además de permitir registrar las corridas, tiene la opción de seguir programas de entrenamiento.&lt;br /&gt;
&lt;br /&gt;
El que elegí yo era para correr la &lt;a href=&quot;http://runkeeper.com/fitness-class/running-half-marathon/15&quot;&gt;media maratón en menos de 2 horas y 15 minutos&lt;/a&gt;. Implicaba salir a correr entre cuatro y cinco veces por semana, con distintas distancias, velocidades, y con sesiones con cambio de ritmo.

Fueron algo más de tres meses de entrenamiento y casi 500 km recorridos, que sin duda valieron la pena.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;
La carrera&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
La carrera fue ayer, como decía, a las 9 de la mañana.&lt;br /&gt;
&lt;br /&gt;
Hubo bastante gente. No la cantidad que hay en las carreras masivas de 10km, pero me sorprendió tanta gente para correr los 21km. Después viendo los resultados, llegaron a la meta más de 800 personas.&lt;br /&gt;
&lt;br /&gt;
El día estuvo muy lindo. Demasiado lindo capaz, cerca de las 11 de la mañana se hizo sentir el calor...&lt;br /&gt;
&lt;br /&gt;
Pude cumplir mi objetivo de terminar la carrera primero, y luego de hacerla en menos de 2:15&#39; ya que puse un tiempo de &lt;a href=&quot;http://kronos.com.uy/?Q=resultado&amp;amp;M=detalleResultado&amp;amp;RID=636186&amp;amp;ID=2250&amp;amp;C=70171&amp;amp;S=2&quot;&gt;2:09&#39;30&quot;&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
De todas formas venía mejor hasta el km 18, y los últimos tres fueron bastante difíciles. Así que en parte quedé con esa sensación de derrota, como cuando te empatan el partido en la hora.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;¿Y ahora qué?&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Por lo pronto ahora a descansar unos días, para darle un respiro a las rodillas.&lt;br /&gt;
&lt;br /&gt;
En la primavera correré alguna de las carreras de 10km, a ver si puedo bajar de los 55 minutos, que era el objetivo para el 2012 y no logré cumplir.&lt;br /&gt;
&lt;br /&gt;
Y después veremos... No creo que estos hayan sido los últimos 21km ;)
&lt;br /&gt;
&lt;br /&gt;</description><link>http://mcrispino.blogspot.com/2013/04/mi-primer-media-maraton.html</link><author>noreply@blogger.com (Unknown)</author><thr:total>8</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-33066466.post-3271675633054564336</guid><pubDate>Fri, 12 Apr 2013 00:04:00 +0000</pubDate><atom:updated>2013-04-11T21:04:00.101-03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">desarrollo</category><category domain="http://www.blogger.com/atom/ns#">objective-c</category><category domain="http://www.blogger.com/atom/ns#">reflexiones</category><title>Cosas que me gustaría tener en Objective-C</title><description>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOSetojcLobUZ8Rnv1UmjQ4A6HFN7kvj4gGvJS1GGhDII9eYV6AIlk2jOKqEONBqFd2_OZRvzqOhXZg5Wh_pUZUQOirL2559dbpI75rsKjggMIl52Dx8OwlSZii0e5hiFv1fJ8/s1600/xcode_logo.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;120&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOSetojcLobUZ8Rnv1UmjQ4A6HFN7kvj4gGvJS1GGhDII9eYV6AIlk2jOKqEONBqFd2_OZRvzqOhXZg5Wh_pUZUQOirL2559dbpI75rsKjggMIl52Dx8OwlSZii0e5hiFv1fJ8/s200/xcode_logo.png&quot; width=&quot;120&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
En los últimos tiempos, el lenguaje Objective-C ha mejorado bastante, como ya hemos comentado en el blog (por ejemplo &lt;a href=&quot;http://blog.marcoscrispino.com/2012/12/objective-c-se-moderniza-subscripting.html&quot;&gt;acá&lt;/a&gt;).&lt;br /&gt;
&lt;br /&gt;
Pero (siempre hay un &quot;pero&quot;), igual hay algunas cosas que todavía se podrían mejorar o agregar al lenguaje.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;
Implementación default para métodos de protocolos&lt;/h4&gt;
Supongamos que tenemos un &lt;i&gt;@protocol MyProtocol&lt;/i&gt;, que define una &lt;i&gt;@property NSArray *someArray&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
Cuando uso una variable que está basada en este protocolo (&lt;i&gt;id&amp;lt;MyProtocol&amp;gt; myVar&lt;/i&gt;), puedo ver cuantos elementos tiene el array escribiendo&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;tt&gt;
[[myVar someArray] count]&lt;/tt&gt;&lt;/blockquote&gt;
Pero supongamos que esto lo hago muy seguido, entonces quiero cambiar esto, para que el protocolo ya defina la propiedad &lt;i&gt;elementCount&lt;/i&gt; para poder usarla como&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;tt&gt;
[myVar elementCount]&lt;/tt&gt;&lt;/blockquote&gt;
¿Cuál es el problema con esto? Que si agrego la propiedad &lt;i&gt;elementCount&lt;/i&gt; al protocolo, tengo que implementarla en todas las clases que implementan el protocolo.&lt;br /&gt;
&lt;br /&gt;
Una alternativa sería tener algo así como &quot;method templates&quot;, donde se pudiera definir la implementación del método en el protocolo mismo. Estos templates solo podrían usar otros métodos y propiedades definidos en el protocolo.&lt;br /&gt;
&lt;h4&gt;
Templates o módulos&lt;/h4&gt;
Yendo en la misma línea, hay casos en que una implementación de un método es genérica, sin importar la clase en la que esté.&lt;br /&gt;
&lt;br /&gt;
El ejemplo más claro de esto es con los &quot;singleton&quot;. Una posible implementación es la siguiente:&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;tt&gt;
+ (instancetype)sharedInstance {&lt;br /&gt;
&amp;nbsp; static id _sharedInstance = nil;&lt;br /&gt;
&amp;nbsp; static dispatch_once_t onceToken;&lt;br /&gt;
&amp;nbsp; dispatch_once(&amp;amp;onceToken, ^{&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _sharedInstance = [[self alloc] init];&lt;br /&gt;
&amp;nbsp; });&lt;br /&gt;
&amp;nbsp; return _sharedInstance;&lt;br /&gt;
}&lt;/tt&gt;&lt;/blockquote&gt;
(tomada de &lt;a href=&quot;http://nshipster.com/c-storage-classes/&quot;&gt;NSHipster&lt;/a&gt;, un excelente blog sobre Objective-C, ya que estamos)&lt;br /&gt;
&lt;br /&gt;
Nótese que en esta implementación no se hace nunca referencia a la clase donde está definido el método. Lo único que se requiere es que tenga un método init.&lt;br /&gt;
&lt;br /&gt;
Si tuviera algo equivalente a los módulos de Ruby (&lt;a href=&quot;http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_modules.html#s2&quot;&gt;cuando se usan como &quot;mixins&quot;&lt;/a&gt;), podría simplemente &quot;declarar&quot; que una clase es un singleton, y que eso incluya la implementación del método sharedInstance.&lt;br /&gt;
&lt;h4&gt;
Generics&lt;/h4&gt;
En las APIs de Objective-C, cuando un método espera recibir un objeto genérico, declara que recibe un &lt;i&gt;id&lt;/i&gt;, que indica que puede recibir cualquier tipo de objeto.&lt;br /&gt;
&lt;br /&gt;
Esto es muy útil, y por ejemplo los arrays no controlan el tipo de objeto, por lo que podemos tener por ejemplo un número y un texto en el mismo array.&lt;br /&gt;
&lt;br /&gt;
Sin embargo, hay veces que es útil saber de que tipo son los elementos de una colección, y forzar a que no se agreguen elementos de otro tipo.&lt;br /&gt;
&lt;br /&gt;
Supongamos el caso que tenemos un protocolo que define una propiedad&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;tt&gt;
@property (nonatomic, strong) NSArray *actions;&lt;/tt&gt;&lt;/blockquote&gt;
¿De qué tipo pueden ser las &lt;i&gt;actions&lt;/i&gt;? No lo sabemos, a no ser que quien escribió el protocolo haya puesto un comentario... El lenguaje me debería ayudar a que esto quede más claro.&lt;br /&gt;
&lt;h4&gt;
Boxing (y unboxing) de tipos básicos&lt;/h4&gt;
&lt;div&gt;
En Objective-C, los arrays y los diccionarios solo pueden contener objetos, por lo que si queremos guardar por ejemplo un int en un array, tenemos que hacer el &quot;boxing&quot;y pasarlo al array como un &lt;i&gt;NSNumber *&lt;/i&gt;.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Si bien no es algo complicado de hacer, por ejemplo;&lt;/div&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;tt&gt;
int someInteger = 1;&lt;br /&gt;
NSArray *myArray = [NSArray arrayWithObject: @(someInteger) ];&lt;/tt&gt;&lt;/blockquote&gt;
podría ser el compilador el que se encargue de hacerlo...&lt;br /&gt;
&lt;h4&gt;
Map &amp;amp; Reduce&lt;/h4&gt;
&lt;div&gt;
Las funciones que tiene la API para manipular colecciones, en ciertos aspectos son bastante limitados.&lt;br /&gt;
&lt;br /&gt;
Por ejemplo, no tengo funciones para Map y Reduce, que son muy útiles. Son fáciles de implementar, pero ya podrían venir incluidas.&lt;br /&gt;
&lt;br /&gt;
Otras, por ejemplo para filtrar un array, son demasiado complicadas:&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;tt&gt;
[[someArray filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^(id evaluatedObject, NSDictionary *bindings) {&lt;br /&gt;&amp;nbsp;   /* filtering code goes here */&lt;br /&gt;}];&lt;/tt&gt;&lt;/blockquote&gt;
Debería poder escribir simplemente&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;tt&gt;
[someArray filterWithBlock:^(id evaluatedObject) {&lt;br /&gt;&amp;nbsp;   /* filtering code goes here */&lt;br /&gt;}];&lt;/tt&gt;&lt;/blockquote&gt;
&lt;/div&gt;
&lt;h4&gt;
Conclusión&lt;/h4&gt;
Por suerte Objective-C es un lenguaje en evolución, así que tal vez podamos contar con alguna de estas cosas en el futuro...&lt;br /&gt;
&lt;br /&gt;</description><link>http://mcrispino.blogspot.com/2013/04/cosas-que-me-gustaria-tener-en.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOSetojcLobUZ8Rnv1UmjQ4A6HFN7kvj4gGvJS1GGhDII9eYV6AIlk2jOKqEONBqFd2_OZRvzqOhXZg5Wh_pUZUQOirL2559dbpI75rsKjggMIl52Dx8OwlSZii0e5hiFv1fJ8/s72-c/xcode_logo.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-33066466.post-6880537734836631008</guid><pubDate>Sat, 06 Apr 2013 23:36:00 +0000</pubDate><atom:updated>2013-04-06T21:06:42.601-03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">google</category><category domain="http://www.blogger.com/atom/ns#">útiles</category><title>Comandos útiles de Google Search</title><description>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimV2yP9G7hPcRKLbxwhUrSiBUu8WyPXGks41-7_NVY8KD6JDhZYr-esNFRhjk98FV5uVZK0ObbocaBHat4Jkt4nbbrPzjENJd8Qk8jKHMHeDtksAR7az_y18K6pZrIbKiln6U4/s1600/google-g-logo.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimV2yP9G7hPcRKLbxwhUrSiBUu8WyPXGks41-7_NVY8KD6JDhZYr-esNFRhjk98FV5uVZK0ObbocaBHat4Jkt4nbbrPzjENJd8Qk8jKHMHeDtksAR7az_y18K6pZrIbKiln6U4/s1600/google-g-logo.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;Hace ya bastante tiempo que la página de búsqueda de Google dejó de ser un simple buscador de páginas web, y ha pasado a ser más una especie de aplicación de línea de comandos, que brinda información de contexto y no solo una lista de resultados.&lt;br /&gt;
&lt;br /&gt;
Lo que sigue son algunos comandos útiles que se pueden usar en Google Search. No pretende ser una lista exhaustiva, son los que conosco y uso con cierta frecuencia.&lt;br /&gt;
&lt;h4&gt;Calculadora&lt;/h4&gt;&lt;div&gt;Si en vez de ingresar un texto a buscar, ingresamos una operación aritmética como por ejemplo &quot;&lt;a href=&quot;https://www.google.com/search?q=2%2B3&amp;amp;aq=f&amp;amp;oq=2%2B3&amp;amp;aqs=chrome.0.57j5j0l2j60j62.571j0&amp;amp;sourceid=chrome&amp;amp;ie=UTF-8&quot;&gt;2+3&lt;/a&gt;&quot;, Google nos devuelve el resultado, y muestra una calculadora como para poder seguir haciendo operaciones.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;También permite usar funciones trigonométricas, logaritmos, exponenciales, factoriales, etc. Es bastante completa.&lt;/div&gt;&lt;h4&gt;Gráfica de funciones&lt;/h4&gt;&lt;div&gt;Si uno escribe una función, por ejemplo &quot;&lt;a href=&quot;https://www.google.com/search?q=x%5E2%2B1&amp;amp;aq=f&amp;amp;oq=x%5E2%2B1&amp;amp;aqs=chrome.0.57j0l3j62l2.491j0&amp;amp;sourceid=chrome&amp;amp;ie=UTF-8&quot;&gt;x^2+1&lt;/a&gt;&quot;, el resultado que obtiene es la gráfica de la misma.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;No es que use mucho esta funcionalidad, pero me hubiera servido en otro momento :)&lt;/div&gt;&lt;h4&gt;Conversión de monedas&lt;/h4&gt;&lt;div&gt;Si queremos saber algún tipo de cambio, digamos para saber cuantos dólares son 100 euros, escribimos &quot;&lt;a href=&quot;https://www.google.com/search?q=convert+100+euros+to+dollars&amp;amp;aq=f&amp;amp;oq=convert+100+euros+to+dollars&amp;amp;aqs=chrome.0.57j0l3.514j0&amp;amp;sourceid=chrome&amp;amp;ie=UTF-8&quot;&gt;convert 100 euros to dollars&lt;/a&gt;&quot;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;Funciona también para pesos uruguayos, la única dificultad es que hay que escribir el comando en inglés:&amp;nbsp;&lt;a href=&quot;https://www.google.com/search?q=convertir+100+pesos+uruguayos+a+argentinos&amp;amp;aq=0&amp;amp;oq=convertir+100+pesos+uruguayos+a+&amp;amp;aqs=chrome.1.57j0l3.8454j0&amp;amp;sourceid=chrome&amp;amp;ie=UTF-8#hl=en&amp;amp;sclient=psy-ab&amp;amp;q=convert+100+uruguayan+pesos+to+dollars&amp;amp;oq=convert+100+uruguayan+pesos+to+&amp;amp;gs_l=serp.3.0.33i29i30l4.9288.13055.1.15661.19.19.0.0.0.0.292.4851.2-19.19.0...0.0...1c.1.8.psy-ab.LlxDnFXBIQA&amp;amp;pbx=1&amp;amp;bav=on.2,or.r_cp.r_qf.&amp;amp;bvm=bv.44697112,d.eWU&amp;amp;fp=e89d73f048cc8be0&amp;amp;biw=1163&amp;amp;bih=727&quot;&gt;convert 100 uruguayan pesos to dollars&lt;/a&gt;.&lt;/div&gt;&lt;h4&gt;Estado del tiempo&lt;/h4&gt;&lt;div&gt;También podemos consultar el estado del tiempo en algún lugar, por ejemplo preguntando &quot;&lt;a href=&quot;https://www.google.com/search?q=weather+montevideo&amp;amp;aq=f&amp;amp;oq=weather+montevideo&amp;amp;aqs=chrome.0.57j0l3j64.587j0&amp;amp;sourceid=chrome&amp;amp;ie=UTF-8&quot;&gt;weather montevideo&lt;/a&gt;&quot;, o simplemente &quot;weather&quot; y (a veces) Google se da cuenta en donde estamos.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;El resultado muestra pronóstico por hora de la temperatura, lluvia y viento, y el pronóstico para los próximos días. Bastante completo, aunque no me puse a sacar estadísticas para ver que tan acertado es...&lt;/div&gt;&lt;h4&gt;Información sobre películas, libros y música&lt;/h4&gt;&lt;div&gt;Si buscamos por el título de una &lt;a href=&quot;https://www.google.com/search?q=the+matrix&amp;amp;aq=0&amp;amp;oq=the+matrix&amp;amp;aqs=chrome.0.0l4.2709j0&amp;amp;sourceid=chrome&amp;amp;ie=UTF-8&quot;&gt;película&lt;/a&gt;, &lt;a href=&quot;https://www.google.com/search?q=game+of+thrones&amp;amp;aq=0&amp;amp;oq=game+of+thrones&amp;amp;aqs=chrome.0.0l4j62l2.2925j0&amp;amp;sourceid=chrome&amp;amp;ie=UTF-8&quot;&gt;serie&lt;/a&gt;, &lt;a href=&quot;https://www.google.com/search?q=foundation+series&amp;amp;aq=0&amp;amp;oq=foundation+seri&amp;amp;aqs=chrome.0.0j57j5j0j62.3444j0&amp;amp;sourceid=chrome&amp;amp;ie=UTF-8#hl=en&amp;amp;sclient=psy-ab&amp;amp;q=foundation+book&amp;amp;oq=foundation+book&amp;amp;gs_l=serp.3..0i20j0l3.2140.5302.3.5628.8.7.1.0.0.1.285.1823.2-7.7.0...0.0...1c.1.8.psy-ab.6IEGJC_nnIQ&amp;amp;pbx=1&amp;amp;bav=on.2,or.r_cp.r_qf.&amp;amp;bvm=bv.44697112,d.dmQ&amp;amp;fp=e89d73f048cc8be0&amp;amp;biw=1034&amp;amp;bih=624&quot;&gt;libro&lt;/a&gt;, &lt;a href=&quot;https://www.google.com/search?q=abbey+road&amp;amp;aq=0&amp;amp;oq=abbey+roa&amp;amp;aqs=chrome.0.0j57j5j0.2636j0&amp;amp;sourceid=chrome&amp;amp;ie=UTF-8&quot;&gt;disco&lt;/a&gt;, o por autor, actor, director, etc., además de la clásica lista de resultados, muestra a la derecha de la página información sobre lo que estamos buscando.&lt;/div&gt;&lt;h4&gt;Conclusión&lt;/h4&gt;&lt;div&gt;La búsqueda de páginas web a veces es útil, pero puede ser una pérdida de tiempo si queremos encontrar algo específico. Google va por el camino de tratar de mostrar la información más relevante dada la búsqueda que estamos haciendo.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;La lista de comandos que mencioné en el artículo puede resultar útil, seguramente haya otras cosas que no conozco, y seguramente se vayan agregando más comandos con el paso del tiempo.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;¿Alguien sabe de otros comandos que se puedan usar en Google Search? ¿Algún otro buscador que haga este tipo de cosas?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;</description><link>http://mcrispino.blogspot.com/2013/04/comandos-utiles-de-google-search.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimV2yP9G7hPcRKLbxwhUrSiBUu8WyPXGks41-7_NVY8KD6JDhZYr-esNFRhjk98FV5uVZK0ObbocaBHat4Jkt4nbbrPzjENJd8Qk8jKHMHeDtksAR7az_y18K6pZrIbKiln6U4/s72-c/google-g-logo.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-33066466.post-2168787255494039871</guid><pubDate>Thu, 14 Mar 2013 16:51:00 +0000</pubDate><atom:updated>2013-03-14T14:28:07.783-03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">curiosidades</category><category domain="http://www.blogger.com/atom/ns#">desarrollo</category><category domain="http://www.blogger.com/atom/ns#">objective-c</category><category domain="http://www.blogger.com/atom/ns#">útiles</category><title>Optimizaciones del compilador en Objective-C</title><description>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOSetojcLobUZ8Rnv1UmjQ4A6HFN7kvj4gGvJS1GGhDII9eYV6AIlk2jOKqEONBqFd2_OZRvzqOhXZg5Wh_pUZUQOirL2559dbpI75rsKjggMIl52Dx8OwlSZii0e5hiFv1fJ8/s1600/xcode_logo.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;120&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOSetojcLobUZ8Rnv1UmjQ4A6HFN7kvj4gGvJS1GGhDII9eYV6AIlk2jOKqEONBqFd2_OZRvzqOhXZg5Wh_pUZUQOirL2559dbpI75rsKjggMIl52Dx8OwlSZii0e5hiFv1fJ8/s200/xcode_logo.png&quot; width=&quot;120&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Cuando se tiene un objeto que es inmutable, por ejemplo un string, es bastante útil contar con optimizaciones del compilador, para que no cree varias instancias idénticas.&lt;br /&gt;
&lt;br /&gt;
Por ejemplo, en Objective-C si hacemos&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;tt&gt;
NSString *a = @&quot;hola&quot;;&lt;br /&gt;NSString *b = @&quot;hola&quot;;&lt;/tt&gt;&lt;/blockquote&gt;
el compilador se da cuenta que son referencias a la misma instancia, y crea el string &lt;i&gt;@&quot;hola&quot;&lt;/i&gt; una sola vez en memoria, por lo que &lt;i&gt;a&lt;/i&gt; y &lt;i&gt;b&lt;/i&gt; quedan apuntando al mismo objeto.&lt;br /&gt;
&lt;br /&gt;
Lo mismo pasa si se usan objetos de tipo NSNumber. Si tengo por ejemplo&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;tt&gt;
NSNumber *c = @1;&lt;br /&gt;NSNumber *d = @1;&lt;/tt&gt;&lt;/blockquote&gt;
el objeto &lt;i&gt;@1&lt;/i&gt; queda una sola vez en memoria y las variables &lt;i&gt;c&lt;/i&gt; y &lt;i&gt;d&lt;/i&gt; referencian la misma instancia.&lt;br /&gt;
&lt;br /&gt;
Hasta acá no hay mucha sorpresa. Son objetos inmutables, por lo que no importa mucho que sean la misma instancia... salvo en lo que se puede ahorrar de memoria.&lt;br /&gt;
&lt;br /&gt;
Una curiosidad si se quiere, es que los constructores no siempre pueden ser optimizados. Por ejemplo&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;tt&gt;
NSString *e = [@&quot;h&quot; stringByAppendingString:@&quot;ola&quot;];&lt;/tt&gt;&lt;/blockquote&gt;
crea una nueva instancia del string &lt;i&gt;@&quot;hola&quot;&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
¿Qué pasa con el método &lt;i&gt;alloc&lt;/i&gt;? En principio uno podría pensar que si se usa &lt;i&gt;alloc&lt;/i&gt;, debería devolver una nueva instancia. Esto sin embargo no es así para la clase NSNumber. El siguiente código devuelve la misma instancia que la asignada en &lt;i&gt;c&lt;/i&gt; y &lt;i&gt;d&lt;/i&gt;.&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;tt&gt;
NSNumber *f = [[NSNumber alloc] initWithInt:1];&lt;/tt&gt;&lt;/blockquote&gt;
Raro...&lt;br /&gt;
&lt;br /&gt;
Pero más raro aún, es que el método &lt;i&gt;copy&lt;/i&gt; también devuelve la misma instancia. &lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;tt&gt;
NSNumber *g = [f copy];&lt;/tt&gt;&lt;/blockquote&gt;
En este caso, ¡&lt;i&gt;c&lt;/i&gt;, &lt;i&gt;d&lt;/i&gt;, &lt;i&gt;f&lt;/i&gt; y &lt;i&gt;g&lt;/i&gt; quedan apuntando todas a la misma dirección de memoria!&lt;br /&gt;
&lt;br /&gt;
Esto no es necesariamente un bug o una feature, creo que se puede argumentar a favor y en contra de cada una de las dos opciones. Lo que sí es importante, es conocer como se comportan las herramientas que usamos.&lt;br /&gt;
&lt;br /&gt;
Una última curiosidad,&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;tt&gt;
[NSObject new]&lt;/tt&gt;&lt;/blockquote&gt;
siempre devuelve una nueva instancia, a pesar de que dos NSObject creados de esta forma son indistiguibles...&lt;br /&gt;
&lt;br /&gt;</description><link>http://mcrispino.blogspot.com/2013/03/optimizaciones-del-compilador-en.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOSetojcLobUZ8Rnv1UmjQ4A6HFN7kvj4gGvJS1GGhDII9eYV6AIlk2jOKqEONBqFd2_OZRvzqOhXZg5Wh_pUZUQOirL2559dbpI75rsKjggMIl52Dx8OwlSZii0e5hiFv1fJ8/s72-c/xcode_logo.png" height="72" width="72"/><thr:total>2</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-33066466.post-177327572098481816</guid><pubDate>Fri, 22 Feb 2013 22:10:00 +0000</pubDate><atom:updated>2013-02-22T20:10:00.302-02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">reflexiones</category><category domain="http://www.blogger.com/atom/ns#">uruguay</category><title>Leyes inconstitucionales</title><description>Capaz que es un poco ingenuo de mi parte, pero ¿el parlamento no debería asegurarse que las leyes que vota sean constitucionales?&lt;br /&gt;
&lt;br /&gt;
En los últimos días hemos tenido por lo menos dos casos, con &lt;a href=&quot;http://www.elobservador.com.uy/noticia/243873/vea-sentencia-de-la-scj-sobre-inconstitucionalidad-del-icir/&quot;&gt;el ICIR&lt;/a&gt; y &lt;a href=&quot;http://www.elobservador.com.uy/noticia/244268/la-scj-cierra-definitivamente-las-investigaciones-por-derechos-humanos/&quot;&gt;la ley interpretativa de la ley de caducidad&lt;/a&gt;, que la Suprema Corte de Justicia declara como inconstitucionales leyes que fueron votadas y promulgadas.&lt;br /&gt;
&lt;br /&gt;
Es decir, tenemos un Parlamento con 99 diputados y 30 senadores (o por ahí...), que a su vez tienen secretarios y asistentes varios. ¿No deberían al menos tratar de que las leyes sean constitucionales? ¿Qué sentido tiene que voten leyes que no son válidas?&lt;br /&gt;
&lt;br /&gt;
¿Son tan ignorantes que ni siquiera conocen la constitución? Parece como que debería ser requisito previo para ser diputado o senador, ¿no? Aunque en la realidad esto claramente no aplica...&lt;br /&gt;
&lt;br /&gt;</description><link>http://mcrispino.blogspot.com/2013/02/leyes-inconstitucionales.html</link><author>noreply@blogger.com (Unknown)</author><thr:total>1</thr:total></item></channel></rss>