Я парень определенного возраста, который до сих пор помнит общепринятую версию Nixie Tubes : когда я рос, у нас были цифровые часы, которые отображали время вместе с ними, и тогда это был верх технического совершенства. Когда я наткнулся на эти активы , я не удержался от создания простого компонента Swift для отображения чисел и простых строк в чрезвычайно скейоморфном стиле ретро.
Мой компонент FMNixieDigitDisplay очень прост в реализации: после создания экземпляра и добавления его в целевое представление:
let nixieDigitDisplay = FMNixieDigitDisplay(numberOfDigits: 8)
view.addSubview(nixieDigitDisplay)
Его intrinsicContentSize может использоваться для определения размера и размещения. Здесь я центрирую его на родительском представлении:
nixieDigitDisplay.frame = CGRect(
x: view.frame.width / 2 - nixieDigitDisplay.intrinsicContentSize().width / 2,
y: view.frame.height / 2 - nixieDigitDisplay.intrinsicContentSize().height / 2,
width: nixieDigitDisplay.intrinsicContentSize().width,
height: nixieDigitDisplay.intrinsicContentSize().height)
Компонент имеет три функции setValue, которые поддерживают целые числа, числа с плавающей запятой или простые строки:
nixieDigitDisplay.setValue(int: 1234)
nixieDigitDisplay.setValue(float: 123.456)
nixieDigitDisplay.setValue(string: "12.34-56")
Единственные нечисловые символы, которые поддерживает дисплей, — это тире и точки. Любые другие символы будут отображаться как пустое место.
Компонент FMNixieDigitDisplay содержит массив FMNixieDigit, который отображает отдельные цифры. Чтобы получить плавное перекрестное затухание при изменении цифры, я использую UIView.transitionFromView для перехода между двумя экземплярами UIImageView.
Например, когда FMNixieDigit создается впервые, его логическое свойство useEven устанавливается в значение true, а из двух его представлений изображения даже DigitView и oddDigitView в представление добавляется только oddDigitView. Когда его значение изменяется, он устанавливает свойство изображения evenDigitView и выполняет:
UIView.transitionFromView(oddDigitView, toView: evenDigitView, duration: 0.5, options: animationOptions, completion: nil)
Этот код удаляет oddDigitView из своего суперпредставления и добавляет в этот же суперпредставление evenDigitView с распадом. С помощью togglinguseEven при каждом изменении я получаю плавный переход с каждым разом.
Когда я впервые начал писать FMNixieDigitDisplay, моей единственной мыслью было отображение целых чисел, поэтому его setValue (Int) использует логарифм значения 10, чтобы выяснить, сколько символов требуется, а затем повторяет это много раз, постепенно увеличивая его до возрастающей степени десять, чтобы найти текущую цифру по модулю 10:
let numberOfChars = Int(ceil(log10(Double(value))))
for i in 0 ..< numberOfChars
{
let digitValue = floor((Double(value) / pow(10.0, Double(i)))) % 10
nixieDigits[i].value = Int(digitValue)
}
Затем я подумал, что было бы неплохо поддерживать числа с плавающей запятой, поэтому добавил больше кода, разбивающего значение на целую часть дробной части, используя modf () и продвигаясь назад через дробную часть:
for i in (numberOfDigits - numberOfChars - 1).stride(to: 0, by: -1)
{
let digitValue = modf(value).1 * pow(10.0, Float(numberOfDigits - numberOfChars - i)) % 10
if i - 1 >= 0
{
nixieDigits[i - 1].value = Int(digitValue)
}
}
Наконец, я решил добавить setValue (String) для отображения простых строк, состоящих из цифр, точек и тире. Это повторяет символы значения и устанавливает каждую цифру соответственно. Оглядываясь назад, и целочисленные, и реализации с плавающей точкой setValue () могли бы использовать эту технику и сделать код намного проще. Тем не менее, мне очень нравятся эти первые две функции, и, поскольку это не рабочий код, я сохранил весь код.
Код контроллера демонстрационного представления использует NSTimer для обновления экземпляра FMNixieDigitDisplay каждую секунду с текущим временем. Здесь я разбиваю NSDate на составные части и формирую строку для отображения времени:
let date = NSDate()
let calendar = NSCalendar.currentCalendar()
let components = calendar.components(
NSCalendarUnit(rawValue: NSCalendarUnit.Hour.rawValue | NSCalendarUnit.Minute.rawValue | NSCalendarUnit.Second.rawValue),
fromDate: date)
let hour = components.hour
let minute = components.minute
let second = components.second
print(hour, minute, second)
nixieDigitDisplay.setValue(string: "\(hour).\(minute)-\(second)")
Весь код для этого компонента доступен в моем репозитории GitHub здесь . Если вы планируете использовать это в коммерческих целях, пожалуйста, обратите внимание на примечания по использованию для активов здесь . Наслаждайтесь!