lunes, 30 de noviembre de 2015

VIPER Clean Architecture for iOs



VIPER es una aplicación de Clean Architecture para iOs.

VIPER es un acrónimo:

Pulsa este enlace para descargar el ejemplo inicial para aplicar VIPER primeros pasos.






VIEW: Muestra lo que se le dice que por el Presentator.

INTERACTOR: Contiene la lógica de negocio según lo especificado por un caso de uso.

PRESENTER: Contiene vista lógica para la preparación de contenidos para la pantalla (como se recibió del INTERACTOR).

ENTITY: Contiene objetos modelo básico utilizado por el INTERACTOR.

ROUTING: Contiene la lógica de navegación para describir qué pantalla se muestran y en qué orden.

martes, 16 de junio de 2015

Relación entre KVC y KVO (Key-Value Coding / Key-Value Object). Relationship between KVC and KVO (Key-Value Coding / Key-Value Object).

//
//  ViewController.m
//  DemoKVC
//  Relación entre KVC y KVO
//  Created by eduardo fulgencio on 16/6/15.
//  Copyright (c) 2015 eduardo fulgencio. All rights reserved.
//

// Al final de la página está la definición de la clase Deposito

#import "ViewController.h"
#import "Deposito.h"

@interface ViewController ()
// Declaramos dos objetos de tipo Deposito
@property (nonatomic, strong) Deposito *depositoAgua;
@property (nonatomic, strong) Deposito *depositoLeche;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    self.depositoAgua = [[Deposito alloc] init];
    self.depositoLeche = [[Deposito alloc] init];
    
}

-(void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:NO];
    
    // Asignamos nombre y litros a DepositoAgua
    self.depositoAgua.tipo = @"Agua";
    self.depositoAgua.litros = 10;
    // Asignamos nombre y litros a DepositoLeche
    self.depositoLeche.tipo = @"Leche";
    self.depositoLeche.litros = 5;
    
    // Utilización de KVC Key-Value Coding para generar el mismo valor anterior
    
    [self.depositoAgua setValue:@"Agua" forKey:@"tipo"];
    [self.depositoAgua setValue:[NSNumber numberWithInteger:10] forKey:@"litros"];

     // Relacion KVC y KVO ( Key-Value Observing )
    [self.depositoAgua addObserver:self forKeyPath:@"litros" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
  
    // Aumentamos en 1 litro los litros del deposito agua
    [self.depositoAgua setValue:[NSNumber numberWithInteger:11] forKey:@"litros"];
}


// En cuanto se produza un cambio en los litros del depósito de agua
// este método será llamado
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
    
    if ([keyPath isEqualToString:@"litros"]) {
        NSLog(@"La cantidad de litros ha cambiado.");
        NSLog(@"%@ : ", change);
    }
    
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


@end



// ESTA ES LA DEFINICION DE LA CLASE DEPOSITO

/* Clase deposito 

 #import <Foundation/Foundation.h>

 @interface Deposito : NSObject

 @property (nonatomic, strong) NSString *tipo;

 @property (nonatomic) NSUInteger litros;


 @end

 #import "Deposito.h"

 @implementation Deposito

 - (instancetype)init
 {
 self = [super init];
 if (self) {
 self.tipo = @"";
 self.litros = 0;
 }
 return self;
 }

 @end

 */

jueves, 11 de junio de 2015

CGContextSetShadowWithColor dibujar sobra a un Rectángulo. CGContextSetShadowWithColor to draw a rectangle.

/*
 En un UIView asignado 
 @interface TrianguloSombraView : UIView

*/

// En el método drawRect llamamos a dibujarRectanguloConSombra
- (void)drawRect:(CGRect)rect{
    [self dibujarRectanguloConSombra];
}


