【问题标题】:Implement UIView extension function using Generic in objective C在 Objective C 中使用 Generic 实现 UIView 扩展功能
【发布时间】:2020-12-05 03:44:49
【问题描述】:

我正在尝试将一些 swift 函数转换为 Objective-c

extension UIView {
    class func fromNib<T: UIView>() -> T {
        return Bundle(for: T.self).loadNibNamed(String(describing: T.self), owner: nil, options: nil)![0] as! T
    }
}

这是来自Load a UIView from nib in Swift的代码

我以为.h文件可以这样写

@interface UIView <T: UIView *> (MyCommon)
+ (T) loadFromNib;
@end

我遇到了这样的错误

非参数化类 'UIView' 的类别不能有类型参数

这是否意味着在 Objective C 中使用 Generic 实现 UIView 扩展功能是不可能的?

【问题讨论】:

  • 认为您正在寻找一个类别,看看这个answer
  • @skaak 谢谢你的推荐。我帮了很多忙。除此之外,我想限制像 &lt;T: UIView&gt; 这样的泛型类型。但我只能找到通用 T 。你能给我更多的建议吗?
  • 好的,在那个答案中,代码的开头是这样的+ (id)loadFromNib:(NSString *)name classToLoad:(Class)classToLoad {,只需将其替换为+ (UIView*)loadFromNib:(NSString *)name classToLoad:(Class)classToLoad { ...我认为这里的泛型是矫枉过正的。 id 表示任何东西,更改为UIView 表示它必须是 UIView 或子类。

标签: objective-c swift generics uiview extension-methods


【解决方案1】:

我提到的那个答案使用NSObject 类别。也许将其更改为UIView 类别,如下所示。

编辑

既然您想要MyView,请查看下面的更改并尝试一下。请注意,在 Objective-C 中,您会收到警告,而 Swift 会为此类代码拍打您的手腕...

@class MyView;

@interface UIView (loadFromNib)

@end

@implementation UIView (LoadFromNib)

// This only returns UIView or subclass ... or nil
+ ( UIView * )loadFromNib:( NSString * ) name
{
    // For the adventurous
    return [[NSBundle mainBundle] loadNibNamed:name owner:self options:nil].firstObject;

    // For the cautious
    for ( NSObject * i in [[NSBundle mainBundle] loadNibNamed:name owner:self options:nil] )
    {
        if ( [i isKindOfClass:UIView.class] )
        {
            return i;
        }
    }

    // For the unsuccessful
    return nil;
}

// This returns MyView
+ ( MyView * ) loadMyViewFromNib:( NSString * ) name
{
    return [UIView loadFromNib:name];
}

@end

【讨论】:

  • 好吧,你会看到我在代码中提供了两种返回 UIView 的方法。第一个几乎适用于所有情况,并且我相信被广泛使用,但有时对于某些 NIB 会失败,而第二个更安全。
  • 我将其更改为UIView 类别并使其返回UIView。像这样创建 UIView 是成功的。 let myView: MyView = UIView.loadFromNib(from: MyView.self) as! MyView 但我不满意我总是需要像as! MyView 那样进行类型转换@ 不能通过引用我传递的参数来推断我的类型,这样我就不需要进行类型转换了吗?
  • 我认为我们的 cmets 越界了!在 Objective-C 中,您不需要进行类型转换,在 Swift 方面,您受到更加严格的约束。我对 Swift 不是很流利,对此我无能为力——事实上,这也是我对 Swift 不太流利的原因之一。我认为感叹号是因为该函数可能返回 nil,而您必须帮助 Swift 为其赋予意义。
  • 我真的没有什么 Swift 技能,但我认为你可以摆脱这个 let myView: MyView = UIView.loadFromNib(from: MyView.self)! - 或者你可以声明函数返回 NONNULL 但这不是你想要的。
  • 为什么我需要添加感叹号是当我调用那个函数时,它只知道返回类型是UIView,所以我需要断言它是类型MyView。如果 Objective-C 不需要类型转换,我如何根据我传递的类型返回特定类型?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-29
  • 2017-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多