我终于从 Objective-C 转向了 Swift。我正在为我的客户创建一个 View 布局系统,使他们的应用程序在布局上更加灵活,而不使用自动布局,因为他们想远程设计他们的屏幕,而自动布局对他们来说太复杂了。我尝试使用 structs 和 protocols 来做到这一点,但我发现它很笨拙,所以我怀疑我没有以正确的方式思考它。
对于类,结构如下:
class ViewModel {
var frame: CGRect = .zero
}
class ViewGroupModel: ViewModel {
var weight: Int = 1
var children:[ViewModel] = [ViewModel]()
}
class HorizontalViewGroupModel: ViewGroupModel {
}
class VerticalViewGroupModel: ViewGroupModel {
}
我试图通过定义一个 ViewModel 协议(protocol)和一个 ViewGroupModel 协议(protocol)来使用协议(protocol)来处理它,但我发现它创建了很多重复(属性)。有更好的方法吗?在这种情况下使用类会被认为是一种好的做法吗?
编辑:如果不使用类会更好,我正在寻找一个答案,在 structs 和 protocols 方面给我一个具体的解决方案。
最佳答案
如果问题仅仅是如何实现协议(protocol)的属性,我不一定会让那影响我在 struct 与 class 之间的选择。如果您的 struct 类型必须实现各种属性,您有两个基本选择:
如果您谈论的是几个属性,只需在符合该协议(protocol)的 struct 类型中实现这几个属性即可。我们一直这样做。例如。在定义符合 MKAnnotation 的自定义类型时,我们只需实现三个必需的属性。
当然,如果我们讨论的是一组更大的属性,这会变得乏味,但编译器会在整个过程中牵着我们的手,确保我们不会遗漏任何东西。所以挑战相当小。
虽然我不喜欢这种方法,https://stackoverflow.com/a/38885813/1271826表明您可以将共享属性实现为一个组件,其中您有 struct 来包装所有这些属性,然后在扩展中为您的协议(protocol)实现默认计算属性:
enum SubviewArrangement {
case none
case horizontal
case vertical
case flow
}
struct ViewComponent {
var frame = CGRect.zero
var weight = 1
var subviews = [ViewModel]()
var subviewArrangement = SubviewArrangement.none
}
protocol HasViewComponent {
var viewComponent: ViewComponent { get set }
}
protocol ViewModel: HasViewComponent { }
extension ViewModel {
var frame: CGRect {
get { return viewComponent.frame }
set { viewComponent.frame = newValue }
}
var weight: Int {
get { return viewComponent.weight }
set { viewComponent.weight = newValue }
}
var subviews: [ViewModel] {
get { return viewComponent.subviews }
set { viewComponent.subviews = newValue }
}
var subviewArrangement: SubviewArrangement {
get { return viewComponent.subviewArrangement }
set { viewComponent.subviewArrangement = newValue }
}
}
在那里,您可以创建一个符合 ViewModel 的实例,如下所示:
struct LabelModel: ViewModel {
var viewComponent = ViewComponent()
}
var label = LabelModel()
label.weight = 2
print(label.weight)
我必须承认,这不是最优雅的方法。 (我什至不愿展示它。)但它避免了必须在符合 ViewModel 的类型中单独实现所有这些属性。
所以,让我们把属性问题放在一边。真正的问题是您应该使用值类型 (struct) 还是引用类型 (class)。我认为在 Protocol-Oriented Programming in Swift 接近尾声 (@42:15) 时考虑 Apple 关于值(value)与引用语义的讨论很有启发性。视频。他们触及了您实际上可能仍想使用类的那些情况。例如,他们建议您可能希望在“复制或比较实例没有意义”时使用引用类型。他们建议在处理“Window”实例时可以应用此规则。这同样适用于此。
最重要的是,在我看来,使用值类型来表示 View 层次结构并没有多大好处, View 层次结构是引用类型对象的集合。这只会让人更加困惑。我会坚持使用 class 类型,因为它会准确地反射(reflect)它所代表的 View 层次结构。
不要误会我的意思:我们已经习惯使用引用类型,所以我认为挑战我们先入为主的观念并仔细研究值类型是否可以更好地解决这种情况总是好的。不过,在这种情况下,我根本不会担心它,只是坚持使用反射(reflect)您正在建模的那些对象的层次结构的 class 层次结构。
话虽如此,您在问题中提出的类层次结构也感觉不太对。感觉很奇怪,你实际上可以实例化一个 ViewModel,你以后不能添加 subview (而所有 UIView 对象都有 subview 属性)。此外,您的水平和垂直组类型也感觉不正确。例如,它是否应该是具有某些“轴”属性的单一类型,如 UIStackView 或其他一些“排列”属性,以扩大捕获 UICollectionView 布局的概念?。正如您将在我上面的 ViewComponent 示例中看到的那样,考虑到这两个注意事项,我将其扁平化了一点,但是您可以按照自己认为合适的方式进行操作。
关于ios - Swift:构建还是不构建,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45376913/
这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下
我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的
在编写Ruby(客户端脚本)时,我看到了三种构建更长字符串的方法,包括行尾,所有这些对我来说“闻起来”有点难看。有没有更干净、更好的方法?变量递增。ifrender_quote?quote="NowthatthereistheTec-9,acrappyspraygunfromSouthMiami."quote+="ThisgunisadvertisedasthemostpopularguninAmericancrime.Doyoubelievethatshit?"quote+="Itactuallysaysthatinthelittlebookthatcomeswithit:themo
1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里
我正在尝试在配备ARMv7处理器的SynologyDS215j上安装ruby2.2.4或2.3.0。我用了optware-ng安装gcc、make、openssl、openssl-dev和zlib。我根据README中的说明安装了rbenv(版本1.0.0-19-g29b4da7)和ruby-build插件。.这些是随optware-ng安装的软件包及其版本binutils-2.25.1-1gcc-5.3.0-6gconv-modules-2.21-3glibc-opt-2.21-4libc-dev-2.21-1libgmp-6.0.0a-1libmpc-1.0.2-1libm
print"Enteryourpassword:"pass=STDIN.noecho(&:gets)puts"Yourpasswordis#{pass}!"输出:Enteryourpassword:input.rb:2:in`':undefinedmethod`noecho'for#>(NoMethodError) 最佳答案 一开始require'io/console'后来的Ruby1.9.3 关于ruby-为什么不能使用类IO的实例方法noecho?,我们在StackOverflow上
我在思考流量控制的最佳实践。我应该走哪条路?1)不要检查任何东西并让程序失败(更清晰的代码,自然的错误消息):defself.fetch(feed_id)feed=Feed.find(feed_id)feed.fetchend2)通过返回nil静默失败(但是,“CleanCode”说,你永远不应该返回null):defself.fetch(feed_id)returnunlessfeed_idfeed=Feed.find(feed_id)returnunlessfeedfeed.fetchend3)抛出异常(因为不按id查找feed是异常的):defself.fetch(feed_id
eruby和erb有什么区别?哪些考虑因素会促使我选择其中之一?我的应用程序正在为网络设备(路由器、负载平衡器、防火墙等)生成配置文件。我的计划是对配置文件进行模板化,在源文件中使用嵌入式ruby(通过eruby或erb)来执行诸如迭代生成路由器的所有接口(interface)配置block之类的操作(这些block都非常相似,仅在标签上有所不同和IP地址)。例如,我可能有这样一个配置模板文件:hostnamesample-routerlogging10.5.16.26当通过嵌入式ruby解释器(erb或eruby)运行时,会产生以下输出:hostnamesample-rout
关闭。这个问题需要更多focused.它目前不接受答案。想改进这个问题吗?更新问题,使其只关注一个问题editingthispost.关闭8年前。Improvethisquestion我们有以下(以及更多)系统,我们将数据从一个应用推送/拉取到另一个:托管CRM(InsideSales.com)Asterisk电话系统(内部)横幅广告系统(openx,我们托管)潜在客户生成系统(自行开发)电子商务商店(spree,我们托管)工作板(本土)一些工作网站抓取+入站工作提要电子邮件传送系统(如Mailchimp,自主开发)事件管理系统(如eventbrite,自主开发)仪表板系统(大量图表和
在我的mac上安装几个东西时遇到这个问题,我认为这个问题来自将我的豹子升级到雪豹。我认为这个问题也与macports有关。/usr/local/lib/libz.1.dylib,filewasbuiltfori386whichisnotthearchitecturebeinglinked(x86_64)有什么想法吗?更新更具体地说,这发生在安装nokogirigem时日志看起来像:xslt_stylesheet.c:127:warning:passingargument1of‘Nokogiri_wrap_xml_document’withdifferentwidthduetoproto