2009-07-01 19 views
55

Estoy empezando a desarrollar para el iPhone y, como tal, estoy buscando diferentes tutoriales en línea, así como probando algunas cosas por mi cuenta. Actualmente, intento crear una cuenta atrás hasta la medianoche. Para obtener el número de horas, minutos y segundos, hago lo siguiente (que he encontrado en alguna parte):Cómo obtengo la fecha actual en Cocoa

NSDate* now = [NSDate date]; 

int hour = 23 - [[now dateWithCalendarFormat:nil timeZone:nil] hourOfDay]; 
int min = 59 - [[now dateWithCalendarFormat:nil timeZone:nil] minuteOfHour]; 
int sec = 59 - [[now dateWithCalendarFormat:nil timeZone:nil] secondOfMinute]; 
countdownLabel.text = [NSString stringWithFormat:@"%02d:%02d:%02d", hour, min,sec]; 

Sin embargo, cada lugar que utilizo -dateWithCalendarFormat:timeZone: me sale el siguiente error:

warning: 'NSDate' may not respond to '-dateWithCalendarFormat:timeZone:' 
(Messages without a matching method signature will be assumed to return 'id' and accept '...' as arguments.) 
warning: no '-hourOfDay' method found 
error: invalid operands to binary - (have 'int' and 'id') 

Esto parece algo muy simple. ¿Qué me estoy perdiendo?

Además, he notado en diferentes lugares y en diferentes momentos que el asterisco (*) se encuentra justo después del tiempo NSDate* now o justo antes de la variable NSDate *now. ¿Cuál es la diferencia en los dos y por qué usarías uno frente al otro?

Respuesta

47

debe utilizar el siguiente:

NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; 
NSDateComponents *dateComponents = [gregorian components:(NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit) fromDate:yourDateHere]; 
NSInteger hour = [dateComponents hour]; 
NSInteger minute = [dateComponents minute]; 
NSInteger second = [dateComponents second]; 
[gregorian release]; 

No hay diferencia entre NSDate * ahora * NSDate y ahora, es sólo una cuestión de preferencia. Desde la perspectiva del compilador, nada cambia.

+0

¿Por qué tienes que utilizar este NSCalendar es una reciente ¿cambio? Hay muchos códigos que usan NSDate para estas cosas. – Jason

+0

Sí, muchos métodos ahora están en desuso. –

+2

Jason: NSDate todavía está allí. Está utilizando NSCalendarDate (eso es lo que -dateWithCalendarFormat: timeZone: returns), que está programado para desactivarse y no existe en el iPhone. –

0

No hay diferencia en la ubicación del asterisco (en C, en el que se basa Obj-C, no importa). Es puramente preferencia (estilo).

2

NSDate* now y NSDate *now son lo mismo: un puntero a un objeto NSDate.

es probable que desee utilizar descriptionWithCalendarFormat: timeZone: locale: en lugar de dateWithCalendarFormat: - éste vuelve un NSCalendarDate, que los documentos dicen que está programado para ser obsoleto en algún momento.

3

que tiene que hacer algo en la línea de lo siguiente:

NSDate *now = [NSDate date]; 
NSCalendar *calendar = [NSCalendar currentCalendar]; 
NSDateComponents *components = [calendar components:NSHourCalendarUnit fromDate:now]; 
NSLog(@"%d", [components hour]); 

Y así sucesivamente.

1

Ésta es otra manera:

NSDate *now = [NSDate date]; 

//maybe not 100% approved, but it works in English. You could localize if necessary 
NSDate *midnight = [NSDate dateWithNaturalLanguageString:@"midnight tomorrow"]; 

//num of seconds between mid and now 
NSTimeInterval timeInt = [midnight timeIntervalSinceDate:now]; 
int hours = (int) timeInt/3600; 
int minutes = ((int) timeInt % 3600)/60; 
int seconds = (int) timeInt % 60; 

Se pierde precisión por debajo con el elenco de la NSTimeInterval a un int, pero eso no debería importar.

+0

En segundo lugar, el iPhone SDK puede no tener - (NSDate) dateWithNaturalLanguageString: (NSString *) str método por lo que esta puede ser una solución Leopard/Tiger solamente. Lo siento –

21

También puede utilizar:


CFGregorianDate currentDate = CFAbsoluteTimeGetGregorianDate(CFAbsoluteTimeGetCurrent(), CFTimeZoneCopySystem()); 
countdownLabel.text = [NSString stringWithFormat:@"%02d:%02d:%02.0f", currentDate.hour, currentDate.minute, currentDate.second]; 
CFRelease(currentDate); // Don't forget this! VERY important 

Creo que esto tiene las siguientes ventajas:

  1. Sin asignación de memoria directa.
  2. Segundos es un doble en lugar de un número entero.
  3. Sin llamadas de mensajes.
  4. Más rápido.
+1

Opp que se olvidó de agregar "@" en su stringWithFormat. De todos modos, gracias por esto. – andsien

+0

Debe liberar la referencia devuelta por CFTimeZoneCopySystem(), de lo contrario, se produce una pérdida de memoria. – brutella

4

Also, I've noticed at different places and at different times the asterisk (*) is located either right after the time NSDate* now or right before the variable NSDate *now . What is the difference in the two and why would you use one versus the other?

El compilador no le importa, pero poniendo el asterisco antes de que el espacio puede ser engañosa.Aquí está mi ejemplo:

int* a, b; 

¿Cuál es el tipo de b?

Si adivinó int *, está equivocado. Es solo int.

