Pergunta

Eu estou começando a desenvolver para o iPhone e, como tal, eu estou olhando para diferentes tutoriais on-line, bem como tentar algumas coisas diferentes de mim. Atualmente, eu estou tentando criar uma contagem regressiva até meia-noite. Para obter o número de horas, minutos e segundos, eu faço o seguinte (que eu encontrei em algum lugar):

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

No entanto, cada lugar que eu uso -dateWithCalendarFormat:timeZone: eu recebo o seguinte erro:

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

Este parece ser algo muito simples. O que eu estou ausente?

Além disso, tenho notado em diferentes locais e em diferentes épocas do asterisco (*) é localizado logo após o NSDate* now tempo ou logo antes de a variável NSDate *now. Qual é a diferença entre os dois e por que você usaria um contra o outro?

Foi útil?

Solução

Você deve usar o seguinte:

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

Não há nenhuma diferença entre NSDate * agora e NSDate * agora, é apenas uma questão de preferência. Do ponto de vista do compilador, nada muda.

Outras dicas

Você tem problemas com iOS 4.2? Utilize 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

Você também pode usar:


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

Eu acho que isso tem as seguintes vantagens:

  1. No alocação de memória direta.
  2. Segundos é um casal em vez de um inteiro.
  3. Não há chamadas de mensagens.
  4. Faster.

// você pode obter a data / hora com o seguinte código atual:

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

Substitua o seguinte:

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

Com este:

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

Além disso, tenho notado em diferentes locais e em diferentes épocas do asterisco (*) é localizado logo após o NSDate* now tempo ou logo antes de a variável NSDate *now. Qual é a diferença entre os dois e por que você usaria um contra o outro?

O compilador não se importa, mas colocar o asterisco antes do espaço pode ser enganosa. Aqui está o meu exemplo:

int* a, b;

O que é o tipo de b?

int * Se você adivinhou, você está errado. É apenas int.

A outra maneira torna este um pouco mais clara, mantendo o * ao lado da variável a que pertence:

int *a, b;

É claro, existem duas formas que são ainda mais claro do que isso:

int b, *a;

int *a;
int b;

Você precisa fazer algo ao longo das linhas do seguinte:

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

E assim por diante.

Aqui está outra maneira:

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;

Você perde precisão subsecond com o elenco do NSTimeInterval para um int, mas isso não importa.

NSDate* now e NSDate *now são a mesma coisa:. Um ponteiro para um objeto NSDate

Você provavelmente vai querer usar descriptionWithCalendarFormat: Fuso horário: locale: em vez de dateWithCalendarFormat: - este último retorna um NSCalendarDate, que os documentos dizem está programado para ser preterido em algum ponto.

O cartaz original - a maneira que você está determinando segundos até a meia-noite não vai funcionar em um dia em que o horário de verão começa ou termina. Aqui está um pedaço de código que mostra como fazê-lo ... Vai ser em número de segundos (um NSTimeInterval); você pode fazer a divisão / módulo / etc para chegar até o que você precisa.

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

Não há nenhuma diferença na localização do asterisco (em em C, que Obj-C é baseada em, não importa). É puramente preferência (estilo).

Levei um tempo para localizar porque as obras de aplicativos de amostra, mas o meu não.

A biblioteca (Foundation.Framework) que o autor se refere é a biblioteca de sistema (a partir OS), onde o iPhone SDK (estou usando 3.0) não é apoiar mais.

Por isso, a aplicação da amostra (de about.com, http://www.appsamuck.com/day1 .html ) funciona, mas o nosso não.

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

Mark estava certo este código é muito mais eficiente para gerenciar datas horas min e segs. Mas ele esqueceu o @ no início da declaração de string de formato.

+ (NSString *)displayCurrentTimeWithAMPM 
{
    NSDateFormatter *outputFormatter = [[NSDateFormatter alloc] init];
    [outputFormatter setDateFormat:@"h:mm aa"];

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

    return dateTime;
}

retorno 03h33

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top