- (void) dibujarRectanguloConSombra{
  

  CGContextRef currentContext = UIGraphicsGetCurrentContext();
  CGContextSaveGState(currentContext);
    
  // Sombra a aplicar al rectángulo
  CGContextSetShadowWithColor(currentContext, CGSizeMake(15.0f, 15.0f), 12.0f,[[UIColor redColor] CGColor]);
  

  CGMutablePathRef mutablePathRef = CGPathCreateMutable();

  CGRect rectangulo = CGRectMake(55.0f, 60.0f, 150.0f,150.0f);
  
  // Añadidmos el rectángulo al path
  CGPathAddRect(mutablePathRef,  NULL, rectangulo);
  
  CGContextAddPath(currentContext, mutablePathRef);
  
  // Color de rellon para el rectángulo
  [[UIColor colorWithRed:0.20f green:0.60f  blue:0.80f  alpha:1.0f] setFill];
  
  CGContextDrawPath(currentContext,  kCGPathFill);
  
  CGPathRelease(mutablePathRef);
  
  CGContextRestoreGState(currentContext);
  
}

miércoles, 10 de junio de 2015

Creación de un Block Object para centralizar acciones. Creating a Block Object to centralize actions.

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController


- (void)viewDidLoad {
    
    [super viewDidLoad];
    // Llamada al bloque definido
    [self testMetodoMultiplicaPorMil];
    
}

- (void) testMetodoMultiplicaPorMil{
    
    NSString *testBloqueIntToString = multiplicaPorMil(135);
    NSLog(@" Resultado de 135 * 1000  %@", testBloqueIntToString);
    
}

NSString* (^multiplicaPorMil)(NSUInteger) = ^(NSUInteger parametroIn){
    
    NSString *result = [NSString stringWithFormat:@"%lu",(unsigned long)parametroIn * 1000];
    
    return result;
    
};




@end

Añadir una UIButton a una celda UITableViewCell. Adding a UIButton to a cell UITableViewCell.


// En cellForRowAtIndexPath
// de la tableView que mostramos
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
  
  UITableViewCell* result = nil;
  
  static NSString *cellIden = @"cellRow";
  
  result = [tableView dequeueReusableCellWithIdentifier:cellIden];
  
  if (result == nil){
    result = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIden];
  }
  
    result.textLabel.text = @"Contenido de la celda";
  
    // Añadiremos un botón para indicar si pulsa accederá a más información
    
    UIButton *btnInformacion = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    
    btnInformacion.frame = CGRectMake(0.0f, 0.0f, 30.0f, 30.0f);
    btnInformacion.layer.cornerRadius = 10.0f;
    btnInformacion.layer.borderColor = [[UIColor redColor] CGColor];
    btnInformacion.layer.borderWidth = 1.0f;
    [btnInformacion setTitle:@"i" forState:UIControlStateNormal];
    [btnInformacion addTarget:self action:@selector(ejecutarSel:) forControlEvents:UIControlEventTouchUpInside];
    
    result.accessoryView = btnInformacion;
    
    return result;
    
}

- (void) ejecutarSel:(UIButton *)paramSender{
    
    UITableViewCell *perteneceCell = (UITableViewCell*)paramSender.superview;
    
    if (perteneceCell != nil){
        
        // En este caso tratamos el evento de un botón perteneciente a una celda
    }
    

}

viernes, 29 de mayo de 2015

UIView BeginAnimation, Animar una imagen CGAffineTransformMakeScale. UIView BeginAnimation, animate a CGAffineTransformMakeScale image.


- (void) viewDidLoad
{
    [super viewDidLoad];
    
    UIImage *imagenAnima = [UIImage imageNamed:@"imagen.png"];
    
    self.imageView = [[UIImageView allocinitWithImage:imagenAnima];
    [self.imageView setFrame:CGRectMake(0.0f,0.0f,50.0f,50.0f)];
    [self.view addSubview:self.imageView];
}


- (void) viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    [self iniciarAnimacion];
}

- (void) iniciarAnimacion
{
  
  [UIView beginAnimations:@"moverImagen"  context:(__bridge void *)self.imageView];
  
  [UIView setAnimationDuration:4.0f];
  [UIView setAnimationDelegate:self];
  [UIView setAnimationDidStopSelector: @selector(imageViewDidStop:finished:context:)];
  
  [self.imageView setCenter:self.view.center];
  [self.imageView setTransform:CGAffineTransformMakeScale(5.0f, 5.0f)];
  
  [UIView commitAnimations];
  
}