La otra forma hace que esta un poco más clara, manteniendo el * junto a la variable que pertenece a:

int *a, b; 

Por supuesto, hay dos maneras que son aún más claro que eso:

int b, *a; 

int *a; 
int b; 
+0

Sí, este es un buen argumento para cualquiera de los dos: siempre adjunte el * al nombre de la variable; o nunca declare dos variables en la misma línea. Personalmente, dado que prefiero pensar en el "puntero a" como parte del tipo, elijo la última solución, pero la gente definitivamente debe estar al tanto de este problema. –

0

Me tomó un tiempo encontrar por qué funciona la aplicación de muestra, pero la mía no.

La biblioteca (Foundation.Framework) a la que se refiere el autor es la biblioteca del sistema (del sistema operativo) donde el iphone sdk (estoy usando 3.0) ya no es compatible.

Por lo tanto, la aplicación de muestra (de about.com, http://www.appsamuck.com/day1.html) funciona pero la nuestra no.

+0

Foundation sigue siendo parte del iPhone SDK. Realmente no puedes prescindir de eso. Lo que falta es NSCalendarDate, que nunca ha estado disponible en el iPhone (hasta donde yo sé). –

5

Reemplazar esta:

NSDate* now = [NSDate date]; 
int hour = 23 - [[now dateWithCalendarFormat:nil timeZone:nil] hourOfDay]; 
int min = 59 - [[now dateWithCalendarFormat:nil timeZone:nil] minuteOfHour]; 
int sec = 59 - [[now dateWithCalendarFormat:nil timeZone:nil] secondOfMinute]; 
countdownLabel.text = [NSString stringWithFormat:@"%02d:%02d:%02d", hour, min,sec]; 

Con esta:

NSDate* now = [NSDate date]; 
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; 
NSDateComponents *dateComponents = [gregorian components:(NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit) fromDate:now]; 
NSInteger hour = [dateComponents hour]; 
NSInteger minute = [dateComponents minute]; 
NSInteger second = [dateComponents second]; 
[gregorian release]; 
countdownLabel.text = [NSString stringWithFormat:@"%02d:%02d:%02d", hour, minute, second]; 
+0

'fromDate: now' no funciona para mí. El identificador 'now' no está definido o lo que sea. ¿Cómo lo inicializas con la fecha actual? –

+0

Ah, '[NSDate initWithTimeIntervalSinceNow: 0]' parece ser el camino. –

+0

En realidad '[NSDate init]' creará uno con la hora actual. –

0
CFGregorianDate currentDate = CFAbsoluteTimeGetGregorianDate(CFAbsoluteTimeGetCurrent(), CFTimeZoneCopySystem()); 
countdownLabel.text = [NSString stringWithFormat:@"%02d:%02d:%2.0f", currentDate.hour, currentDate.minute, currentDate.second]; 

marca fue en este mismo código es mucho más eficiente para manejar fechas y horas minutos segundos. Pero olvidó el @ al comienzo de la declaración de cadenas de formato.

+1

No olvide el 0 en frente del tercero 2, mientras lo hace. De lo contrario, segundos menos de 10 saldrán como (por ejemplo) ": 6". –

57

¿Tiene problemas con iOS 4.2? utilizar este código:

NSDate *currDate = [NSDate date]; 
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init]; 
[dateFormatter setDateFormat:@"dd.MM.YY HH:mm:ss"]; 
NSString *dateString = [dateFormatter stringFromDate:currDate]; 
NSLog(@"%@",dateString); 

-> 20.01.2011 10:36:02

+5

en realidad 'YY' arrojará el año en 2 dígitos. 'YYYY' arrojará el año en 4 dígitos. – Bot

1

Cartel original - la forma en que está la determinación de segundos hasta la medianoche no funcionará en un día en que comienza el horario de verano o termina Aquí hay un fragmento de código que muestra cómo hacerlo ... Será en número de segundos (un NSTimeInterval); puedes hacer la división/módulo/etc. para llegar a lo que necesites.

NSDateComponents *dc = [[NSCalendar currentCalendar] components:NSDayCalendarUnit|NSMonthCalendarUnit|NSYearCalendarUnit fromDate:[NSDate date]]; 
[dc setDay:dc.day + 1]; 
NSDate *midnightDate = [[NSCalendar currentCalendar] dateFromComponents:dc]; 
NSLog(@"Now: %@, Tonight Midnight: %@, Hours until midnight: %.1f", [NSDate date], midnightDate, [midnightDate timeIntervalSinceDate:[NSDate date]]/60.0/60.0); 
0
+ (NSString *)displayCurrentTimeWithAMPM 
{ 
    NSDateFormatter *outputFormatter = [[NSDateFormatter alloc] init]; 
    [outputFormatter setDateFormat:@"h:mm aa"]; 

    NSString *dateTime = [NSString stringWithFormat:@"%@",[outputFormatter stringFromDate:[NSDate date]]]; 

    return dateTime; 
} 

retorno 3:33 AM

12

// puede obtener la fecha/hora con el siguiente código:

NSDate* date = [NSDate date]; 
    NSDateFormatter* formatter = [[NSDateFormatter alloc] init]; 
    NSTimeZone *destinationTimeZone = [NSTimeZone systemTimeZone]; 
    formatter.timeZone = destinationTimeZone; 
    [formatter setDateStyle:NSDateFormatterLongStyle]; 
    [formatter setDateFormat:@"MM/dd/yyyy hh:mma"]; 
    NSString* dateString = [formatter stringFromDate:date]; 
Cuestiones relacionadas