Intereting Posts
iPhone: Как удалить правую кнопку на панели навигации в контроллере? Передача объектов Core Data из DetailViewController в другой контроллер просмотра Когда я нажимаю Viewcontroller в режиме раскадровки, изменения макета iOS – прокрутка UICollectionViewCell по горизонтали Отключите UISlider от скольжения, но все же разрешите ему получать UIControlEventTouchDown Нужна ли мне сертификация Apple MFi для написания приложения, которое общается с автомобильным радиоприемником Made for iPod через USB? Как добавить цель пакета в podspec Геолокация iOS Force, чтобы вернуть название города на определенном языке Почему self.view.frame.size.width показывает 768 в ландшафтном режиме iPad Игровая площадка swift3 не смогла получить расширение песочницы для пути Ошибка 401 – Базовая аутентификация с AFNetworking AFHTTPClient & Tastypie Есть ли способ получить интенсивность тряски? jsoncpp работает медленно после обновления цели развертывания iOS с 6.0 до 7.0 Разбор «непризнанного селектора, отправленного экземпляру» при доступе к членам PFObject Не удается прочитать файл JSON: «Текст JSON не начинался с массива или объекта»

Показывать обратный отсчет с включенными / отключенными единицами времени

Этот вопрос в основном касается пользовательского форматирования даты. Мне удалось разработать приложение обратного отсчета, которое управляет созданием события, которое позже может быть просмотрено, настроено или отслеживается клиентом. Важной частью является таймер обратного отсчета, который захватывает секунды с db и отображает оставшееся время в соответствии с форматом даты. До сих пор я использовал настройку по умолчанию в приложении, что формат счетчика был dd: hh: mm, видимо, мой клиент хочет разрешить пользователям приложения настраивать способ отображения времени. Итак, теперь пользователь может выбрать четыре варианта, например, yy: weeks: hh: mm или months: weeks: days: hours. Я думал, что лучший способ – сохранить таблицу четыре индекса в db как строку. Моя проблема появилась в календаре.

conversionInfo = [sysCalendar components:NSHourCalendarUnit | NSMinuteCalendarUnit | NSDayCalendarUnit | NSSecondCalendarUnit fromDate:today toDate:future options:0]; one = [NSString stringWithFormat:@"%d Days %d Hours %d Minutes %d Seconds %@", [conversionInfo day], [conversionInfo hour],[conversionInfo minute],[conversionInfo second], untilOrSince]; self.eventTimer.text = one; conversionInfo = [sysCalendar components: NSHourCalendarUnit | NSSecondCalendarUnit fromDate:today toDate:future options:0]; one = [NSString stringWithFormat:@"%ld Seconds %@", (long)[conversionInfo second], untilOrSince]; 

Также, если я создаю календарь со всеми единицами, но покажу только секунды, тогда обратный отсчет покажет только 59 секунд, а не 343746545 секунд, пока Счетчик

Эти календарные блоки не могут быть помещены в массив, например, так как я могу выбрать форматирование календаря, если пользователь выберет 2,4,5,6, которые будут месяцами: дни: часы: минуты? Я не могу сказать, что components = [NSArray arrayWithObjects: [arrComponents objectAtIndex:2], [arrComponents objectAtIndex:2],nil];

Параметры пользователя

Есть идеи?

Хорошо, это было тяжелее, чем я изначально думал


Во всем флажке системного блока используются для определения дат как компонентов и т. Д. Этот дефект устройства можно комбинировать только одним значением, бит-маской. Я использую его для своего кода.

Единицей года может быть 0....000010 месяца может быть 0....000100

битовая маска для обоих будет

  0....000010 NSCalendarUnitYear 0....000100 NSCalendarUnitMonth ------------ & 0....000110 

Таким образом, чтобы сохранить информацию о том, что одна единица используется, означает, что мы просто должны установить соответствующий бит в 1

 - (void)viewDidLoad { [super viewDidLoad]; self.selectedUnitsBitmask= 0; self.unitNames = @[ @"Year", @"Month", @"Week", @"Day", @"Hour", @"Minute", @"Second"]; self.units = @[@(NSCalendarUnitYear), @(NSCalendarUnitMonth), @(NSCalendarUnitWeekOfMonth), @(NSCalendarUnitDay), @(NSCalendarUnitHour), @(NSCalendarUnitMinute), @(NSCalendarUnitSecond)]; NSDateComponents *c = [[NSDateComponents alloc] init]; c.year = 2014; c.month = 12; c.day = 25; self.futureDate = [[NSCalendar currentCalendar] dateFromComponents:c]; } 

