问题标签 [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 投票
1 回答
276 浏览

ios - 在 Swift 中使用协议构建可组合对象

我正在尝试创建一种在 Swift 中构建可比较对象的方法。我觉得我几乎已经有了我所拥有的,但它仍然不是 100% 正确的。

我的目标是拥有一个FlowController可以创建我们的对象,UIViewControllers然后为他们提供他们需要的任何依赖项。

我还想做的是使这项工作尽可能松散。

我在这里有一个小例子,但并不理想。我会解释...

这里有两个可以用作组件的对象......WalletUser

然后我们定义一个Component枚举,其中包含每个案例......

...以及定义requiresComponents返回数组的方法的协议Components

这就是问题出现的地方。为了让“工厂对象”将组件放入Composable对象中,我们还需要在协议中定义userwallet属性。

为了使这些属性“可选”(不是可选的),我定义了Composable协议的扩展,将这些变量定义为 nil。

现在我声明我要创建的类Composable。如您所见,它需要User组件并声明变量。

现在FlowController将创建这些并将组件添加到它们。您可以在这里看到我必须获取对象,创建它的本地var版本,然后返回更新的对象。我认为这是因为它不知道将符合协议的对象的类型,因此不能改变参数。

我在这里创建对象。

在这里我添加了组件。在生产中,这将在FlowController.

如您所见,它在这里工作。用户对象被添加。

但是,您也可以看到。因为我已经在协议中声明了变量,所以该composable对象还具有对wallet组件的引用(尽管它总是为零)。

我觉得我已经完成了 95% 的工作,但我想做的是改进属性的声明方式。我想要的是最后一行......composable.wallet成为编译错误。

我可以通过将属性声明移出协议来做到这一点,但是我遇到了无法将属性添加到任何符合Composable协议的对象的问题。

令人敬畏的是工厂对象能够在不依赖声明的情况下添加属性。或者甚至有某种守卫说“如果这个对象有一个属性调用用户,那么将用户组件添加到它”。或类似的东西。

如果有人知道我怎样才能让这剩下的 5% 工作,那就太棒了。就像我说的,这行得通,只是不是以理想的方式。

感谢:D

哈基编辑

嗯......作为一个快速俗气,可怕的,“没有人应该这样做”的编辑。我已将我的协议扩展更改为这样......

现在,如果我尝试访问尚未定义的变量,至少程序会崩溃。但它仍然不理想。

阅读丹尼尔的博客后编辑

好吧,我想我已经做到了我想要的。只是不确定它是否完全是 Swifty。虽然,我也觉得有可能。寻求第二意见:)

所以,我的组件和协议变成了这个……

现在工厂方法已经改变了......

这让我可以做到这一点......

0 投票
1 回答
126 浏览

ios - Swift 面向协议的扩展

试图了解 Swift 中面向协议的编程以及扩展如何工作以及它可以提供什么级别的可扩展性。

有以下我在 Playgrounds 中运行的代码片段

我打印的是:

无论如何,我可以保证所有扩展都运行。

理想情况下,我想获得以下输出。

我确实理解 Swift 会根据其类型选择最强匹配,事实上,如果我不提供 ProtocolA 与 ProtocolB 和 ProtocolC 匹配的实现,我会得到一个编译时错误。无论如何我可以解决这个问题吗?

谢谢。

0 投票
1 回答
90 浏览

ios - 协议类型的异构混合,包括通用协议

尝试创建一个ParentProtocol包含 ChildProtocol的类型数组Child_With_Value_Protocol。有没有可能的方法来创建一个循环遍历异构数组并返回只是 type 的值的函数Child_With_Value_Protocol

这可能需要架构更改。对所有解决方案开放。

尝试失败的解决方案 #1

protocol 'Child_With_Value_Protocol' can only be used as a generic constraint because it has Self or associated type requirements由于编译器在转换为 just 时不知道类型,因此失败并出现错误Child_With_Value_Protocol,这会导致下一个失败的解决方案。

尝试失败的解决方案 #2

如果数组是 just 的同构数组,则Child_With_Value_Protocol可以使用类型擦除来检索值。

由于结构AnyValue没有用于ParentProtocol.

尝试失败的解决方案#3

与其他解决方案不同,此解决方案实际上可以编译。这个解决方案的问题在于数组erased只能保存类型擦除版本的值Child_With_Value_Protocol。目标是让数组同时保存 Child_With_Value_Protocol的类型ChildProtocol

尝试失败的解决方案#4

修改类型擦除结构以包含初始化程序ParentProtocol仍然会创建一个可编译的解决方案,但是该结构将仅使用不太具体的 init,而不是更具体的 init。

0 投票
4 回答
48801 浏览

ios - Swift - 协议扩展 - 属性默认值

假设我有以下协议:

我有以下结构:

如您所见,我必须“符合”结构 A 和结构 B 中的 Identifiable 协议。但是想象一下,如果我还有 N 个需要符合该协议的结构......我不想“复制/粘贴” ' 一致性 (var id: Int, var name: String)

所以我创建了一个协议扩展

