【问题标题】:Subclassing UIView vs UIScrollView子类化 UIView 与 UIScrollView
【发布时间】:2012-02-24 21:13:51
【问题描述】:

好的,这可能是不可能的,但我有一个类(称为CompositeView),它是UIView 的子类。它使用一些核心图形工作来根据一些选项生成自定义背景。不是一个庞大的班级,但随着我的需求变化/增加/无论如何,一定会增长。我遇到的问题是我在很多不同的地方经常使用这个类。但在某些地方,我需要它成为UIScrollView 的子类,而不是UIView。有趣的是,我可以简单地更改超类,并且一切正常。但我不仅不希望我的所有其他视图都成为UIScrollView,它还会干扰其中一些视图的操作。所以我需要一个类,它有时是UIScrollView 的子类,有时是UIView 的子类。

目前,我已经完全复制了CompositeView 的所有接口/实现,将类名更改为CompositeScrollView,并将其继承更改为UIScrollView。它工作正常,但现在我有两组代码做完全相同的事情,只是从不同的父类继承。这让他们都保持最新状态很痛苦。

有没有更好的方法来做到这一点?

【问题讨论】:

  • 为什么需要它成为 UIScrollView 或 UIView 的子类(当 UISCrollView 已经是 UIView 的子类时)?需要更多关于您要完成的工作的详细信息。

标签: objective-c subclass


【解决方案1】:

单一继承语言强制您使用委托。您会将添加的功能分解到一个单独的类中,您可以为派生类实例化该类,然后将派生类中的转发填充程序写入实例。好痛。

Objective C 的协议可以描述添加的函数(任何未被覆盖的垫片),然后如果您没有编写垫片,编译器会出错......您仍然必须手动完成。

Objective C 还具有允许您扩展现有类的类别,但这些类别不能共享(您必须单独扩展每个类),因此它并没有真正的帮助。

【讨论】:

  • 是的,实际上这可能是迄今为止最好的主意。复合视图实际上使用核心图形来创建它添加到共享缓存(由具有相同选项的所有视图共享)的 UIImage。视图所做的只是在 drawInRect 中绘制图像。我可能可以卸载很多。我会让对象创建更复杂一点,但可能是值得的。
  • UIView 上的类别实际上可以工作,但它们不允许属性,因此除非您添加的功能没有添加新状态(只是行为),否则您无法使用它们。 +1!
  • 是的,我不认为他想添加到所有视图中,因此正在考虑使用类别作为混合应用到他从 UIView 和 UIScrollView 派生的类。但是由于类别本身不能应用于多个类,所以这无济于事(甚至在查看添加 ivar 的东西之前)。
  • @smparkes 每个类别在这种情况下都不起作用,因为是的,有很多状态需要保存。我认识到,鉴于我提出的问题的上下文,如果大部分核心图形工作是在 DrawRect 中完成的,您的回答可能不起作用。但实际上,CG 工作是在一个 UIGrapicsImageContext 中完成的,它很容易导出。所以你的解决方案在我的情况下确实有效。此外,转发方法非常简单。请参阅我的问题:stackoverflow.com/questions/9415694/…
【解决方案2】:

当然,最好的办法是不可能的:让UIScrollView 继承自您的UIView 子类。

@smparkes 的回答很好,但有时委派不会做你想做的事,或者太不方便了。在这种情况下,很可能是后者。

考虑在任何地方使用 UIScrollView,但会破坏您不需要的功能。 UIScrollView 实例的行为与 UIView 实例完全相同——嗯,它们是 @ 987654326@ 个实例——所以你可以解决这个简单的问题,“干扰其中一些实例的运行”,然后继续。关闭缩放、关闭滚动等...

不幸的是,这就是单继承语言的现实。无论您做什么,都不要尝试通过更改isa 之类的方法来解决此问题。如果你有任何成功,它不会持久。 Objective-C 只是稍微动态的,不允许普通程序员认真使用这种东西。

【讨论】:

  • FWIW,我可能也会先尝试禁用所有 UIScrollView 的东西。也就是说,UIScrollViews 是野兽,我可能还认为值得额外的 shim 代码来避免它们,除非我真的需要它们。
  • 我曾考虑禁用 UIScrollView,但事实是,UIScrollView 增加了一些我不想要的权重。我最初编写复合视图是为了在较慢的设备上加速一些动画(它确实这样做了)。使用 UIScrollView 可以解决一点问题(不多,但足够了)。
  • @AaronHayman 凭经验使用 UIScrollView 会失败吗?我同意它看起来很重,但真的吗?
  • @Yar 有点,就像我说的,没什么大不了的。但是我一次可以在屏幕上查看多达 200 个视图(iPad ......也许在 iPhone 上 50 个)。它加起来。使它“更糟”的是用户可以放置任意数量的位置。因此,保持它的重量尽可能轻是有意义的。
  • @AaronHayman 我只是说如果您还没有尝试 1000 或 2000,也许您会感到惊讶。或者可能不是;)
【解决方案3】:

好的,也许这完全是疯狂的,但是 ISA 切换选项吗?

object->isa = [SomeClass class];

见:Objective-C: How to change the class of an object at runtime?

如果您实现了一个知道如何将其 ISA 指针切换到 UIScrollView 子类的 UIView 子类,那么您只需处理一个类,甚至可以在运行时动态决定您想要哪些视图。

请注意,这纯粹是理论上的。我从来没有在实时代码中使用过 ISA 切换,我个人认为这不是一个好的设计:P

编辑: 但同样,它并没有减少任何冗余...... 我对该主题进行了更多阅读,但它似乎并不值得推荐(旧对象的内存结构保持不变,例如)

【讨论】:

  • Isa swizzling 仅在两个类具有相同的内存布局时才有效。 UIView 与 UIScrollView 不太可能。
  • 他们不会...UIScrollViews 对内存的影响更大。
【解决方案4】:

是的,您可能对使用 Class-cluster 感兴趣。这可以生成对象,比如说 MyCompositeClass,它将生成 MyCompositeScrollClass 对象或 MyCompositeViewClass 对象。

Apple 经常在 NSArray 中使用类集群,当您使用它时,您会在后台操作不同的对象。区别在于数组的大小,例如对于一些小数组 NSArray 将实例化一个专门用于小数据结构的类等......

这具有性能良好的优点,并且通过类集群的概念完全向用户隐藏了复杂性。

我邀请您阅读一些有关此的文档,这可能更容易理解。 https://developer.apple.com/library/mac/#documentation/General/Conceptual/DevPedia-CocoaCore/ClassCluster.html

希望这会有所帮助:)

【讨论】:

  • 我不知道是谁放了-1...但是如果他或她能详细说明一下,我很想知道我的错误在哪里..
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-08
  • 1970-01-01
  • 1970-01-01
  • 2012-01-31
  • 1970-01-01
相关资源
最近更新 更多