- (void)imageViewDidStop:(NSString *)paramAnimationID
                finished:(NSNumber *)paramFinished  context:(void *)paramContext{
    
    UIImageView *contextImageView = (__bridge UIImageView *)paramContext;
    NSLog(@"Información de la imágen %@", contextImageView);
    

}

jueves, 28 de mayo de 2015

NSMutableAttributedString Aplicar subrayado a las palabras de un texto. Apply NSMutableAttributedString underlined the words of a text.

    // Texto completo del documento
    NSString *textoDelDocumento = @"Los vehículos como el camión corresponden a una evolución del coche y en un paso intermedio la furgoneta.";
   
    // Palabras a las que queremos aplicar el subrayado
    NSArray *palabras = [[NSArray alloc] initWithObjects:@"camión",@"coche",@"furgoneta", nil];
    // Iniciamos NSMutableAttributedString con el texto del documento
    NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:textoDelDocumento];
    
    // APLICAMOS EL SUBRAYADO A LAS PALABRAS QUE QUEREMOS DESTACAR
    for (NSString *palabra in palabras) {
      NSRange range = [textoDelDocumento rangeOfString:palabra];
      [attrString addAttribute:NSUnderlineStyleAttributeName value:[NSNumber numberWithInt:NSUnderlineStyleSingle] range:range];
    }

    [attrString addAttribute:NSBackgroundColorAttributeName  value:[UIColor cyanColorrange:NSMakeRange(0, [attrString length])];
    
    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(10, 20, 300, 80)];
    [label setAttributedText:attrString];
    [label setNumberOfLines:0];
    [label sizeToFit];

    [[self view] addSubview:label];

miércoles, 27 de mayo de 2015

Modificar la altura del Header y Footer del UITableView. Modify Header and Footer height of UITableView.


// @property (nonatomic, strong) UITableView *tableViewHeaderModif;


// ALTURA Y CONTENIDO DEL HEADER DE LA TABLA

- (CGFloat)   tableView:(UITableView *)tableView  heightForHeaderInSection:(NSInteger)section{
  
  CGFloat alturaHeader = 0.0f;
  
  if ([tableView isEqual:self.tableViewHeaderModif] && section == 0){
    alturaHeader = 40.0f;
  }
  
  return alturaHeader;
  
}

- (UIView *)  tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
    
    UILabel *viewHeader = nil;
    
    if ([tableView isEqual:self.tableViewHeaderModif] &&  section == 0){
        
        viewHeader = [[UILabel alloc] initWithFrame:CGRectZero];
        viewHeader.text = @"viewForHeaderInSection  Header";
        viewHeader.backgroundColor = [UIColor cyanColor];
        [viewHeader sizeToFit];
        
    }
    
    return viewHeader;
    
}

// ALTURA Y CONTENIDO DEL FOOTER DE LA TABLA

- (CGFloat)   tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{
  
  CGFloat alturaFooter = 0.0f;
  
  if ([tableView isEqual:self.tableViewHeaderModif] && section == 0){
    alturaFooter = 20.0f;
  }
  
  return alturaFooter;
  
}


- (UIView *)  tableView:(UITableView *)tableView  viewForFooterInSection:(NSInteger)section{
  
  UILabel *viewFooter = nil;
  
  if ([tableView isEqual:self.tableViewHeaderModif] && section == 0){
      
    viewFooter = [[UILabel alloc] initWithFrame:CGRectZero];
    viewFooter.text = @"viewForFooterInSection PIE";
    viewFooter.backgroundColor = [UIColor yellowColor];
    [viewFooter sizeToFit];
      
  }
  
  return viewFooter;
  

}

Shake en el dispositivo, cuanto ha durado. Shake for how long time.

/*
@property (nonatomic) int inicio;
@property (nonatomic) int final;
@property (nonatomic) int duracion;
*/

@synthesize duracion = _duracion;
@synthesize inicio = _inicio;
@synthesize final = _final;