Значения self.unitNames используются для заполнения вида таблицы.
self.units сохраняют флаг устройства для каждого доступного устройства.

 -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier =@"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath]; cell.textLabel.text = _unitNames[indexPath.row]; NSUInteger s; NSUInteger row = indexPath.row; s = NSIntegerMax & [self.units[row] integerValue]; cell.accessoryType = (self.selectedUnitsBitmask & s) ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone; return cell; } 

Если ячейка выбрана, s = NSIntegerMax & [self.units[row] integerValue]; будет проверять битную маску, если это устройство должно использоваться.

Если ячейка выбрана, мы хотим переключить бит для единицы, которую она представляет

 -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { NSUInteger s; NSUInteger row = indexPath.row; s = NSIntegerMax & [self.units[row] integerValue]; self.selectedUnitsBitmask ^= s ; NSLog(@"%lu, %lu", (unsigned long)s, (unsigned long)self.selectedUnitsBitmask); UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; cell.accessoryType =(self.selectedUnitsBitmask & s) ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone; [self updateCountDownLabel:nil]; } 

Вот

 NSUInteger s; NSUInteger row = indexPath.row; s = NSIntegerMax & [self.units[row] integerValue]; 

s представляет бит, который выбран, и

 self.selectedUnitsBitmask ^= s ; 

будет переключать его в битовой маске. bitmask ^= s – это короткая форма bitmask = bitmask ^ s , где ^ является исключительной или: n-й бит битовой маски должен быть противоположным n-му биту s

  0011 bitmask ^ 0101 s ---- = 1100 

