2009-07-01 13 views
55

Je commence à développer pour l'iPhone et en tant que tel, je regarde différents tutoriels en ligne ainsi que d'essayer des choses différentes sur moi-même. Actuellement, j'essaye de créer un compte à rebours jusqu'à minuit. Pour obtenir le nombre d'heures, minutes et secondes, je fais ce qui suit (que je trouvais quelque part):Comment obtenir la date actuelle dans 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]; 

Cependant, chaque endroit où j'utilise -dateWithCalendarFormat:timeZone: je reçois l'erreur suivante:

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') 

Cela semble être quelque chose de très simple. Qu'est-ce que je rate?

En outre, j'ai remarqué à différents endroits et à des moments différents l'astérisque (*) est situé soit juste après l'heure NSDate* now ou juste avant la variable NSDate *now. Quelle est la différence entre les deux et pourquoi utiliseriez-vous l'un par rapport à l'autre?

Répondre

47

Vous devez utiliser les éléments suivants:

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]; 

Il n'y a pas de différence entre NSDate * maintenant et NSDate * maintenant, il est juste une question de préférence. Du point de vue du compilateur, rien ne change.

+0

Pourquoi vous devez utiliser NSCalendar est-ce une récente changement? Il y a beaucoup de code qui utilise NSDate pour ces choses. – Jason

+0

Oui, de nombreuses méthodes sont maintenant obsolètes. –

+2

Jason: NSDate est toujours là. Vous utilisez NSCalendarDate (c'est ce que -dateWithCalendarFormat: timeZone: renvoie), qui est prévu pour la dépréciation et n'existe pas sur l'iPhone. –

0

Il n'y a pas de différence dans l'emplacement de l'astérisque (en C, sur lequel Obj-C est basé, cela n'a pas d'importance). C'est purement préférence (style).

2

NSDate* now et NSDate *now sont la même chose: un pointeur vers un objet NSDate.

Vous voulez probablement utiliser descriptionWithCalendarFormat: timeZone: locale: plutôt que dateWithCalendarFormat: - ce dernier renvoie un NSCalendarDate, que les documents disent devrait être dépréciée à un moment donné.

3

Vous devez faire quelque chose le long des lignes de ce qui suit:

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

Et ainsi de suite.

1

Voici une autre façon:

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; 

Vous perdez une précision plus fine avec les acteurs de la NSTimeInterval à un int, mais cela ne devrait pas d'importance.

+0

Au second coup d'œil, l'iPhone SDK peut ne pas avoir la méthode - (NSDate) dateWithNaturalLanguageString: (NSString *) str donc cela peut être une solution de Leopard/Tiger seulement. Désolé –

21

Vous pouvez également utiliser:


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 

Je pense que cela présente les avantages suivants:

  1. Aucune allocation de mémoire directe.
  2. Seconds est un double au lieu d'un nombre entier.
  3. Aucun appel de message.
  4. Plus rapide.
+1

Opps vous avez oublié d'ajouter "@" sur votre stringWithFormat. En tout cas merci pour ça. – andsien

+0

Vous devez libérer la référence retournée par CFTimeZoneCopySystem(), sinon vous aurez une fuite de mémoire. – 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?

Le compilateur ne se soucie pas, mais mettre l'astérisque avant que l'espace peut être trompeur.Voici mon exemple:

int* a, b; 

Quel est le type de b?

Si vous avez deviné int *, vous avez tort. C'est juste int.

L'autre façon en fait un peu plus clair en gardant le * à côté de la variable, il appartient à:

int *a, b; 

Bien sûr, il y a deux façons qui sont encore plus clairs que:

int b, *a; 

int *a; 
int b; 
+0

Oui, c'est un bon argument pour: soit attacher toujours le * au nom de la variable; ou ne jamais déclarer deux variables sur la même ligne. Personnellement, puisque je préfère penser au «pointeur vers» comme faisant partie du type, je choisis la dernière solution, mais les gens devraient certainement être conscients de ce problème. –

0

Il m'a fallu du temps pour trouver pourquoi l'application d'échantillon fonctionne mais pas la mienne.

La bibliothèque (Foundation.Framework) à laquelle l'auteur fait référence est la bibliothèque système (de l'OS) où l'iphone sdk (j'utilise 3.0) n'est plus supporté.

Par conséquent, l'exemple d'application (de about.com, http://www.appsamuck.com/day1.html) fonctionne mais pas le nôtre.

+0

Foundation fait toujours partie du kit de développement iPhone. Vous ne pouvez vraiment pas vous en passer. Ce qui manque, c'est NSCalendarDate, qui n'a jamais été disponible sur l'iPhone (pour autant que je sache). –

5

Remplacer ceci:

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]; 

Avec ceci:

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' ne fonctionne pas pour moi. L'identifiant 'now' n'est pas défini ou quoi que ce soit. Comment l'initialiser avec la date actuelle? –

+0

Ah, '[NSDate initWithTimeIntervalSinceNow: 0]' semble être le chemin. –

+0

En fait '[NSDate init]' va en créer un avec l'heure actuelle. –

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

Mark était juste ce code est beaucoup plus efficace pour gérer les dates et heures min sec. Mais il a oublié le @ au début de la déclaration de chaîne de format.

+1

Ne pas oublier le 0 devant le troisième 2, pendant que vous y êtes. Sinon, les secondes inférieures à 10 apparaîtront comme (par exemple) ": 6". –

57

Vous avez des problèmes avec iOS 4.2? Utilisez ce code:

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 fait 'YY' sortira l'année en 2 chiffres. "YYYY" sortira l'année en 4 chiffres. – Bot

1

Affiche originale - la façon dont vous déterminer secondes jusqu'à minuit ne fonctionnera pas un jour où commence l'heure d'été ou se termine. Voici un morceau de code qui montre comment le faire ... Ce sera en nombre de secondes (un NSTimeInterval); vous pouvez faire la division/module/etc pour descendre à tout ce dont vous avez besoin.

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; 
} 

retour 03h33

12

// vous pouvez obtenir la date/heure avec le code suivant:

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]; 
Questions connexes