Элемент массива не может быть подключен к Objective-C

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

import UIKit
import QuartzCore


let rect : CGRect = CGRectMake(0,0,320,100)

var vista : UIView = UIView(frame: rect)

let gradient : CAGradientLayer = CAGradientLayer()
gradient.frame = vista.bounds

let cor1 = UIColor.blackColor()
let cor2 = UIColor.whiteColor()

let arrayColors = [cor1.CGColor, cor2.CGColor]

gradient.colors = arrayColors

view.layer.insertSublayer(gradient, atIndex:0)

Xcode не дает мне компилируемой ошибки, но код сбой в строке

let arrayColors = [cor1.CGColor, cor2.CGColor]

с элементом сообщения не может быть подключен к Objective-C

На самом деле я ожидал, что он рухнет там, потому что я не уверен, как создать массив CGColors в Swift. Удивительно, что Xcode упоминает Objective-C. На мой взгляд, я создавал CGColorRef в быстром...

Любые подсказки? Почему он упоминает Objective-C и как это решить?

Ответ 1

Причина Objective-C упоминается в том, что UIKit и QuartzCore являются Objective-C фреймами. В частности, gradient.colors = arrayColors вызывает метод Objective-C, который ожидает NSArray.

Это похоже на ошибку, так как в документации Apple звучит так, что массив должен автомостеризоваться до NSArray, пока элементы в массиве можно считать AnyObject:

Когда вы переходите из массива Swift в объект NSArray, элементы в массиве Swift должен быть совместим AnyObject. Например, Swift массив типа Int [] содержит элементы структуры Int. Тип Int - это не экземпляр класса, а потому, что мосты типа Int Класс NSNumber, тип Int совместим с AnyObject. Поэтому вы может связать массив Swift типа Int [] с объектом NSArray. Если элемент в массиве Swift не совместим с AnyObject, ошибка времени выполнения возникает, когда вы соединяетесь с объектом NSArray.

Вы также можете создать объект NSArray непосредственно из литерала массива Swift, следуя тем же правилам моста, описанным выше. Когда ты явно введите константу или переменную в качестве объекта NSArray и назначьте это литерал массива, Swift создает объект NSArray вместо Swift.

В настоящее время работа должна состоять в том, чтобы объявить arrayColors как NSArray:

let arrayColors: NSArray = [cor1.CGColor, cor2.CGColor]

Или объявить его как принятие AnyObject:

let arrayColors: Array <AnyObject> = [cor1.CGColor, cor2.CGColor]

Ответ 2

Эта ошибка времени выполнения также может быть запущена, если она пытается связать массив типа [MySwiftProtocol] с Objective-C.

Решение состоит в том, чтобы пометить ваш протокол @objc:

@objc protocol MySwiftProtocol {
   // ...
}

Ответ 3

Я обнаружил, что могу исправить проблему, явно используя CGColorRef, а не CGColor для моих цветов, например:

    var bottomColour:CGColorRef = UIColor.redColor().CGColor
    var topColour:CGColorRef = UIColor(red: 255.0/255.0, green: 123.0/255.0, blue: 37.0/255.0, alpha: 1.0).CGColor

    gradientLayer.colors = [bottomColour, topColour]

... работал отлично, без кавычек NSArray или AnyObject. Если я вычеркнул явный CGColorRef в объявлениях типов для цветов, я получаю ошибку "элемент массива не может быть связан с ошибкой Objective-C".

Ответ 4

С помощью массивов Swift вы можете называть bridgeToObjectiveC() на них, и они превратятся в NSArrays. То же самое относится к словарям Swift.

Ответ 5

Для тех, кто пытается заставить это работать в Swift, вы можете сделать следующее:

let arrayColors: NSArray = [UIColor.blackColor().CGColor as AnyObject, UIColor.clearColor().CGColor as AnyObject]

Я заметил, что в моем коде Objective-C я использовал типы CGColorRef для id. Не знаю, почему. Если у кого есть причина, почему это было бы здорово!