现在有了这个扩展,我可以创建一个符合 Identifiable 协议的结构,而无需实现这两个属性:

现在的问题是我无法为 id 属性或 name 属性设置值:

这是因为在 Identifiable 协议中,id 和 name 只能获取。现在,如果我将 id 和 name 属性更改为{get set}我会收到以下错误:

类型“C”不符合协议“可识别”

发生此错误是因为我没有在协议扩展中实现设置器......所以我更改了协议扩展:

现在错误消失了,但是如果我为 id 或 name 设置一个新值,它将获得默认值(getter)。当然,setter 是空的

我的问题是: 我必须在 setter 中放入什么代码?因为如果我添加self.id = newValue它会崩溃(递归)。

提前致谢。

0 投票
1 回答
167 浏览

ios - 面向协议编程,隐式调用扩展方法

我第一次破解 POP。在这种情况下,我想装饰一些 UIViewControllers,以便它们自动引发“页面查看”分析事件。

所以我创建了一个协议,以及该协议的扩展:

如果我用ReportPageViewedEvent这样的方式装饰 UIViewController,这可以按我的意愿工作:

除非我设置了我想要的“pageName”,否则我会收到编译器错误。

我陷入困境的地方是在哪里以及如何调用实际reportPageViewed()方法。我真的希望它被调用,viewDidLoad这意味着我要么必须修改每个使用它的控制器中的每个“viewDidLoad”,要么子类化并调用超类中的方法,这首先违背了使用 POP 的意义。

有没有一个很好的方法来实现这一点。我在任何教程/博客中都找不到这样的例子。

0 投票
1 回答
39 浏览

swift - 为什么我的默认属性值仍然显示为 Init() 中的参数?

我有一个描述需要测试的海水参数的协议:

我有一个结构,Calcium符合Parameter

既然 的nameunit参数Calcium都有默认值,那我为什么要在init方法中提供呢?我不应该只需要为 提供一个值value吗?

我正在尝试了解面向协议的编程,并且非常感谢这里的一些指导。

在此处输入图像描述

0 投票
1 回答
1234 浏览

struct - 有没有办法隐藏 Swift 结构的默认初始化程序?

我有一个名为的协议Parameter

我还有 16 个结构符合Parameter

如您所见,所有结构都实现了相同的初始化程序。在初始化程序中,我为Parameter协议所需的三个参数中的两个提供了默认值,这给了我以下初始化程序:

我还得到了结构创建的默认初始化程序:

当我创建结构的实例时,两个初始化器都出现在 Xcode 的代码完成弹出窗口中。但是,我不希望nameandunit参数能够与初始化程序中提供的默认值不同。我还尝试为在结构内部但在协议所需的初始化程序之外声明它们的name和属性分配默认值。unitParameter

name有没有办法通过为和unit参数提供默认值来初始化结构,只value需要提供参数,而不在 Xcode 的代码完成弹出窗口中显示默认初始化程序?

我对让两个初始化程序都出现在 Xcode 的代码完成弹出窗口中的唯一担心是,我不希望其他人创建结构并提供除Parameter协议所需的初始化程序中提供的值之外的值。

我意识到我可以通过一个类来做到这一点,但我试图通过面向协议的编程和使用结构来让我的想法正确。

0 投票
0 回答
44 浏览

ios - 面向协议的文件获取

最近我看了这个演讲(链接,见网络部分),我决定做一些面向协议编程的练习。所以我想到了这个简单的例子:用于显示文件列表的视图控制器。当然,面向协议的方式,有以下限制:

FilesViewController- 包含表格视图和FilesTableViewAdapter。表视图委托。 FilesTableViewAdapter- 可使用表格视图 & 进行初始化FilesProvider: Gettable,以便在测试中注入FilesProviderMock: GettableFilesTableViewAdapter是表视图的数据源,FilesProvider用于获取文件。

我知道我在概括这段代码方面走得太远了。现在我被困住了,我有这个我无法回答的问题:

  1. 如何以面向协议的方式使用与 VC 不同的网络代码(比如Adapter)?
  2. 如何让它在未来易于测试和扩展?
0 投票
2 回答
400 浏览

ios - ios swift 类符合协议

我正在尝试快速学习并希望使用面向协议的编程方法。我想要实现的很简单,但我找不到任何方法。

假设我有 Outlet,它是文本字段。我希望该文本字段符合 ValidatesName 协议之类的协议。有什么办法吗?我不想创建子类 UITextField 并符合协议的新类。我想用于这个特定的属性。

谢谢

0 投票
2 回答
116 浏览

swift - 面向协议的编程扩展变量初始化两次

这是情况。我有一个协议,以及它的扩展。

我制作了一个 ViewController 来符合这个协议,然后我将这个自定义的“aView”添加到我的 ViewController 的视图中。

我运行它。在我的控制台日志中,它打印了两次 init,我试图在我的自定义“aView”中做某事,但它失败了。(我在上面粘贴的代码进行了简化,以便很容易地表达我的意图)

任何人都可以解释原因或对其进行修复,我将不胜感激。