[neu geschrieben, nachdem weitere Forschung]
Hier ist eine aufwendige Abhilfe basierend auf dem unten
http://nshipster.com/swift-objc-runtime/
[WARNUNG von den Autoren]
Abschließend erinnern, dass mit Bastelei Die Objective-C-Laufzeitumgebung sollte eher ein letzter Ausweg als ein Startpunkt sein. Das Ändern der Frameworks, auf denen Ihr Code basiert, sowie der von Ihnen ausgeführte Code von Drittanbietern ist eine schnelle Möglichkeit, den gesamten Stack zu destabilisieren. Trete sanft!
Also hier ist es, müssen alle Accessoren und Mutatoren abgedeckt werden, so ist es eine Menge. Plus, da Sie mit den Werten intervenieren müssen, aber die ursprüngliche gespeicherte Eigenschaft erneut verwenden müssen, da Sie hier keinen neuen Speicher einführen können, haben Sie einige seltsam aussehende Funktionen, die rekursiv zu sein scheinen, aber nicht wegen Laufzeitwechsel . Dies ist das erste Mal, dass der Compiler eine Warnung für meinen Code generiert hat, von dem ich weiß, dass er zur Laufzeit ist.
Naja, es ist eine interessante akademische Übung.
extension UIScrollView {
struct StaticVars {
static var token: dispatch_once_t = 0
}
public override class func initialize() {
dispatch_once(&StaticVars.token) {
guard self == UIScrollView.self else {
return
}
// Accessor
method_exchangeImplementations(
class_getInstanceMethod(self, Selector("swizzledContentOffset")),
class_getInstanceMethod(self, Selector("contentOffset"))
)
// Two-param setter
method_exchangeImplementations(
class_getInstanceMethod(self, #selector(UIScrollView.setContentOffset(_:animated:))),
class_getInstanceMethod(self, #selector(UIScrollView.swizzledSetContentOffset(_:animated:)))
)
// One-param setter
method_exchangeImplementations(
class_getInstanceMethod(self, #selector(UIScrollView.swizzledSetContentOffset(_:))),
class_getInstanceMethod(self, Selector("setContentOffset:")))
}
}
func swizzledSetContentOffset(inContentOffset: CGPoint, animated: Bool) {
print("Some interceding code for the swizzled 2-param setter with \(inContentOffset)")
// This is not recursive. The method implementations have been exchanged by runtime. This is the
// original setter that will run.
swizzledSetContentOffset(inContentOffset, animated: animated)
}
func swizzledSetContentOffset(inContentOffset: CGPoint) {
print("Some interceding code for the swizzled 1-param setter with \(inContentOffset)")
swizzledSetContentOffset(inContentOffset) // not recursive
}
var swizzledContentOffset: CGPoint {
get {
print("Some interceding code for the swizzled accessor: \(swizzledContentOffset)") // false warning
return swizzledContentOffset // not recursive, false warning
}
}
}
Dieser Artikel können Ihnen helfen http://nshipster.com/swift-objc-runtime/ –
Und wenn Sie wollen, dass die nach unten dem Kaninchen-Loch jagen : http://stackoverflow.com/questions/25651081/method-swizzling-in-swift?rq=1 – BaseZen
@VictorSigler dieser Artikel deckt nicht diesen speziellen Fall mit Property Setter. – brigadir