Cita:
Empezado por Al González
Mario, si trabajaras en Embarcadero y te preguntaran ¿qué podemos hacer para que FireMonkey sea mejor o por lo menos tan bueno como Cocoa Touch?, ¿qué sugerirías? De tu meditada respuesta puede surgir alguna buena idea para tomarse en cuenta.
.
|
Que es lo que hace a delphi una herramienta superior en Windows? Inventarse una libreria alienigena a la plataforma donde corre y "pintarla" para taparlo? Al contrario, es construir sobre esa plataforma y ofrecer un nivel de abstracción
mejor.
Firemonkey es un intento de crear una libreria unificada para todas las plataformas. Esa es la estrategia de Java, y su éxito solo ha sido a los programadores que no les interesa hacer la
mejor app posible sino simplemente tener su app en el mayor numero de plataformas. Es por eso que multiplataforma en el nivel de la GUI siempre ha sido equivalente a una interface mediocre (no muy mala, no muy buena, mediocre). Eso es lo que la gente le choca de "Java" y otras librerias similares.
El problema, es que al contrario del API de windows,
Coccoa Touch es un (conjunto) de frameworks
muy bien pensado. En muchos aspectos, mas avanzados que la VCL. Sin embargo, todo se puede mejorar y simplificar, por ejemplo hace dias vi
https://github.com/clayallsopp/formotion (eso que muestra ahorra un monton de trabajo!).
Osea, si soy alguien que quiero tener
la mejor app (a nivel de GUI) firemonkey ni me va ni me viene. Como dije antes, uno puede programar Winforms desde delphi, pero para que? Lo que me interesa es poder sacar provecho, no solo a un API mas completo, y superior, que cualquier intento de crear una GUI multiplataforma, sino que me da acceso a todos los componentes disponibles en el mercado (ej:
http://www.cocoacontrols.com/platforms/ios/controls). Ganar firemonkey y perder Coccoa Touch
no tiene gracia.
Ganar Firemonkey
y poder usar Coccoa Touch sin problemas? Eso es *muy distinto*. Es lo mismo con windows: Ganas VCL y puedes usar API Win32. Es win-win. Si te sale mejor con VCL, genial, sino, no hay problema.
Y mejorar firemonkey, por lo que he visto es complicado. Conceptualmente no lo entiendo muy bien. Siendo coccoa touch complicado -como todo api grande- es muy facil de entender como se construyen nuevos controles. Son como 4 cosas que debes entender (Todo es un UIView, se construye con capas, usas datasources virtuales y haces delegados. Eso es todo). Lo hago de forma habitual todo el tiempo, y sin lios.
Cita:
Empezado por Al González
¿Por qué esa tendencia a pensar que Delphi las tiene de perder donde otros han sido los primeros? ¿Acaso no podemos, comunidad + fabricante, ponernos las pilas para hacerlo competitivo en esos terrenos? ¿No se dispone de capital, medios, profesionales cualificados y putas ganas para lograrlo?
.
|
Yo no pienso eso! Ser primero es mucha ventaja, pero el segundo tiene la ventaja de ver el pasado y mejorarlo (prácticamente, esa es la estrategia de Apple
).
El problema es que los que han manejado Delphi no han tenido una estrategia que conduzca a todo eso. Y mucha gente de la comunidad se ha cansado, gente con talento.
Cita:
Empezado por Al González
¿Podrías dedicar el tiempo que sea necesario, en tu siguiente mensaje, para exponer un ejemplo contundente, sin margen de ambigüedades, argumentado con paciencia y sin limitarte a presentar meras referencias Web, que deje claro, sin lugar a dudas, las diferencias de calidad y productividad entre Cocoa Touch y el FireMonkey de Delphi XE4?
|
Me la pones dificil! Sin *referencias*! si eso es lo que mas me gusta! La diferencia se nota en las mismas apps, su fluidez, desempeño, y versatilidad. Has usado un iPhone o iPad? Solo es comparar las apps que alli se ven con las que se ven en windows.
En fin, te pongo ejemplos, sacados de mis proyectos (asi que no son de lo mejor, porque programador de GUI no soy):
Asi es como se anima una transicion, con efecto de "pasar pagina", a pesar que donde hago eso, hay cientos de controles graficos. Cero problemas de desempeño:
Código PHP:
- (IBAction)saveDocument:(id)sender {
if ([self saveRecord]) {
[UIView transitionWithView:self.view
duration:0.7
options:UIViewAnimationOptionTransitionCurlDown
animations:^{
[self newDocument:0];
} completion:^(BOOL finished) {
}];
}
}
Asi es como puedo graficar miles de imagenes, sin problemas de desempeño:
Código PHP:
// The cell that is returned must be retrieved from a call to -dequeueReusableCellWithReuseIdentifier:forIndexPath:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
ProductIconViewCell *cell = (ProductIconViewCell *)[collectionView dequeueReusableCellWithReuseIdentifier:@"IconCell" forIndexPath:indexPath];
NSDictionary *p = self.data[indexPath.row];
NSString *img = [p objectForKey:@"imageName"];
NSString *imgFile = [[p objectForKey:@"image"] lastPathComponent];
cell.imageBtn.tag = indexPath.row;
[cell.imageBtn setBackgroundImage:[UIImage imageNamed:imgFile] forState:UIControlStateNormal];
cell.title.text = img;
[cell.imageBtn setTitle:self.ref forState:UIControlStateNormal];
return cell;
}
Asi convierto un HTML a un PDF, el HTML esta full con CSS3:
Código PHP:
DDLogInfo(@"Report HTML %@", templatePath);
NSError * error;
content = [GRMustacheTemplate renderObject:self
fromString:content
error:&error];
[content writeToFile:[@"~/Documents/demo.html" stringByExpandingTildeInPath] atomically:YES encoding:NSUTF8StringEncoding error:nil];
if (error && [self.delegate respondsToSelector:@selector(reportFail:)]) {
[self.delegate reportFail:error];
}
[NDHTMLtoPDF createPDFWithHTML:content
pathForPDF:[@"~/Documents/demo.pdf" stringByExpandingTildeInPath]
delegate:self
pageSize:kPaperSizeA4
margins:UIEdgeInsetsMake(10, 5, 5, 5)];
QUiero visualizar un conjunto de datos igual a
http://pinterest.com/all/, control el cual no existe. Asi que necesito inventarmelo (y los que mire open source no me gustaron):
Código PHP:
//
// NewsListViewController.m
// DisplayNews
//
// Created by mamcx on 15/03/13.
// Copyright (c) 2013 El malabarista. All rights reserved.
//
#import "NewsListViewController.h"
@implementation NewsListCell
- (UILabel *) buildLabel:(NSString *)className {
UILabel *label = [[UILabel alloc] init];
label.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;
label.backgroundColor = [UIColor clearColor];
[NUIRenderer renderLabel:label withClass:className];
return label;
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
self.lbTitle = [self buildLabel:@"LargeLabel"];
self.lbTitle.lineBreakMode = NSLineBreakByWordWrapping;
self.lbTitle.numberOfLines = 0;
self.lbDate = [self buildLabel:@"NormalLabel"];
self.lbSource = [self buildLabel:@"NormalLabel"];
[self addSubview:self.lbTitle];
[self addSubview:self.lbDate];
[self addSubview:self.lbSource];
}
return self;
}
- (void) layoutSubviews {
[super layoutSubviews];
self.lbDate.frame = CGRectMake(10, 5, self.frame.size.width - 20, 20);
[self.lbDate sizeToFit];
self.lbTitle.frame = CGRectMake(0, self.lbDate.frame.size.height + 6, self.frame.size.width - 20, self.frame.size.height - self.lbDate.frame.size.height*2 - 6);
self.lbTitle.center = CGPointMake(self.frame.size.width/ 2, self.frame.size.height/2);
[self.lbSource sizeToFit];
self.lbSource.frame = CGRectMake(10, self.frame.size.height - self.lbSource.frame.size.height - 6, self.frame.size.width - 20, self.lbSource.frame.size.height);
[NewsSource adjustFontSizeToFit:self.lbTitle from:14 to:60];
}
@end
@interface NewsListViewController ()
@end
@implementation NewsListViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.delegate = self;
self.onSingleTap = ^(UIView* view, NSInteger viewIndex){
NSLog(@"Single press on %@, at %d", view, viewIndex);
[[NSNotificationCenter defaultCenter]
postNotificationName:NOTIFY_SHOW_NEW object:[NSNumber numberWithInt:viewIndex] userInfo:nil];
__weak NewsListViewController *weakSelf = self;
[weakSelf.navigationController popViewControllerAnimated:YES];
};
self.onLongPress = ^(UIView* view, NSInteger viewIndex){
NSLog(@"Long press on %@, at %d", view, viewIndex);
};
self.onDoubleTap = ^(UIView* view, NSInteger viewIndex){
NSLog(@"Double tap on %@, at %d", view, viewIndex);
};
[self reloadData];
}
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
BDDynamicGridCell *theCell = (BDDynamicGridCell*)cell;
theCell.gridContainerView.backgroundColor = [UIColor lightGrayColor];
for (UIView *v in theCell.gridContainerView.subviews) {
//[NUIRenderer render:v];
v.backgroundColor = self.view.backgroundColor;
}
}
- (NSUInteger)numberOfViews
{
return [NewsSource SourceDB].newsItems.count;
}
-(NSUInteger)maximumViewsPerCell
{
return 3;
}
- (UIView *)viewAtIndex:(NSUInteger)index rowInfo:(BDRowInfo *)rowInfo
{
NewsListCell * cell = [[NewsListCell alloc] initWithFrame:CGRectMake(0, 0, 300, 300)];
FeedItem *item = [NewsSource SourceDB].newsItems[index];
cell.lbTitle.text = item.item.title;
cell.lbDate.text = [[NewsSource SourceDB] formatDate: item.item.date];
cell.lbSource.text = item.source.name;
return cell;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
//Call super when overriding this method, in order to benefit from auto layout.
[super shouldAutorotateToInterfaceOrientation:toInterfaceOrientation];
return YES;
}
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
[self reloadData];
}
- (CGFloat)rowHeightForRowInfo:(BDRowInfo *)rowInfo
{
return 300;
}
@end
P
: La parte visual se hace con
Interface Builder, no tan bueno como el diseño en Delphi, pero apenas suficiente. De todo lo anterior, es notable lo poco código que requieren, excepto por lo largos que son los metodos en obj-c.
Animar, rotar, graficar, componer controles en base a otros, alimentar los datos no importan lo bastante que sean, a pesar de correr en maquinas menos potentes que un PC, y aplicar efectos y estilos visuales atractivos, son las cosas que programadores normales como yo podemos hacer, sin problemas y sin sudar mucho.
Hay muchas cosas que salen genial. Es dificil sin apuntar a algo concreto (no se si les parecera mucha gracia mis ejemplos, a mi si porque la programacion GUI no es mi fuerte
). Por ejemplo, necesito hacer una tarea en el "background" sin frenar la GUI:
Código PHP:
dispatch_async(queue, ^{
self.inventory = [Product retrieveInventoryItems];
dispatch_async(dispatch_get_main_queue(), ^{
lbHello.text = @"Inventory Loaded\n\nHow can I help you?";
});
});
O necesito notificar (broadcast) a todo el que escuche que algo paso:
Código PHP:
[[NSNotificationCenter defaultCenter] postNotificationName:DB_RECORD_CHANGED object:ds userInfo:nil];
En fin, Coccoa Touch es el equivalente a la VCL (ya que no solo cubre la parte visual, sino que ademas
maneja otras sub-apis, como las de audio, multimedia, sqlite, mapas y otros)