/*
 motion es de tipo UIEventSubtypeMotionShake
 event es de tipo UIMotionEvent
 */

- (void) motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event
{

  NSLog(@"Detectado Shake en el dispositivo");

    _inicio = [NSDate timeIntervalSinceReferenceDate];
  
  // Simulo que el Shake se produce durante 2 segundos
  sleep(2);

}

// Fin motion

- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
    
    if ( event.subtype == UIEventSubtypeMotionShake ) {
        
        NSLog(@"Finalizado Shake en el dispositivo");
        
        _final = [NSDate timeIntervalSinceReferenceDate];
        _duracion = _final - _inicio;

      
        NSLog(@"%i", _duracion);
        
    }
    
    if ([super respondsToSelector:@selector(motionEnded:withEvent:)]) {
        [super motionEnded:motion withEvent:event];
    }
    

}

martes, 26 de mayo de 2015

UIDatePicker limitar fecha mínima y máxima. UIDatePicker limit minimum and maximum date.

@property (nonatomic, strong) UIDatePicker *temporizador;

#define DIAS_DEL_ANYO 365
#define HORAS_DEL_DIA 24
#define MINUTOS_POR_HORA 60
#define SEGUNDOS_POR_MINUTO 60
#define UN_ANYO  DIAS_DEL_ANYO * HORAS_DEL_DIA * MINUTOS_POR_HORA * SEGUNDOS_POR_MINUTO;

- (void)viewDidLoad{

  [super viewDidLoad];

  self.temporizador = [[UIDatePicker alloc] init];
  self.temporizador.datePickerMode = UIDatePickerModeDate;
    
  [self.view addSubview:self.temporizador];
  
  // intervalo
  NSTimeInterval intervaloAnyo = UN_ANYO;
    
  NSDate *fechaActual = [NSDate date];
  NSDate *fechaLimite = [fechaActual dateByAddingTimeInterval:intervaloAnyo];

 // Permite seleccionar una fecha con una año de márgen a
 //  partir de la fecha actual.

  self.temporizador.minimumDate = fechaActual;
  self.temporizador.maximumDate = fechaLimite;


}

lunes, 25 de mayo de 2015

Cambiar Tamaño texto en el contenido del HTML en un UIWebView. Change text size HTML content in UIWebView.


// Depende si es iPhone o iPad retorno el tamaño a aplicar a la fuente
#define TAMANYO_FUENTE_DISPOSITIVO() (UI_USER_INTERFACE_IDIOM() == 0) ? @"10" : @"20"


@property (strong, nonatomic) IBOutlet UIWebView *webViewPdf;



- (void) viewDidAppear:(BOOL)animated
{
    
    self.webViewPdf.scrollView.showsVerticalScrollIndicator = NO;
    
    NSURL *targetURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:_nomFichero ofType:@"html"]];
    NSString *contenidoHTML = [NSString stringWithContentsOfFile:targetURL.path encoding:NSUTF8StringEncoding error:NULL];

// Estilo aplicado a los párrafos, TAMANYO_FUENTE_TAG_P
// En el HMTL tenemos
// p {font-size:TAMANYO_FUENTE_TAG_Ppt; font-family: "Helvetica"; color: black;}


// Sustituir TAMANYO_FUENTE_TAG_P por 10 o 20 según dispositivo

    NSString *modificadoContenidoHTML = [contenidoHTML stringByReplacingOccurrencesOfString:@"TAMANYO_FUENTE_TAG_P" withString:TAMANYO_FUENTE_DISPOSITIVO()];
    
    [self.webViewPdf loadHTMLString:modificadoContenidoHTML baseURL:nil];
    

}

sábado, 23 de mayo de 2015

NSSet inicializar y recorrer valores. NSSet initialize and explore values.

// tipos de transporte
NSString *avion = @"avión";
NSString *coche = @"coche";
NSString *barco = @"barco";
NSString *metro = @"metro";
    