Теперь мы можем обновить строку, которая будет печатать разницу во времени в соответствии с флажками единиц, найденными в битовой маске:

 - (IBAction)updateCountDownLabel:(id)sender { BOOL includeYear = self.selectedUnitsBitmask & NSCalendarUnitYear; BOOL includeMonth = self.selectedUnitsBitmask & NSCalendarUnitMonth; BOOL includeDay = self.selectedUnitsBitmask & NSCalendarUnitDay; BOOL includeHour = self.selectedUnitsBitmask & NSCalendarUnitHour; BOOL includeMinute= self.selectedUnitsBitmask & NSCalendarUnitMinute; BOOL includeSecond= self.selectedUnitsBitmask & NSCalendarUnitSecond; NSDateComponents *diffDateComponents = [[NSCalendar currentCalendar] components:self.selectedUnitsBitmask fromDate:[NSDate date] toDate:self.futureDate options:0]; NSMutableString *outputString = [@"" mutableCopy]; if (includeYear && diffDateComponents.year) [outputString appendFormat:@"%d Year", diffDateComponents.year]; if (includeMonth && diffDateComponents.month) [outputString appendFormat:@" %d Month", diffDateComponents.month]; if (diffDateComponents.weekOfMonth < NSIntegerMax && diffDateComponents.weekOfMonth) [outputString appendFormat:@" %d Week", diffDateComponents.weekOfMonth]; if (includeDay && diffDateComponents.day) [outputString appendFormat:@" %d Day", diffDateComponents.day]; if (includeHour && diffDateComponents.hour) [outputString appendFormat:@" %d Hour", diffDateComponents.hour]; if (includeMinute && diffDateComponents.minute) [outputString appendFormat:@" %d Minute", diffDateComponents.minute]; if (includeSecond && diffDateComponents.second) [outputString appendFormat:@" %d Second", diffDateComponents.second]; self.countDownLabel.text = [outputString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; } 

Чтобы определить, был ли установлен флаг, мы имеем оператор & AND

 BOOL includeYear = self.selectedUnitsBitmask & NSCalendarUnitYear; 

если флаг года равен 0....000010

и битмаска содержит 0....010110

операция & вернется

  0....000010 NSCalendarUnitYear & 0....010110 bitmask ------------- = 0....000010 -> NSCalendarUnitYear 

мы делаем это для всех подразделений, работающих неделю. Я понятия не имею, почему, но операция & всегда возвращает 0 для этого. Здесь мы используем хак:

 if (diffDateComponents.weekOfYear < NSIntegerMax) [outputString appendFormat:@" %d Week", diffDateComponents.weekOfYear]; 

для новой week NSDateComponents создается экземпляр с наибольшим числом, представимым с целым числом, NSIntegerMax. Если его значение меньше, чем NSIntegerMax, мы предполагаем, что оно было установлено, и мы добавим его в строку.


Результат:

введите описание изображения здесь


Весь код в одной части:


 #import "ViewController.h" @interface ViewController () <UITableViewDataSource, UITableViewDelegate> @property (weak, nonatomic) IBOutlet UITableView *tableView; @property (weak, nonatomic) IBOutlet UILabel *countDownLabel; @property (nonatomic) NSInteger selectedUnitsBitmask; @property (strong, nonatomic) NSArray *unitNames; @property (strong, nonatomic) NSArray *units; @property (strong, nonatomic) NSDate *futureDate; - (IBAction)updateCountDownLabel:(id)sender; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.selectedUnitsBitmask= 0; self.unitNames = @[ @"Year", @"Month", @"Week", @"Day", @"Hour", @"Minute", @"Second"]; self.units = @[@(NSCalendarUnitYear), @(NSCalendarUnitMonth), @(NSCalendarUnitWeekOfMonth), @(NSCalendarUnitDay), @(NSCalendarUnitHour), @(NSCalendarUnitMinute), @(NSCalendarUnitSecond)]; NSDateComponents *c = [[NSDateComponents alloc] init]; c.year = 2014; c.month = 12; c.day = 25; self.futureDate = [[NSCalendar currentCalendar] dateFromComponents:c]; } -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [self.units count]; } -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier =@"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath]; cell.textLabel.text = _unitNames[indexPath.row]; NSUInteger s; NSUInteger row = indexPath.row; s = NSIntegerMax & [self.units[row] integerValue]; cell.accessoryType = (self.selectedUnitsBitmask & s) ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone; return cell; } -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { NSUInteger s; NSUInteger row = indexPath.row; s = NSIntegerMax & [self.units[row] integerValue]; self.selectedUnitsBitmask ^= s ; NSLog(@"%lu, %lu", (unsigned long)s, (unsigned long)self.selectedUnitsBitmask); UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; cell.accessoryType =(self.selectedUnitsBitmask & s) ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone; [self updateCountDownLabel:nil]; } - (IBAction)updateCountDownLabel:(id)sender { BOOL includeYear = self.selectedUnitsBitmask & NSCalendarUnitYear; BOOL includeMonth = self.selectedUnitsBitmask & NSCalendarUnitMonth; BOOL includeDay = self.selectedUnitsBitmask & NSCalendarUnitDay; BOOL includeHour = self.selectedUnitsBitmask & NSCalendarUnitHour; BOOL includeMinute= self.selectedUnitsBitmask & NSCalendarUnitMinute; BOOL includeSecond= self.selectedUnitsBitmask & NSCalendarUnitSecond; NSDateComponents *diffDateComponents = [[NSCalendar currentCalendar] components:self.selectedUnitsBitmask fromDate:[NSDate date] toDate:self.futureDate options:0]; NSMutableString *outputString = [@"" mutableCopy]; if (includeYear && diffDateComponents.year) [outputString appendFormat:@"%d Year", diffDateComponents.year]; if (includeMonth && diffDateComponents.month) [outputString appendFormat:@" %d Month", diffDateComponents.month]; if (diffDateComponents.weekOfMonth < NSIntegerMax && diffDateComponents.weekOfMonth) [outputString appendFormat:@" %d Week", diffDateComponents.weekOfMonth]; if (includeDay && diffDateComponents.day) [outputString appendFormat:@" %d Day", diffDateComponents.day]; if (includeHour && diffDateComponents.hour) [outputString appendFormat:@" %d Hour", diffDateComponents.hour]; if (includeMinute && diffDateComponents.minute) [outputString appendFormat:@" %d Minute", diffDateComponents.minute]; if (includeSecond && diffDateComponents.second) [outputString appendFormat:@" %d Second", diffDateComponents.second]; self.countDownLabel.text = [outputString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; } 

Вы можете использовать stringByAppendingString:

 NSString formattedDate = @""; formattedDate = [formattedDate stringByAppendingString:[NSString stringWithFormat:@"%d Days", [conversionInfo day]]]; formattedDate = [formattedDate stringByAppendingString:[NSString stringWithFormat:@"%d Hours", [conversionInfo hour]]]; ///.... 

Спасибо вам за все ваши ответы, я их ценю.

Прежде чем ответить, я думаю о своем собственном решении, которое может быть не таким подробным и понятным, как vikingosegundo, но оно работает, и оно может быть расширено.

Сначала из контрольной таблицы я храню четыре числа в виде строки в базе данных. Это позволяет мне хранить информацию о форматировании с помощью «события». Каждый раз, когда я хочу получить форматирование, мне нужно получить строку и изменить на массив чисел:

 int option = 0; unsigned int unitFlags = 0; NSString *input = self.detailItem.prefs; NSArray *myWords = [input componentsSeparatedByString:@","]; for (int fuu = 0; fuu < myWords.count; fuu++) { option = [[myWords objectAtIndex:fuu]intValue]; switch (option) { case 0: unitFlags = unitFlags | NSYearCalendarUnit; break; case 1: unitFlags = unitFlags | NSMonthCalendarUnit; break; case 2: unitFlags = unitFlags | NSWeekCalendarUnit; break; case 3: unitFlags = unitFlags | NSDayCalendarUnit; break; case 4: unitFlags = unitFlags | NSHourCalendarUnit; break; case 5: unitFlags = unitFlags | NSMinuteCalendarUnit; break; } } 

Как вы можете видеть, я строю свой флаг подразделения с единицами в соответствии с whats в массиве.

Теперь некоторые из того, как мне нужно создать календарь, но как я знаю, какие компоненты и форматирование?

Вот ответ:

 NSString *prularity = @""; if ([future compare:today] == NSOrderedAscending ) { conversionInfo = [sysCalendar components:unitFlags fromDate:future toDate:today options:0]; untilOrSince = @"since"; } else { conversionInfo = [sysCalendar components:unitFlags fromDate:today toDate:future options:0]; untilOrSince = @"until"; } 

Здесь я строю свой календарь с выбранными единицами, я также рассчитываю с или до даты.

Наконец, мне просто нужно сделать формат в соответствии с тем, что было выбрано:

 for (int fuu = 0; fuu < myWords.count; fuu++) { option = [[myWords objectAtIndex:fuu]intValue]; switch (option) { case 0: if ([conversionInfo year] >= 2 || [conversionInfo year] == 0) { prularity = @"YEARS"; } else { prularity = @"YEAR"; } one = [one stringByAppendingString:[NSString stringWithFormat:@"%ld %@ ", (long)[conversionInfo year], prularity]]; break; case 1: if ([conversionInfo month] >= 2|| [conversionInfo month] == 0) { prularity = @"MONTHS"; } else { prularity = @"MONTH"; } one = [one stringByAppendingString:[NSString stringWithFormat:@"%ld %@ ", (long)[conversionInfo month], prularity]]; break; case 2: if ([conversionInfo week] >= 2 || [conversionInfo week] == 0) { prularity = @"WEEKS"; } else { prularity = @"WEEK"; } one = [one stringByAppendingString:[NSString stringWithFormat:@"%ld %@ ", (long)[conversionInfo week], prularity]]; break; case 3: if ([conversionInfo day] >= 2 || [conversionInfo day] == 0) { prularity = @"DAYS"; } else { prularity = @"DAY"; } one = [one stringByAppendingString:[NSString stringWithFormat:@"%ld %@ ", (long)[conversionInfo day], prularity]]; break; case 4: if ([conversionInfo hour] >= 2 || [conversionInfo hour] == 0) { prularity = @"HOURS"; } else { prularity = @"HOUR"; } one = [one stringByAppendingString:[NSString stringWithFormat:@"%ld %@ ", (long)[conversionInfo hour], prularity]]; break; case 5: if ([conversionInfo minute] >= 2 || [conversionInfo minute] == 0) { prularity = @"MINUTES"; } else { prularity = @"MINUTE"; } one = [one stringByAppendingString:[NSString stringWithFormat:@"%ld %@ ", (long)[conversionInfo minute], prularity]]; break; } } 

И напечатайте свой счетчик:

 one = [one stringByAppendingString:[NSString stringWithFormat:@" %@",untilOrSince]]; self.eventTimer.text = one; 

Надеюсь, это поможет кому-то с подобной проблемой. Я знаю, что это не лучшее решение, но пока это сработало.