#ios #swift #optional #optional-binding
#iOS #быстрый #параметр-тип #необязательно-привязка
Вопрос:
Я хочу сослаться на переменную к определенной функции. Однако возникает ошибка, вызываемая Value of type 'UIView' has no member 'lineTo'
Очевидно, что whatSelectObject
переменная содержит классы, в которых существует элемент. Поэтому я использовал оператор If, «необязательная привязка». Но результаты те же самые.
//: A UIKit based Playground for presenting user interface
import UIKit
import PlaygroundSupport
class ObjectView: UIView {
var outGoingLine : CAShapeLayer?
var inComingLine : CAShapeLayer?
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func lineTo(connectToObj: ObjectView) -> CAShapeLayer {
let path = UIBezierPath()
path.move(to: CGPoint(x: self.frame.maxX, y: self.frame.midY))
path.addLine(to: CGPoint(x: connectToObj.frame.minX, y: connectToObj.frame.midY))
let line = CAShapeLayer()
line.path = path.cgPath
line.lineWidth = 5
line.fillColor = UIColor.clear.cgColor
line.strokeColor = UIColor.gray.cgColor
connectToObj.inComingLine = line
outGoingLine = line
return line
}
}
class MyViewController : UIViewController {
var whatSelectView: UIView?
override func loadView() {
let view = UIView()
view.backgroundColor = .white
let object = ObjectView(frame: CGRect(x: 10, y: 100, width: 100, height: 100))
object.backgroundColor = UIColor.orange
view.addSubview(object)
whatSelectView = object
let object2 = ObjectView(frame: CGRect(x: 200, y: 200, width: 100, height: 100))
object2.backgroundColor = UIColor.red
view.addSubview(object2)
if let s = whatSelectView {
view.layer.addSublayer(s.lineTo(connectToObj: object2)) // error
}
self.view = view
}
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()
!Этот код является примером сокращенного кода, о котором идет речь, чтобы помочь респонденту понять его.
Я могу ссылаться непосредственно на object
переменную, но я должен ссылаться на whatSelectView
в обязательном порядке.
Почему это приводит к ошибке в ссылочной переменной? Или я ошибся с необязательной привязкой?
Комментарии:
1.
if let s = whatSelectView as? ObjectView
вместоif let s = whatSelectView
. Потому что для компилятораwhatSelectView
этоUIView
(как указано в получаемой вами ошибке), поэтому id не знаетlineTo(connectToObj:)
. Сообщите компилятору с приведением, что это на самом делеObjectView
объект, поэтому он знает этот метод.2. @Larme Спасибо за ваш первый хороший ответ на вопрос.
Ответ №1:
Действительно, в UIView нет ни элемента, ни вызываемого метода lineTo
, и вам приходится использовать приведение ( as?
в вашем случае)
вот так:
if let s = whatSelectView as? ObjectView {
view.layer.addSublayer(s.lineTo(connectToObj: object2)) // error
}
Кроме того, ссылка на whatSelectView
должна быть слабой, потому что view уже содержит сильную ссылку на него, поскольку его объект является вложенным представлением.
И вам вообще не нужно условие if, у вас уже есть ссылка на представление с использованием object.
Итак, вот мое предложение по лучшей реализации
class MyViewController : UIViewController {
weak var whatSelectView: ObjectView?
override func loadView() {
let view = UIView()
view.backgroundColor = .white
let object = ObjectView(frame: CGRect(x: 10, y: 100, width: 100, height: 100))
object.backgroundColor = UIColor.orange
view.addSubview(object)
whatSelectView = object
let object2 = ObjectView(frame: CGRect(x: 200, y: 200, width: 100, height: 100))
object2.backgroundColor = UIColor.red
view.addSubview(object2)
let shape = object.lineTo(connectToObj: object2)
view.layer.addSublayer(shape)
self.view = view
}
}
Комментарии:
1. Спасибо за ваш подробный ответ. Вы сообщили мне, что есть два способа.
Ответ №2:
if let s = whatSelectView as? ObjectView {
view.layer.addSublayer(s.lineTo(connectToObj: object2))
}
это должно решить вашу проблему.
Ответ №3:
Изменить
var whatSelectView: UIView?
Для
var whatSelectView: ObjectView?
и оно будет скомпилировано. Как сказал @Larme, когда вы объявляете его как простое UIView
, вы не можете получить доступ к каким-либо элементам и функциям, которые находятся в подклассах UIView
.
Комментарии:
1. Спасибо за ваш искренний ответ и предложение.