2015-06-23 3 views
2

Будет ли это срабатывать при каждом срабатывании геттера? Или Swift кэширует его «за кулисами»?Насколько эффективен синтаксис Swift?

var colors: [UIColor] { 
get { 
    var colors = [UIColor]() 
    let palette = [UIColor.redColor(), UIColor.greenColor(), UIColor.blueColor(), UIColor.orangeColor(), UIColor.purpleColor(), UIColor.yellowColor()] 
    var paletteIndex = 0 
    for _ in 0..<photos.count { 
    colors.append(palette[paletteIndex]) 
    paletteIndex = paletteIndex == (palette.count - 1) ? 0 : ++paletteIndex 
    } 
    return colors 
} 
} 

В Objective-C геттер, как это будет позиционироваться за чеком на частном Ивар, так что Ивар устанавливается один раз, а затем Ивар вернулся на последующих вызовах.

ответ

2

Он срабатывает каждый раз, когда вызывается геттер. Ни в коем случае это не может быть оптимизировано.

Возможно, вы захотите сохранить предустановленный массив цветов в синхронизации с свойством photos, т. Е. Изменить его непосредственно при настройке фотографий.

Мне также не нравится жесткая муфта в том месте, которое кажется ненужным. Я думаю, что было бы целесообразно реорганизовать это и просто вернуть определенный цвет для заданного индекса фотографии (что тривиально с помощью оператора modulo).

Итак, мое предложение состоит в том, чтобы сохранить палитру как переменную экземпляра и просто сделать свой метод return palette[index % palette.count], что даст правильный цвет сразу.

0

Вы используете computed property, которые фактически не сохраняют значение, а значение вычисленного именованного значения или вычисленное свойство не сохраняются в памяти. Он находится в быстрой книге программирования

+1

я уверен, что ответы на большинство вопросов, задаваемых на стеки в книге где-то чувак. –

+0

Да, вы правы, но я имею в виду, что значение не хранится в памяти в книге. Таким образом, кеш @robdashnash – dopcn

1

Я буду делать это, как @Eiko предложил

let palette = [UIColor.redColor(), UIColor.greenColor(), UIColor.blueColor(), UIColor.orangeColor(), UIColor.purpleColor(), UIColor.yellowColor()] 

override func viewDidLoad() { 
    super.viewDidLoad() 
    ... 
} 

override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell { 
    let cell = collectionView.dequeueReusableCellWithReuseIdentifier("AnnotatedPhotoCell", forIndexPath: indexPath) as UICollectionViewCell 
    cell.contentView.backgroundColor = palette[indexPath.item % palette.count] 
    return cell 
} 
+1

Я не вижу необходимости в создании этого массива вообще. palette [index% photos.count] немедленно выдаст правильный цвет. Просто сделайте массив палитр экземпляром или переменной класса. ;) – Eiko

+0

Мне это нравится. поставьте это как ответ, и я его приму. –

+0

Ну, он уже почти там. :) – Eiko

0

Вы можете использовать ленивую инициализацию:

lazy var colors : [UIColor] = { 
    var colors = [UIColor.redColor] 
    // blablabla 
    return colors 
}() 

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

func recalcColors() -> [UIColor] { 
    var colors = [UIColor.redColor] 
    // blablabla 
    return colors 
} 

lazy var colors = recalcColors() 

И когда вам нужно обновить их можно назвать colors = recalcColors()

0

С Swift логической точки зрения, это будет каждый раз, но при этом, есть некоторые обстоятельства, когда оптимизатор может превратить весь расчет в константу, и в этом случае это не имеет значения.

Есть две вещи, стоящие на пути: массив palette и собственность photos.count. Теоретически массив palette никогда не изменяется, но компилятор не может этого знать, потому что он не знает, что такая функция, как redColor(), всегда возвращает то же значение. Поэтому поднимите это создание массива из свойства.

photos.count, возможно, нет фиксации, при условии, что photos динамически изменяется в процессе выполнения программы.

Но это даст вам тот же эффект и не требует создания каких-либо массивов на всех:

struct PaletteCycler { 
    let palette = [ 
     UIColor.redColor(), UIColor.greenColor(), 
     UIColor.blueColor(), UIColor.orangeColor(), 
     UIColor.purpleColor(), UIColor.yellowColor(), 
    ] 

    subscript(idx: Int)->UIColor { 
     return palette[idx%palette.count] 
    } 
} 

let colors = PaletteCycler() 

Поскольку все постоянно существует очень мало затрат времени выполнения для извлечения цвета. В отличие от исходной версии, это не создает массив каждый раз. Поскольку mod и fetch довольно эффективны, а переменная palette постоянна, она должна быть быстрой.

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

let palette = [ 
    UIColor.redColor(), UIColor.greenColor(), 
    UIColor.blueColor(), UIColor.orangeColor(), 
    UIColor.purpleColor(), UIColor.yellowColor(), 
] 

var colors: [UIColor] = { 

    // Swift 2.0 syntax. For 1.2, write 
    // indices(photos).map 
    return photos.indices.map { 
     palette[$0 % palette.count] 
    } 

} 
Смежные вопросы