Почему завершается с неисследованным исключением типа NSException в .addObserver

это то, как мы делаем объект класса итерабельным. предоставить класс с помощью метода iter и next (), тогда вы можете перебирать атрибуты класса или их значения. Вы можете оставить метод next (), если хотите, или вы можете определить next () и повысить StopIteration при некотором условии .

например:

class Book(object):
      def __init__(self,title,author):
          self.title = title
          self.author = author

      def __iter__(self):
          for each in self.__dict__.keys():
              yield self.__getattribute__(each)

>>> book  = Book('The Mill on the Floss','George Eliot')
>>> for each in book: each
...
'George Eliot'
'The Mill on the Floss'

этот класс выполняет итерацию над значением атрибута класса Book. Объект класса можно сделать итерабельным, предоставив ему метод getitem. например:

class BenTen(object):
    def __init__(self, bentenlist):
        self.bentenlist = bentenlist

    def __getitem__(self,index):
        if index <5:
            return self.bentenlist[index]
        else:
            raise IndexError('this is high enough')

>>> bt_obj = BenTen([x for x in range(15)])
>>>for each in bt_obj:each
...
0
1
2
3
4

теперь, когда объект класса BenTen используется во внутреннем цикле, getitem вызывается с успешным более высоким значением индекса, пока он не вызовет IndexError.

-1
задан PARK UI SUK 18 March 2019 в 16:51
поделиться

1 ответ

Вам необходимо вывести свои функции observeValueForKeyPath:ofObject:change:context и updateLine из функции loadView().

Функция observeValueForKeyPath:ofObject:change:context нуждается в переопределении на уровне ViewController, так как вы добавили наблюдателя на self, который в данном случае является контроллером представления.

См. Ниже:

import UIKit
import PlaygroundSupport

class MyViewController : UIViewController {
    private var animator: UIDynamicAnimator?
    private var gravity: UIGravityBehavior?
    private var attach: UIAttachmentBehavior?
    private var plateView: UIView?

    var lineLayer: CAShapeLayer?

    override func loadView() {
        let view = UIView()
        view.backgroundColor = .white
        self.view = view

        plateView = UIView(frame: CGRect(x: 80, y: 150, width: 60, height: 60))
        plateView?.backgroundColor = UIColor.orange
        self.view.addSubview(plateView!)

        animator = UIDynamicAnimator(referenceView: view)

        gravity = UIGravityBehavior(items: [plateView!])
        animator?.addBehavior(gravity!)

        attach = UIAttachmentBehavior(item: plateView!, offsetFromCenter: UIOffset(horizontal: 0, vertical: -30), attachedToAnchor: CGPoint(x: 200, y: 100))

        attach?.damping = 0.1
        attach?.frequency = 0.6
        animator?.addBehavior(attach!)

        plateView?.addObserver(self, forKeyPath: "center", options: .new, context: nil)
    }

    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        updateLine()
    }

    func updateLine() {
        if nil == lineLayer {
            lineLayer = CAShapeLayer()
            lineLayer?.strokeColor = UIColor.purple.cgColor
            lineLayer?.fillColor = UIColor.clear.cgColor
            lineLayer?.lineWidth = 1.5
            lineLayer?.lineJoin = .round
            lineLayer?.strokeEnd = 1.0
            self.view.layer.addSublayer(lineLayer!)
        }

        let platePoint = view.convert(CGPoint(x: plateView!.bounds.midX, y: 0), from: plateView)
        let bezierPath = UIBezierPath()
        bezierPath.move(to: attach!.anchorPoint)
        bezierPath.addLine(to: platePoint)
        lineLayer?.path = bezierPath.cgPath
    }

}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()
0
ответ дан Alex Cornforth 18 March 2019 в 16:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: