我想子类化声明如下的UITableViewRowAction类:
class UITableViewRowAction : NSObject, NSCopying {
convenience init(style: UITableViewRowActionStyle, title: String!, handler: (UITableViewRowAction!, NSIndexPath!) -> Void)
var style: UITableViewRowActionStyle { get }
var title: String!
@NSCopying var backgroundColor: UIColor! // default background color is dependent on style
@NSCopying var backgroundEffect: UIVisualEffect?
}
我希望我的子类覆盖此处存在的方便init,并调用super来获得方便性。
以下是我想要做的事情:
public class MySubclass : UITableViewRowAction {
let handler : (UITableViewRowAction!, NSIndexPath!) -> Void
public init(style: UITableViewRowActionStyle, title: String!, handler: (UITableViewRowAction!, NSIndexPath!) -> Void) {
self.handler = handler
super.init(style: style, title: title, handler: handler) // error == Must call a designated initializer of the superclass 'UITableViewRowAction'
}
}
我想这样做是为了将处理程序公开为readonly属性,以便能够对处理程序执行我认为应该执行的操作进行单元测试。
所以我的问题是超级类没有公开传递给init方法的处理程序,并且没有办法在init方法之外设置它。
答案 0 :(得分:2)
我不知道这个答案是否真的与你的答案完全不同,但我在尝试进行单元测试时遇到了类似的问题。这个感觉有点清洁;但这是主观的。您可以使用set_AssociatedObject(和get_AssociatedObject)和一个小的私有ActionTrigger包装类来允许在单元测试中触发操作。
import UIKit
import ObjectiveC
var ActionTriggerHandle: UInt8 = 0
private class ActionTrigger {
private var handler: (UITableViewRowAction!, NSIndexPath!) -> ()
private var action: UITableViewRowAction
private init(action: UITableViewRowAction, handler: (UITableViewRowAction!, NSIndexPath!) -> Void) {
self.handler = handler
self.action = action
}
private func trigger(indexPath: NSIndexPath) {
handler(action, indexPath)
}
}
public extension UITableViewRowAction {
public convenience init(title: String!, style: UITableViewRowActionStyle, exposedHandler: (UITableViewRowAction!, NSIndexPath!) -> Void) {
self.init(style: style, title: title, handler: exposedHandler)
var actionTrigger = ActionTrigger(action: self, handler: exposedHandler)
objc_setAssociatedObject(self, &ActionTriggerHandle, actionTrigger, objc_AssociationPolicy(OBJC_ASSOCIATION_RETAIN_NONATOMIC))
}
public func trigger(indexPath:NSIndexPath) {
if let storedActionTrigger = objc_getAssociatedObject(self, &ActionTriggerHandle) as? ActionTrigger {
storedActionTrigger.trigger(indexPath)
}
}
}
答案 1 :(得分:0)
您无法继承UITableViewRowAction
。将其视为final
类。 (Objective-C没有正式的方式来声明最终的类,但是,非正式地,由于缺少公开声明的初始化程序,这个类在最终中。)
如果查看原始的Obj-C代码,UITableViewRowAction
实例只能使用类方法创建:
+ (instancetype)rowActionWithStyle:(UITableViewRowActionStyle)style
title:(NSString *)title
handler:(void (^)(UITableViewRowAction *action, NSIndexPath *indexPath))handler;
(那个类方法被转换为你在Swift中看到的便利初始化器。)
UITableViewRowAction
未声明任何初始值设定项。此外,它的style
属性是只读的,不能在上面的类方法之外分配。
无法在此类方法之外实例化UITableViewRowAction
,因此无法继承UITableViewRowAction
。
答案 2 :(得分:0)
我发现一个丑陋的走动(代码需要清理)。
四处走动涉及UITableViewRowAction的扩展。 不幸的是,没有存储可以添加到实例中。 因此,添加静态数组以为创建的不同实例添加存储。 但这引发了一个保留周期的问题,这个问题在这里被使用" WeakWrapper"打破了。
我愿意接受更好的建议。
import UIKit
import FoundationAdditions
public extension UITableViewRowAction {
private static var storedHandlers = [handlerStorage]()
var handler : ((UITableViewRowAction!, NSIndexPath!) -> Void)! {
get {
var needCleanUp = false
var result = {(a: UITableViewRowAction!, b: NSIndexPath!) -> Void in }
for storage in UITableViewRowAction.storedHandlers {
if let x = storage.instance.item {
if x === self {
result = storage.handler
break
}
} else {
needCleanUp = true
}
}
if needCleanUp {
// DO the CLEAN UP
}
return result
}
}
public convenience init(style: UITableViewRowActionStyle, title: String!, storedHandler: (UITableViewRowAction!, NSIndexPath!) -> Void) {
self.init(style: style, title: title, handler: storedHandler)
let x = handlerStorage(instance: self, handler: storedHandler)
UITableViewRowAction.storedHandlers.append(x)
}
}
private class handlerStorage {
let instance : WeakWrapper<UITableViewRowAction>
let handler : ((UITableViewRowAction!, NSIndexPath!) -> Void)
init(instance: UITableViewRowAction, handler: (UITableViewRowAction!, NSIndexPath!) -> Void) {
self.instance = WeakWrapper<UITableViewRowAction>(item: instance)
self.handler = handler
}
}