// creamos un set y no queremos elementos repetidos
// añadimos dos coches pero NSSet se asegura que no
// incluir dos instancias repetidas
NSSet *conjuntoTransportes = [[NSSet alloc] initWithObjects:
                     avion, coche, barco,
                     coche, metro, nil];

[conjuntoTransportes enumerateObjectsUsingBlock:^(__strong id transporte, BOOL *detener) {
  
  if ([transporte isKindOfClass:[NSString class]]){
      
    NSString *string = (NSString *)transporte;
      
    if ([string isEqualToString:@"coche"]){
      NSLog(@"Encontrado  %@ ", string);
      *detener = YES;
        
    }
      
  }
  
}];

  

viernes, 22 de mayo de 2015

NSArray Inicializar y recorrer valores. Initialize NSArray and read values.

// Puede contener diferentes tipos
// podemos guardar como si fuera una clase con propiedades
// en este caso nombre ciudad, latitud y longitud
NSArray *miciudad = @[@"NOMBRE CIUDAD", @4.1343, @1.2223];

// Recorro el contenido
for (NSInteger pos = 0; pos < [miciudad count]; pos++){
    
    id object = miciudad[pos];
    NSLog(@"Contenido:  %@", object);
    

}

Dibujar Figuras en UIView (drawRect). Draw Figures in UIView (drawRect).

/* UIView tiene que ser asignada a una UIViewController */

#import <UIKit/UIKit.h>

@interface AsignaaViewControllerView : UIView

@end


/* implemtación */

#import "AsignaaViewControllerView.h"

@implementation AsignaaViewControllerView

- (id)initWithFrame:(CGRect)frame{
    
  self = [super initWithFrame:frame];
  if (self) {
      // definir si procede
  }
  return self;
}

- (void)drawRect:(CGRect)rect{
  

  CGMutablePathRef mutablePathRef = CGPathCreateMutable();
  
  // RECTÁNGULOS
  CGRect rectanguloUnoAdibujar = CGRectMake(10.0f, 10.0f, 100.0f, 250.0f);
  CGRect rectanguloDosAdibujar = CGRectMake(50.0f, 120.0f, 70.0f, 180.0f);
  
  // ARRAY DE RECTÁNGULOS
  CGRect rectangulosAdibujar[2] = { rectanguloUnoAdibujar, rectanguloDosAdibujar };
  
  // RECTÁNGULOS EN mutablePathRef
  CGPathAddRects(mutablePathRef, NULL, (const CGRect *)&rectangulosAdibujar, 2);
  
  // CONTEXTO ACTUAL
  CGContextRef contextRef = UIGraphicsGetCurrentContext();
  CGContextAddPath(contextRef, mutablePathRef);
  
  // ATRIBUTOS
  [[UIColor colorWithRed:0.60f green:0.40f  blue:0.70f alpha:0.8f] setFill];
  [[UIColor blackColor] setStroke];
    
  CGContextSetLineWidth(contextRef,  6.0f);
  CGContextDrawPath(contextRef,  kCGPathFillStroke);

  CGPathRelease(mutablePathRef);
  

}

jueves, 21 de mayo de 2015

Escribir texto en UIView (drawRect). Write NSString at UIView (drawRect).

/* UIView tiene que ser asignada a una UIViewController */

#import <UIKit/UIKit.h>

@interface AsignaaViewControllerView : UIView

@end


/* implemtación */

#import "AsignaaViewControllerView.h"

@implementation AsignaaViewControllerView

- (id)initWithFrame:(CGRect)frame{
    
  self = [super initWithFrame:frame];
  if (self) {
      // definir si procede
  }
  return self;
}

- (void)drawRect:(CGRect)rect{
    
  // Estableces la fuente a aplicar
  UIFont *fuenteTexto =  [UIFont fontWithName:@"HelveticaNeue" size:14.0f];
  // Establecemos el texto
  NSString *cadena = @"Dibuja texto en UIView - drawRect";
  
  // Pintamos el texto en el contexto según la fuente definida en la posición 20, 200
  [cadena drawAtPoint:CGPointMake(20, 200)  withFont:fuenteTexto];
  

}