【问题标题】:Category is implementing a method which also be implemented in primary class : `viewWillAppear:`类别正在实现一个方法,该方法也可以在主类中实现:`viewWillAppear:`
【发布时间】:2014-05-16 09:48:20
【问题描述】:

我正在尝试对 UIViewController 进行分类以覆盖 viewWillAppear:。但收到此警告。

Category 正在实现一个方法,该方法也可以在 primary 中实现 类

@implementation UIViewController (ViewWillAppearCategory)

-(void)viewWillAppear:(BOOL)animated
{
    //.........
}

@end

我想在查看期间做一些事情出现在所有屏幕上,所以我不想在所有屏幕上触摸。这就是为什么,选择类别。

我可以在子类中实现一些方法,我可以在所有 VC(所有屏幕)中调用该方法。但我不想要这个。它会自动调用在视图中会出现调用。这是这样做的任何想法还是在上面犯了任何错误?

注意:此代码将仅出现在开发阶段用于某些测试目的。所以我会在使用应用商店时删除此代码。所以在移除过程中应该是更容易的任务,即我不会触摸所有屏幕。我不会在提交到应用商店期间保留此代码。

【问题讨论】:

  • 你不应该使用类别来覆盖方法
  • 除此之外还有什么想法吗?
  • 当然是子类化
  • 没有。它也修改所有屏幕。我正在实现一个仅在开发阶段可用的视图。当进行分发时,我应该从所有 VC 中删除此屏幕。我不能子类化。
  • 按照我下面的建议,然后在需要发布的时候,您只需修复一个父类以消除任何地方的行为。

标签: ios objective-c oop objective-c-category


【解决方案1】:

在这种情况下,您必须尝试 Method Swizzling,这是一个非常好的形成概念,它允许您更改现有选择器的实现。

更多详情和代码,请访问下面的链接。

http://nshipster.com/method-swizzling/

【讨论】:

  • 它是否调用了两个实现(class_addMethod(...))?或者只是替换第一个方法并只调用我们自己的方法?我想调用类别中可用的方法,并调用视图控制器中的默认实现。
  • 虽然这行得通,但我认为在所提出的案例中这是一个糟糕的想法,因为它对可能已经完成的大量测试的有效性提出了质疑。咬紧牙关创建 UIViewController 的子类并将许多其他类更改为该子类的子类似乎非常值得付出适度的努力,恕我直言。
  • 它远远优于解决此类问题的任何其他解决方案。我希望每个人都能学会更多地给出这样的精彩答案,包括我在内。多亏了你,我今天学到了很棒的东西。
  • @Mani 那么类别方法和默认实现将被调用?
  • @ShabarinathPabba 是的。基于此,我实现了该库。如果您想要样品,请查看此链接。 github.com/npctech/Tattle-UI-iOS/blob/master/TattleControl/…
【解决方案2】:

类别用于添加新方法,而不是覆盖现有方法。可以使用以下代码创建 UIViewController 的子类,例如 MyUIViewController:

-(void) viewWillAppear:(BOOL) animated {
    // do your "category" stuff
}

然后使用以下代码创建 MyUIViewController 的所有其他 UIViewControllers 子类:

-(void) viewWillAppear:(BOOL) animated {
    [super viewWillAppear:animated];
    // rest of code for this class
}

【讨论】:

  • 完整阅读我的问题,如果我按照上面的方法进行,我应该在所有屏幕上编码。我不想那样做。
  • 我读了你的问题。你不能在不接触代码的情况下一次改变所有视图控制器的行为。上面的方法是最安全,侵入性最小的。
  • @Mani 你错了。如果您创建一个类别,那么您会在所有视图控制器上获得此行为。通过子类化,您将只在一个屏幕上获得所需的行为
  • 可以,但不安全。只要他按照我的建议使所有这些屏幕成为新父类的子类,子类化就可以影响他的所有屏幕。见stackoverflow.com/questions/5272451/…
  • @AndreyChernukha 是的,你是对的。一旦我使用了那个子类,我就会加入所有的 VC,如果我不想要,我必须重新处理它。我说的对吗?
