2009-07-01 23 views
55

Zaczynam się rozwijać dla iPhone'a i jako takie patrzę na różne tutoriale online, jak również próbuję różnych rzeczy samemu. Obecnie próbuję odliczać do północy. Aby uzyskać liczbę godzinę, minuty i sekundy, mam następujące (który znalazłem gdzieś):Jak uzyskać aktualną datę w 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]; 

Jednak każde miejsce używam -dateWithCalendarFormat:timeZone: pojawia się następujący błąd:

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

Wydaje się to być bardzo proste. czego mi brakuje?

Ponadto zauważyłem w różnych miejscach iw różnych momentach gwiazdka (*) znajduje się zaraz po czasie NSDate* now lub tuż przed zmienną NSDate *now. Jaka jest różnica między tymi dwoma elementami i dlaczego używałbyś jednego w porównaniu do drugiego?

Odpowiedz

47

Musisz użyć następujących:

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

Nie ma różnicy między NSDate * teraz i NSDate * teraz, to tylko kwestia preferencji. Z punktu widzenia kompilatora nic się nie zmienia.

+0

Dlaczego trzeba używać NSCalendar jest to ostatnie zmiana? Istnieje wiele kodu, który używa NSDate do tych rzeczy. – Jason

+0

Tak, wiele metod jest obecnie przestarzałych. –

+2

Jason: NSDate nadal tam jest. Używasz NSCalendarDate (to właśnie -dateWithCalendarFormat: timeZone: zwraca), który jest przeznaczony do wycofywania i nie istnieje na iPhone'ie. –

0

Nie ma różnicy w położeniu gwiazdki (w punkcie C, na którym opiera się Obj-C, to nie ma znaczenia). To czysta preferencja (styl).

2

NSDate* now i NSDate *now to to samo: wskaźnik do obiektu NSDate.

Prawdopodobnie chcesz użyć descriptionWithCalendarFormat: Strefa czasowa: Ustawienia regionalne: zamiast dateWithCalendarFormat: - tych ostatnich zwraca NSCalendarDate, który docs powiedzieć planowane jest przestarzałe w pewnym momencie.

3

Trzeba zrobić coś wzdłuż linii następujących czynności:

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

i tak dalej.

1

Oto kolejny sposób:

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; 

Tracisz dokładnością subsekundową z obsady NSTimeInterval na int, ale to nie powinno mieć znaczenia.

+0

Po drugie, pakiet iPhone SDK może nie mieć metody - (NSDate) dateWithNaturalLanguageString: (NSString *), więc może to być rozwiązanie wyłącznie dla systemu Leopard/Tiger. Przepraszam –

21

Można również użyć:


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 

myślę, że to ma następujące zalety:

  1. Brak bezpośredniego alokacji pamięci.
  2. Sekundy są podwójne zamiast liczby całkowitej.
  3. Brak wiadomości.
  4. Szybciej.
+1

Opps zapomniałem dodać "@" na stringWithFormat. W każdym razie dzięki za to. – andsien

+0

Należy zwolnić referencję zwróconą przez CFTimeZoneCopySystem(), w przeciwnym razie wystąpi przeciek pamięci. – 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?

Kompilator nie obchodzi, ale stawianie gwiazdkę przed przestrzeni może być mylące.Oto mój przykład:

int* a, b; 

Jaki jest typ b?

Jeśli zgadłeś int *, jesteś w błędzie. To tylko int.

Innym sposobem czyni to nieco jaśniejsze poprzez utrzymywanie * obok zmiennej należy do:

int *a, b; 

Oczywiście, istnieją dwa sposoby, które są jeszcze wyraźniejsze niż:

int b, *a; 

int *a; 
int b; 
+0

Tak, jest to dobry argument: zawsze dołączaj * do nazwy zmiennej; lub nigdy nie zadeklaruj dwóch zmiennych w tej samej linii. Osobiście, ponieważ wolę myśleć o "wskaźniku do" jako rodzaju, wybieram to drugie rozwiązanie, ale ludzie powinni zdawać sobie z tego sprawę. –

0

Zajęło mi trochę czasu, aby zlokalizować, dlaczego przykładowa aplikacja działa, ale moja nie.

Biblioteka (Foundation.Framework), do której odwołuje się autor, to biblioteka systemowa (z systemu operacyjnego), w której sdk (używam wersji 3.0) nie jest już obsługiwany.

Dlatego przykładowa aplikacja (z about.com, http://www.appsamuck.com/day1.html) działa, ale nasza nie.

+0

Fundacja nadal jest częścią iPhone SDK. Naprawdę nie możesz się bez niego obejść. Brakuje NSCalendarDate, który nigdy nie był dostępny na iPhone'ie (o ile wiem). –

5

Wymień to:

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

z tym:

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' nie działa dla mnie. Identyfikator "teraz" nie jest zdefiniowany lub cokolwiek innego. Jak zainicjować go z bieżącą datą? –

+0

Ah, '[NSDate initWithTimeIntervalSinceNow: 0]' wydaje się być właściwą drogą. –

+0

W rzeczywistości '[NSDate init]' utworzy jeden z bieżącym czasem. –

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

Mark miał rację ten kod jest znacznie bardziej efektywne zarządzanie daktyle godzin min i sek. Ale zapomniał @ na początku deklaracji ciągu formatów.

+1

Nie zapomnij o 0 przed trzecim 2, gdy jesteś przy tym. W przeciwnym razie, sekundy mniej niż 10 będą wyświetlane jako (na przykład) ": 6". –

57

Masz problemy z iOS 4.2? Użyj tego kodu:

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

właściwie "YY" wypisze rok w 2 cyfrach. "YYYY" wypisze rok w 4 cyfrach. – Bot

1

oryginalny plakat - sposób jesteś ustalania sekundy do północy nie będzie działać w dniu, kiedy rozpoczyna się letni lub kończy się. Oto fragment kodu, który pokazuje, jak to zrobić ... Będzie to liczba sekund (NSTimeInterval); możesz zrobić podział/moduł/etc, aby uzyskać wszystko, czego potrzebujesz.

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

powrót 03:33

12

// można uzyskać bieżącą datę/czas z następującego kodu:

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]; 
Powiązane problemy