Я парень определенного возраста, который до сих пор помнит общепринятую версию 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 здесь . Если вы планируете использовать это в коммерческих целях, пожалуйста, обратите внимание на примечания по использованию для активов здесь . Наслаждайтесь!