【解决方案3】:

我理解您为什么想要一个简单的解决方案来测试所有屏幕上的内容并轻松删除它的原因,但是:

  • 您不能在类别中调用super,根据类及其特定实现,不调用[super viewWillAppear:] 可能会产生意外结果。
  • Swizzling 方法是一种 hack,当您将其从最终版本中删除时,您的测试版本将变得毫无用处,因为它的行为可能非常不同。

另一方面,创建一个 UIViewController 超类并在其中正确覆盖 viewWillAppear: 并不复杂:

  • 代码将只属于一个类。无需为每个“屏幕”重复/维护代码。
  • 您只需更改其他控制器的超类和 Nib 或 Storyboard 引用一次。
  • 您可以保留超类以进行测试和发布,其行为将相似。
  • 在超类中可以做的事情比在类别中要多得多。

最终,了解您想要实现的目标会很有趣。您可能可以通过实现 UINavigationControllerDelegate 并跟踪控制器被推送和弹出来实现类似的事情。


至于viewWillAppeardocumentation

在接收者的视图即将添加之前调用该方法 到视图层次结构并在配置任何动画之前 显示视图。您可以覆盖此方法以执行自定义任务 与显示视图相关联。例如,您可以使用这个 将状态栏的方向或样式更改为的方法 与正在呈现的视图的方向或样式相协调。 如果你重写了这个方法,你必须在你的实现中调用 super。

同样,你不能从一个类别中做到这一点。

【讨论】:

  • 你在哪里找到我的代码[super viewWillAppear:]?您是否完整阅读了我的问题以及我在这篇文章中的问题?你怎么知道The code will belong only to a single class?如果我使用UIViewController, UINavigationController, UITabbarController,UIPageViewController?那我一起去吗?不是吗?无论如何,至少,我需要在所有文件中导入该类,并在所有 VC `UIViewController: BaseController" 中执行此操作?这对我来说是个坏主意。
  • 您的代码应该调用[super viewWillAppear:],但您不能在一个类别中。虽然如果您有 UIViewControllers 以外的其他东西,那么您需要多个超类是正确的,但了解您真正想要实现的目标会有所帮助。
  • 我需要[super viewWillAppear:] ,一旦我在屏幕上写了代码viewWillAppear?我可以在我的屏幕上留下viewWillAppear。即使我离开,category 方法也会调用。这就是我需要的。哦,伙计,我想你没有理解我的问题。只需阅读 swizzling 概念,您就会明白我的问题。
【解决方案4】:

正如您所说,代码将仅在调试模式下执行。那你为什么要担心警告让警告来你继续你的工作当涉及到释放你删除你的类别。

如果您甚至不需要看到警告,您就可以使用相同的答案,例如

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"

-(void)viewWillAppear:(BOOL)animated
{
    NSLog(@"I get callback here too");
}

#pragma clang diagnostic pop

但我会说要进行子类化,因为在 XCode 工具中删除现有类也不是那么难。

【讨论】:

    【解决方案5】:

    您想要实现的目标违背了类别的目的。但是,除了继承 UIViewController 之外还有另一种方法,但您必须为每个控制器触摸 viewWillAppear 方法。

    //UIViewController+CustomCategory.h
    @interface UIViewConctroller (CustomCategory)
    
    - (void)performCustomization;
    
    @end
    
    //UIViewController+CustomCategory.m
    @implementation UIViewController (CustomCategory)
    
    - (void)performCustomization {
        // Do custom stuff…
    }
    
    @end
    

    然后在每个控制器中

    //MYViewController.m
    #import "UIViewController+CustomCategory.h"
    
    - (void)viewWillAppear:(BOOL)animated {
        [super viewWillAppear:animated];
        [self performCustomization];
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-03-14
      • 2014-08-15
      • 1970-01-01
      • 2012-04-29
      • 2016-06-04
      • 2013-05-10
      • 1970-01-01
      • 2021-09-13
      相关资源
      最近更新 更多