问题标签 [protocol-oriented]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
2 回答
149 浏览

ios - 通过扩展向协议添加功能的原因是什么,为什么不将其放在协议本身的定义中?

我一直想知道为什么当我看到协议示例时,人们倾向于通过扩展添加大部分功能。像这样:

扩展背后的意义是什么?为什么不将它包含在初始协议定义中?

0 投票
1 回答
552 浏览

ios - 为重写的 UIViewController 方法提供默认实现,但前提是控制器符合协议

在我的应用程序中,每当某个控制器中有 UITableView 时,我都必须编写大量样板代码。为了消除它,我创建了一个BaseTableViewController来实现一些重复使用的UITableDataSource操作,例如tableView(_:numberOfRowsInSection:)tableView(_:cellForRowAt:)。在tableView(_:numberOfRowsInSection:)中,我的 BaseTableViewController 从另一个方法(我们称之为它rowCount(inSection:))检索一个部分中的实际行数并使用它执行一些计算,然后将结果返回给委托调用者。每个继承 BaseTableViewController 的类都必须覆盖该rowCount(inSection:)方法并在给定部分中返回其正确的行数(BaseTableViewController 本身在其默认实现中返回 0)。

现在,我的一些表视图控制器支持显示记录的分页 - 当用户将表视图滚动到最后一行时,将从网络中检索下一批行。为了让事情更加面向协议,我为可分页控制器创建了一个协议:

如果控制器是Pageable,则rowCount(inSection:)方法总是如下所示:

这很乏味,因为每个也是 Pageable 的 BaseTableViewController 后代都必须有这个精确的实现,这违反了 DRY。

我无法在 的协议扩展中添加默认实现Pageable,因为控制器已经从 BaseTableViewController 继承了自己的实现。

我想出了一个解决方案,但我不喜欢它:我可以创建一个 PageableTableViewController(BaseTableViewController 的一个子类),它提供它自己的重写实现rowCount(inSection:),但这不是非常面向协议的。我还尝试将rowCount(inSection:)方法移至协议,但如果我使 BaseTableViewController 的所有后代都符合具有协议扩展的协议,则扩展Pageable以实现该方法将不起作用。

我将如何创建一种机制,其中的所有子类BaseTableViewController都能够覆盖该rowCount(inSection:)方法,但是当它们是时Pageable,它们共享它的默认实现,该实现(可能)放置在 Pageable 协议扩展中?

0 投票
1 回答
535 浏览

swift - 为什么不应该直接扩展 UIView 或 UIViewController?

我看到了这个问题,代码如下:

我想知道为什么我们不只是直接扩展UIView?或者在类似的情况下扩展UIViewController为什么用where Self:

  • 是不是为了增加我们的意图,当其他开发人员来时,他们会看到,嘿,这个类符合 Flashable、Dimmable 等?
  • 我们的 UIView 还会有单独的有意义的扩展吗?而不是 UIView 或 UIViewController 的不同未命名扩展?
  • 是否有任何针对 POP 的特定 Apple 指南?我见过有开发人员这样做,但不知道为什么......
0 投票
3 回答
402 浏览

ios - 如何使用面向协议的编程来改进我的 Swift 代码?

我有一个以这种格式构建的相当大的项目:

Numbers有很多方法printMe(),我希望我的所有子类的任何实例都能够调用。

Numbers还有一个allIntegers()函数,我希望这些子类的任何实例都能够调用。作为变量,哪个可能更好?但是我不能覆盖子类中的变量。因此,我在每个子类中使用相同的私有变量integers,由allIntegers().

还要注意它自己的实例Numbers永远不应该调用allIntegers(),它应该只在子类上调用。

最后,请注意一些子类包含相同的对象1, 2, 3,然后每个子类都有一些自定义整数。但不是所有的子类。如果我后来决定所有这些子类都需要一个4整数,我必须手动遍历每个类并将 a4打入数组,这显然容易出错。

我已经阅读了面向协议的编程,并且觉得可能有一个解决方案,或者我会很感激任何其他建议和创造性的方法来构建一个更好的项目。

谢谢!

编辑

所有子类都是不同的,因为它们也有自己的功能要执行。我已经更新了代码以反映这一点。

想象一下,一个给定的类 likeOne在整个代码库中被初始化了很多次,并且总是用完全相同的integers. 放:

整个代码库都容易出错。

希望这可以解决我提出的人为示例的一些问题。

解决方案

感谢大家的帮助。这是我想出的解决方案(请假设所有类都有自己独特的方法)。

0 投票
1 回答
309 浏览

ios - Swift 3 面向协议的编程导致随机 SIGBUS 崩溃

我负责一个完整的 Swift 3 应用程序,经常发生的崩溃之一是SIGBUS我完全无法理解的信号:

其背后的逻辑是在滚动视图中重用视图的逻辑,如 Apple 在 WWDC 视频中所述(找不到年份和视频......):

PageView 是一个实现 ReusableView 和 Indexed 的类:

其中 ReusableView 和 Indexed 是以这种方式定义的协议:

ReusableContentView 是管理插入或重用视图的视图。它的实现取决于包含的视图类型:

Witch 由 调用,由委托DocumentViewerViewController.reuseOrInsertPages()触发。scrollviewDidScroll

什么能SIGBUS在这里激起我的信号?func prepareForReuse() {}这是我用来使协议功能可选的默认实现吗?还有其他想法吗?

当然,这次崩溃是完全随机的,我无法重现它。我刚刚从应用程序的 prod 版本收到有关它的崩溃报告。谢谢你的帮助 !

0 投票
1 回答
52 浏览

swift - 如何将单一类型的不同功能暴露给不同的模块?

我正在开发一款适用于 iOS 的小型 2 人纸牌游戏应用程序。目前,我已将此应用程序分为 3 个模块。

  • 用户界面
  • 游戏逻辑
  • 联网

我在网络模块中有两个公共协议:

实际上只有一个具体的实现同时符合这两种协议。让我们说:

UI模块从用户那里接收一个名称并使用它来初始化一个Foo. 然后根据peers属性显示附近的玩家。当用户提交开始新游戏的邀请时,UI模块将此请求转发给ConnectionManagerConnectionManager处理那些肮脏的工作。

对于游戏逻辑模块,它只关心消息传输,但传输依赖于前面的“邀请-响应”步骤,因为我们需要一个目标来与之交换消息。(目标相关概念被封装,所以游戏逻辑只知道有一个东西可以发送消息和接收消息。)

我的想法是:一旦建立了会话,即一旦用 响应邀请trueUI模块就会初始化一个游戏逻辑事物(可能是一个 type 的实例Game)并通过ConnectionManager(虽然UI模块初始化一个 type 的实例Foo,它存储类型为ConnectionManager) 的实例。但问题是,即使它们在内部由单一类型实现,ConnectionManager也与从外部看时无关。MessageTransmission

  • 我可以在任一侧做一个强制案例,但它看起来很棘手。
  • 我可以将这两个协议结合起来,但是UI模块和游戏逻辑模块与多余的接口(具有比需要更多功能的接口)交互。

我应该走哪条路?还是有更好的方法来做到这一点?

ps:Foo只能由UI模块初始化,因为它是唯一知道name. 并且还需要将相同的实例传递给游戏逻辑模块,因为有一些内部状态(目标相关的东西)在之前与UI模块的交互中被修改,并影响到以后与游戏逻辑模块的交互。我想不出另一种方法来做到这一点。

0 投票
1 回答
242 浏览

swift - Swift 面向协议的混合作用域

我有一个面向协议的编程概念问题。假设我正在创建一个协议 Foo,并且我想在协议扩展中使用函数 action() 来扩展 Foo。action() 将始终基本相同,无论谁在实施,所以我不想重复这段代码。action() 中唯一改变的部分是 prop,prop 需要是实例属性。所以我的符合结构应该只需要定义道具,然后动作就会正常工作。这段代码很好,看起来像这样:

但现在问题来了。假设 prop 是我不希望其他类访问的信息。我希望他们只能通过 action() 访问它。在当前的 swift 中,prop 必须至少是内部的,因为协议是内部的,但我需要它是私有的,这样消费类就不会意外修改属性或读取我只希望它们通过 action() 访问的信息. 我可以将 action() 添加到协议中,但是每次结构符合时我都需要重写 action()。

同样的例子也可以扩展到一个函数:

action() 将始终是相同的实现,除了 cusotmAction()。因此,我需要符合标准的类来实现 customAction(),但我不希望任何外部类调用 customAction(),因为它只提供一些只能在 action() 内部使用的特定行为。因此我需要 customAction() 是私有的,但同样,这是不可能的。

所以这是我的问题,这只是面向协议编程的一个细分吗?我如何使用协议来编写这种类型的代码,而不给 prop/customAction() 太多的范围,或者不必一遍又一遍地重写 action() 内部的相同代码?这个例子相当简单,但我面临同样问题的更复杂版本。在 POP 方面是否有不同的方法来看待这个问题,或者我应该寻找一种更面向对象的方法?

0 投票
4 回答
1157 浏览

swift - 采用协议+扩展VS使用类实例的区别

我一直在尝试掌握面向协议的编程,但我不明白以下两种情况之间的区别......

方案 1 我有两个类是UIViewControllers. 这两个类都需要使用一些通用功能,所以我创建了一个协议和一个带有协议默认实现的扩展,然后视图控制器只需要在类行中有协议,它们将自动继承所需的功能。IE...

场景 2 我有两个类是UIViewControllers. 这两个类都需要使用一些通用功能,因此我创建了一个控制器类,并且这两个UIViewController类都使用了控制器类的一个实例。IE...

那么区别是什么呢?在我需要使用该foo()功能的任何地方,我都可以获取Controller(). foo()通过将函数放在协议中然后拥有需要的类,我可以获得什么优势foo()从协议继承

0 投票
3 回答
558 浏览

ios - 如何将协议类型添加为子视图

所以我写了一个简单的协议:

并有一个customView:

然后我目前有:

但我想做的是:

错误我得到:

无法转换类型“PopupMessageType!”的值 到预期的参数类型'UIView'

编辑: 我在 Swift 2.3 上!

0 投票
3 回答
1092 浏览

ios - 默认协议实现导致“不符合协议”错误

我正在尝试将默认实现添加到我的委托方法之一。但是,在添加默认实现并从实现协议的类中删除方法后,我得到了does not conform to protocol错误。它在操场上工作。

我错过了什么?