Tag: mvvm

在iOS上使用MVVM进行路由

我在多个项目中使用MVVM已有一段时间了,我非常喜欢它的简单性。 特别是,如果您像许多人一样从MVC移出,则只需要在体系结构中增加一层即可; 查看模型。 如果您发现太多复杂的图层,这确实使事情变得容易。 这是一个好的开始,但是这种简单性并不总是很好。 在MVVM中,将业务逻辑移出视图控制器(VC),然后意识到它仍然很胖。 视图模型(VM)现在具有业务逻辑,但是表示数据(格式)或路由又如何呢? 它们仍然停留在VC中,我们需要将它们移出。 样品流量 假设我们正在实现一个登录屏幕,如下所示。 路线清单: 登录>主屏幕 注册>注册屏幕 忘记密码(?)>忘记密码屏幕 这似乎是一个简单的屏幕,可以使用带有3个脚本的情节提要实现。 但是请相信我,事实并非如此。 例如,您通常会在登录时打开主屏幕。 但是在这种情况下,用户的密码可能已过期,您需要实现重定向以更改密码屏幕。 因此,登录路径变为: 登录>主屏幕或更改密码屏幕 这是情节提要路由失败的地方。 它只是无法应付这种动力。 因此,通常要做的就是让VC处理它: func loginButtonTapped(){ //开始网络请求… //回应后: 如果viewModel.shouldChangePassword { performSegue(id:“ ChangePasswordScreen”,发送者:nil) }其他{ performSegue(id:“ HomeScreen”,发送者:nil) } } 这是路由逻辑,不应在VC中使用。 如果要使用轻量级VC,请在编写if语句之前三思。 他们是决定,不属于那里。 以我的理解,VC仅应具有与视图相关的代码和粘合代码。 永远没有决定。 让我们定义一个路由器协议,并将这些if语句从VC中删除。 我们会需要: 路由ID :字符串标识符,例如segue ID。 上下文 :要从其路由的当前视图控制器。 可选参数 :过渡所需的临时数据。 (点击的行索引等) 协议路由器{ 功能路线( 到routeID:字符串, 来自上下文:UIViewController, […]

Pola Arsitektur MVVM pada迅捷

您尝试过MVVM吗? 嗨,😁! Pastikan Anda Sudah Paham Mengenai TableViewController , Extension和 关闭回调 西伯利亚甜菜 苹果merekomendasikan Pola Arsitektur MVC(模型-视图-控制器) 开发者 dalam iOS / MacOS 开发。 Namun dengan adanya ViewController pada Swift,banyak aplikasi yang dibuat menjadi seperti: Dengan ViewController是MVC(Massive View Controller)。 月经MVVM Dengan menggunakan MVVM,维护部门维护Sebuah aplikasi dapat dibangun secara lebih rapi dan mudah untuk di maintenance。 MVVM(Model-View-ViewModel)记录数据和数据数据ViewController和ViewModel。 Dimana ViewController […]

具有Cocoa键值观察器的简单iOS MVVM

为什么使用MVVM 与使用MVC相比,使用MVVM体系结构构建iOS应用程序具有许多优势。 优势之一是通过将模型和视图分离到单独的MVVM对象来减少Massive View Controller问题,View Controller的职责是仅在ViewModel中 观察与视图相关的值,然后在值更改时更新视图。 这导致View Controller与模型之间的耦合较少 。 单元测试变得更加容易,因为我们可以将ViewModel与View Controller分开进行测试。 iOS应用中MVVM的当前状态 许多使用MVVM架构构建的iOS应用程序都使用第三方库(例如RxSwift和RxCocoa)来观察视图模型对视图控制器的更改。 RxSwift是一个非常强大的库,我们可以将其转换观察器与组合,合并,zip和许多其他强大的转换一起使用。 尽管RxSwift功能非常强大,但有时我们只想使用本机Cocoa Foundation框架构建没有第三方依赖性的简单小型应用程序。 使用不依赖第三方的MVVM Apple Foundation Framework提供了任何可用于在iOS体系结构中构建MVVM应用程序的内置解决方案吗? 是的,答案是Cocoa Key Value Observing 。 KVO是观察者模式 ,可用于观察以NSObject作为其超类的对象中的属性更改的值。 可可KVO是一种非常强大的机制,可用于在iOS中构建基于MVVM的体系结构。 缺点是语法使用起来非常冗长,我们必须手动保留和删除观察者, RxSwift提供了addToDisposeBag方法,该方法可用于自动删除观察者 。 实施KVO以构建基于iOS MVVM的应用 这是示例iOS应用程序,当用户在TextField中键入内容时,该应用程序实现了KVO以构建简单的电子邮件验证。 该应用程序分为3个主要组成部分: ViewController是一个UITableViewController ,它显示UITextField来输入电子邮件,而UILabel来显示电子邮件是否有效。 EmailModel是一个普通的Swift类 ,用于存储电子邮件的字符串和表示电子邮件是否有效的布尔值。 EmailViewModel是一个Cocoa NSObject超类,它提供了将显示电子邮件文本以及它是否为有效电子邮件格式的属性。 电子邮件模型 EmailModel存储电子邮件的值文本和表示电子邮件是否有效的isValid布尔值。 值更改时使用Swift属性观察器,使用包含有具有新值的userInfo的NotificationCenter来发布带有EmailModel.TextDidChange的Notification ,它还通过调用validateEmail来 设置isValid的值 ,并将电子邮件文本的newValue传递为使用RegEx表达式评估。 isValid布尔值中的更改也通过NotificationCenter发布。 EmailViewModel EmailViewModel是基于NSObject超类的MVVM , 该类接受EmailModel作为其构造函数。 它提供了使用objc动态关键字的 emailTextValue和isValidValue, […]

纹理最佳实践5

MVVM활용한材质纹理应用程序만들기 서론 图1〜4편까로는를를를본적인본적인본적인본적인뤘고뤘고뤘고뤘고뤘고뤘고뤘고뤘고뤘고본적인본적인본적인본적인본적인본적인본적인본적인본적인듭니듭니듭니듭니듭니듭니。 이번에높높매우매우때문에팅을팅을하신하신하신한한한한한듭니듭니듭니듭니듭니듭니듭니듭니듭니。。。。。。。。。。 RxSwift / RxCocoa Link이해(链接) Texture UI发布(AsyncDisplayKit) 型号,视图해이해,기존MVC패턴에패턴에 MVC와MVVM 우선MVVM존에에에존존MVC패턴을말씀드리자면 MVC패턴이Model ?,模型—视图—控制器의로약자리케이션을가지의로역할다。 应用程序应用程序控制器控制器模型数据视图,视图视图菜单视图。 iOS장가장기본적인이며,많이쓰이기도다。 下载,下载iOS代理到Google Play上的应用程序。 왜이,MVVM패턴이탄생하게된?。 죠다똑같은케리케이션인데죠이죠。 MVC在UI的다。。。上케케케케케케케케면면면면뿐더러뿐더러。 MVC模型模型视图控制器控制器控制器控制器控制器控制器控制器控制器控制器지게다。 따라서查看模型것이것이MVVM패턴입니다。 MVVM模型— ViewModel —查看로있습니다。 ViewModel的下载,ViewModel的ViewModel的下载,ViewModel的下载,ViewModel的下载。 ViewModel模型在模型中的使用。 iOS는ViewController때문에기模型— ViewModel View View(ViewController)이되겠습니다。 면따라서어플되케에에에에에에에에에에에에에에같습니다。다 에MVVM이랑MVC했습니다만른다고감사참조하시면다하겠습니 (이번스포지취지는기아니기비교할려는게이니다。) 已下载MVVM,Texture和Github存储库列表。 준비물이필요하겠죠? 。사항은같습니다。 Github存储库API(https://api.github.com/repositories) Xcode Cocoapod(Texture,RxSwift / RxCocoa 4.x이상,AlamoFire) 분들은https://github.com/GeekTree0101/RxMVVM-Texture 위의Github存储库를克隆되겠습니다。 (星级눌려주시면사하겠습니다。ㅎ) 迅速下载Swift4.x。 模特과视图를보자! 우선,개략적으로개략적으알아보도록하겠습니다。 在ViewModel中查看ViewModel,在ModelUp中查看模型,在ModelProvider中获取模型。 Model Provider的模型Model和Array的模型。 View저희가만들를넣었고넣었고。나타냈습니다나타냈습니다 […]

UITableViewCell配置实践

假设我们的足球俱乐部模型具有以下界面: 足球俱乐部数据模型 根据俱乐部的属性值,我们的业务逻辑应确定进度的颜色和相应的装饰文字(正,负或破折号)。 1.门面式单元 苹果公司提供的本机UITableViewCell正是这种样式。 它提供了3个公共访问器来呈现内容: textLabel , detailTextLabel, imageView 。 但是,通常,我们需要更多的UI元素和自定义。 因此,我们可以将子视图添加到单元格的内容视图中,也可以创建UITableViewCell的自定义子类并添加必要的公共属性: 外墙样式的单元头文件 因此,业务逻辑由其数据源在外部进行管理: 外墙样式单元格配置 用户选择将按照以下方式处理: 外墙样式的用户选择逻辑 外墙风格的优点: 本机样式(Apple提供的样式)。 简单灵活,将来可以支持。 单元从外部填充,对业务逻辑一无所知。 外墙样式的缺点: 所有访问器都是公共的,这提供了低级别的封装。 要确定选择哪个足球俱乐部用户,您必须在数据源中执行其他搜索操作。 在动态数据更改的情况下,对数据源的附加搜索似乎是不可靠的,并且对于数据源不是PODS(普通旧数据源😏)的情况则很复杂,即它包含许多不同的模型,部分并且具有不均匀的结构。 2. VIPER样式的单元 我想用这种方式命名这种样式,因为它具有VIPER拱形固有的一些功能。 Cell仅提供设置值的公共方法,所有访问器都封装在“ .m”文件中: VIPER样式的单元公共API 在单元的实现中为访问器设置了相应的值。 从外面看起来像: per蛇式电池配置 VIPER风格的优点: 最高级别的封装。 单元从外部填充,对业务逻辑一无所知。 VIPER风格的缺点: 1.对于具有大量UI元素的“超载”单元格,与fe Facade样式的单元格相比,您的头文件将是双倍大小的(要设置标签的字体,文本和文本颜色,您必须向VIPER添加3种单独的方法样式的单元格公共API)。 在这里,我只引用Robert C. Martin在他的“ Clean Code”一书中提到的第4个简单设计规则: 最小的类和方法。 高等级的方法有时是无意义的教条主义的结果​​。 …我们的目标是使整个系统保持较小,同时还要使函数和类保持较小。 2.由于它不存储指向模型的指针-您将必须通过在数据源中进行附加搜索来确定选择了哪个足球俱乐部用户。 3.通过复杂数据源进行其他搜索会降低将来对应用程序的支持的简便性。 3. MVVM样式的单元 这种风格的主要特点是: 1)使用ViewModel,它关心业务逻辑并用数据填充单元格; […]

MVVMC —在Runtastic适应MVVM设计模式

为什么我们关心建筑 在Runtastic,我们已经创建了38个iOS应用程序,我们的团队已经发展到20个iOS开发人员,并且我们的iOS代码库包含超过700,000行代码。 不断壮大的团队会导致代码库不断壮大,从而导致更高的复杂性和更多的代码依赖性。 除非您关心体系结构并在创建软件组件时遵循一些规则,否则这可能会以灾难告终: 遵循单一责任原则 可测试性设计 有明确的依赖性 保持代码可读性和可维护性 我们都从苹果公司的MVC开始,它可以变成Massive View Controller(在那完成了)。 尝试运行`find。 型f -exec wc -l {} + | 在项目的根目录中对-n`进行排序 。 您可能会像我们一样找到具有数千行代码的ViewController。 意识到使用MVC遵守上述规则时,我们面临着越来越多的挑战,因此我们着手寻找其他设计模式。 作为iOS社区中的当今热门话题,您可以在各种设计模式之间进行选择,包括MVC,MVP,MVVM或VIPER。 经过研究后,我们决定采用MVVM,但仍未解决一些问题,例如路由(显示新屏幕)或数据绑定。 因此,我们还仔细研究了VIPER,它在解决这些问题方面确实有很好的想法。 但是在VIPER中,我们经历了不利的一面,即存在大量的样板代码以及不习惯这种模式的开发人员的陡峭学习曲线。 最后,我们将从VIPER中学到的知识整合到我们自己的MVVM设计模式中。 MVVMC —什么是C? C代表“calçots”,这是加泰罗尼亚语起源的一种特定类型的洋葱,与我们的同事和这种模式的发起者相同。 在Runtastic博客上阅读全文

MVVM实现UICollectionView的方法-第4部分

单元中的用户交互。 如果您对示例项目感兴趣,那么PowerTools是一个小框架,我正在构建这些框架,应用这些文章中介绍的所有策略,然后在您的计算机上进行尝试,只需在bash终端上尝试PowerTools 。 在这里您可以找到以前的部分: 第1部分-使您的内容独立 第2部分-增强ViewModel和单元的可重用性 第3部分-使用UICollectionFlowLayout的单元格大小 互动,滚动和委派 正如我们在第3部分中所看到的,UICollectionViewDelegate与UICollectionViewDataSource一起埋在我们的DataSource类中。 这是因为UICollectionViewDelegate具有很多功能: 定义单元格的大小 响应用户与单元的交互 是UICollectionView的UIScrollViewDelegate 吗? 但是通常我想分别定义和管理那些行为,以遵守单一责任原则。 为此,我应用了Jesse Squires在本文中描述的技术,在数据源上定义了两个委托:InteractionDelegate和UIScrollViewDelegate。 所有这些方法都将代理给委托,可以单独实现这些委托并将行为注入到DataSource中。 我的假设是:ViewController,您将在迭代呈现的业务资源上呈现劣势。 如果为真,则每个项目都有一个要呈现的特定UIViewController或定义该项目需要呈现哪个UIViewController的相关逻辑。 同时, UIViewControllers需要定义上下文,通常这些信息不依赖业务资源,而是直接从UIViewController到UIViewController 。 基于这些假设,我可以定义一个Builder,他是唯一知道如何构造目标UIViewController的Builder 。 它将包含与构建UIViewController所需的业务资源相关的所有信息,并从工厂接收要注入的上下文。 带有字符串的示例构建器。 我定义了在应用程序级别在PowerTools框架中通用的Context ,通常将其用于依赖注入。 Factory是一个协议,因此可以从需要它的每个对象中实现它,并将上下文注入到Builder中,因此一切都是类型安全的。 在PowerTools中声明的AbstractFactory 观看AbstractFactory的实现,我们可以看到一个新的接口,该接口以前从未知道过,但是它的名称应该很清楚: BuilderContainer。 这是启用类型擦除的层: 很简单,但是像个魔术 类型擦除是一个复杂的论点,如果您有兴趣深入了解,建议您从NatashaTheRobot的本文开始。 FastForward,这是我在ItemViewModels中应用typeErasure的方式: ItemViewModel如何将构建器传递到其交互工厂 此代码段中的重要部分是ColorItemViewModel扩展,其余的仅用于提供有关正在应用的内容的上下文。 因此,现在我们只需要将Interaction委托绑定到AbstractFactory即可使其像黑魔法一样工作,并且要做到这一点,使用条件扩展的解决方案非常简单: 合并AbstractFactory行为的InteractionDelegate条件扩展 结论 我大量使用这些模式来增强应用程序中的代码可重用性和责任封装,因此,如果您发现此提示很方便或有增强的想法,请提示我或向PowerTools提出拉取请求

具有ReactiveKit的iOS中的MVVM

使用ReactiveKit实现MVVM登录示例 如果您已经开发iOS已有一段时间了,那么您可能已经听说过MVC : Massive View Controller 。 这种现象可以从对视图控制器中的Web服务器的无辜调用开始,然后突然出现:一个庞大的ViewController ,它有成百上千行,大量的职责和测试的噩梦。 苹果的MVC有很多替代方案,例如MVP , MVVM和VIPER 。 在本文中,我决定尝试使用ReactiveKit进行MVVM方法。 观看Bohdan Orlov撰写的有关iOS体系结构模式的精彩文章。 为什么选择ReactiveKit ? 关于RxSwift和ReactiveCocoa的样本很多,但实际上ReactiveKit的样本很少。 我真的很喜欢它的前身SwiftBond,所以我决定尝试它的演变。 在本文中,我们将基于ReactiveKit和MVVM创建一个简单的Login示例。 我们将使用三个依赖项: ReactiveKit , ReactiveUIKit和AlamofireReactive 。 您可以在ReactiveKit Github上了解有关它们的更多信息。 MVVM反应性登录 让我们开始创建一个简单的ViewController的示例,其中包含两个文本字段(用户名和密码)和一个登录按钮。 将IBOutlet链接到ViewController之后,我们将创建一个新的ViewModel类。 此ViewModel将保存ViewController将观察的属性 ,以更新其视觉状态。 属性将可变状态包装到可以观察该状态的对象中。 每当状态改变时,就可以通知观察者。 — ReactiveKit 但是,让我们从更简单的事情开始。 让我们创建一个initializer ,它接收两个属性 (一个用于用户,一个用于密码)并开始观察更改: ReactiveUIKit已经具有UI元素的多个属性,例如`rText`,这使将变量绑定到动作变得非常容易。 看! 现在,在用户键入每个字符后,我们会收到通知! 让我们继续并使用此属性做一些更有用的事情。 如果在字段中未输入任何文本,则将它们组合在一起以禁用登录按钮,并在用户键入有效的用户/密码组合后将其启用: 太棒了! 通过组合来自用户和密码的新值,我们可以决定是否要启用或禁用登录按钮,只需设置属性并将其绑定在按钮上,UI就会自动更新! 测试我们的ViewModel也变得轻而易举 。 我们可以模拟用户和密码的属性 ,然后测试ViewModel行为,而无需处理IBOutlets和UIViewControllers 。 注意:Quick用于BDD测试。 调用我们的后端以验证数据 […]

在Swift 3中涉猎MVVM

MVVM(model-view-viewModel)是一种架构模式,可以替代MVC(model-view-controller)。 MVVM,有时也称为表示模型,提供了一种组织代码的方式,而不会导致大量的视图控制器。 在MVVM中,您将代码抽象为包括viewModel,该模型是一个文件,其中包含要在视图中显示的值。 我们编写的用于格式化值(即格式化要插入到UILabel中的字符串的格式)以呈现给视图的逻辑发生在viewModel中。 View Controller拥有viewModel,该ViewModel拥有Model,而Model又更新了View Model,后者又用于更新View Controller,后者又更新了视图。 在这个博客中,我将向您展示一个简单的示例,说明如何使用MVVM架构模式抽象代码。 为了说明这一点,我将制作一个将在iTunes商店中显示当前排名前100的免费应用的应用。 该应用程序将使用tableView并需要联网到iTunes API端点。 我将在我的过程中包括联网步骤。 步骤1:设定APIClient 我使用的API来自iTunes的RSS Feed Generator,不需要密钥或授权令牌。 端点是:https://rss.itunes.apple.com/api/v1/us/ios-apps/top-free/100/explicit/json #1:我创建了一个从NSObject继承的APIClient类。 稍后在我的viewModel中实例化此APIClient时,从NSObject继承非常重要。 #2:我编写了一个具有完成处理程序的fetchAppList函数。 完成处理程序将包含NSDictionaries的可选数组。 JSON数据将以字典数组的形式返回,用于下面的关键“结果”。 #3:我从iTunes端点创建和解开URL。 #4:创建一个URLSession。 #5:从我们的dataTask中解包我们返回的数据。 #6:由于JSON序列化会引发错误,请使用do / try / catch创建我们的JSON对象并处理我们的错误。 我解包了responseJSON对象,并将其强制转换为NSDictionary,然后选择.allowFragments选项。 #7:从我的responseJSON对象中,我有一个用于“结果”键的字典数组,因此我可以访问它并创建一个对象并将其转换为NSDictionaries数组。 请注意我如何从keyPath “ feed.results”访问此文件。 您可以通过keyPath访问JSON字典值! 🌮 #8:我使用NSDictionaries的apps数组设置完成处理程序。 #9:如果收到错误,则将完成处理程序设置为nil。 #10:我继续执行dataTask。 永远记住要这样做。 步骤2:设置ViewModel。 #1:我创建了一个继承自NSObject的ViewModel文件。 此viewModel将是我的View Controller中的一个属性,并由情节提要插入。 #2:我创建一个标记为@IBOutlet的apiClient属性,该属性将由情节提要实例化。 因为我知道情节提要将注入它,所以我可以使用(!)bang运算符,因为我知道它不会为零。 #3:我定义了一个应用程序字典,该字典将保存通过我的iTunesClient的apiClient调用检索到的应用程序。 #4:编写一个函数,该函数将触发对iTunes API的apiClient调用,返回数据并设置一个完成处理程序,该处理程序准备好重新加载要显示的数据。 #5:调用我们的apiClient属性来获取我们的应用。 #6:将这段代码放在主线程上,因为我们预计它会如何影响视图控制器中表视图中的UI。 #7:将本地应用程序数组分配给我们返回的NSDictionaries JSON。 […]

基于合同的软件架构模式

再次简化软件架构 营销中最重要的规则之一就是倾听其客户需求。 让我们考虑MVVM架构中View客户端的真实需求,注册模型变更通知,以便为他们提供最佳的编码体验,并定义一个架构合同,该合同将满足他们的需求,以严格遵守合同规则。 定义这组需求是为了通过减少此通知调用的外部可变性来减少软件的复杂性:为了获得流畅的体验,当上下文完全由以下内容确定时,只有一种可能的方法可以调用目标函数数据和线程的观点。 此外,该合同应完整并考虑与模型的所有交互:这样,合同就保护了目标功能背后的代码不受应用程序其余部分的影响。 与其编写复杂的代码来管理所有意外的可能情况以解决所有可能的执行情况,不如通过设计减少到唯一的情况并通过合同来强制执行,来减少可能的情况数量。 实施名义上的方案就足够了。 确定每个客户的需求 从市场细分的角度来看,有几种类型的客户: 1)查看内容客户端: 视图内容客户端是视图控制器的功能,负责基于某些模型属性渲染视图。 客户端需要通过其视图模型从模型中读取一组属性:因此,当这些读取属性发生更改时,必须通知客户端。 当所有读取属性都稳定时,客户端要求该通知仅在主线程事件循环中一次 同步发生。 稳定意味着这些读取属性在事件循环结束之前不会更改。 这样可以保证所显示的内容与模型的当前状态完全匹配,而不是其先前状态的过时副本。 客户端可能还需要编写一些模型属性,其他View Content客户端将使用这些模型属性。 在属性写入后,这些订阅的View Content客户应收到其通知。 书面财产应作为合同的一部分。 不允许客户读取或写入不属于合同一部分的任何财产,因为这可能会破坏其他客户的“财产稳定”规则。 在渲染视图时,所有这些都发生在主线程中。 客户端还要求在事件循环结束之前不得删除其视图控制器,这意味着将在接收到此通知之前执行视图层次结构渲染。 该客户端还需要独立于模型对象的存在而注册模型属性,以便与模型对象创建/删除分离:每个模型属性均由源自根模型对象的唯一键路径标识。 这组需求是通知合同的基础: “当这组现在稳定的READ属性中的至少一个发生更改时,我只希望同步地被通知一次,并且我可以读/写其中一些WRITE属性。” 因此,通知调度程序应基于这些联系来计算模型属性之间的依赖关系:如果合同读取A并写入B,则B依赖于A,这将创建模型属性顺序。 因此,通知调度程序应将合同级别计算为读取集的最高属性级别,并按此顺序进行调度。 2)查看层次结构客户端: 视图层次结构客户端是一种视图控制器功能,负责基于一组模型“视图层次结构”属性,通过创建/删除子视图层次结构来修改其子视图层次结构。 该客户端不应向其子视图控制器提供模型属性,而应仅向子视图控制器用于从模型中获取其模型属性的不可变配置数据。 由于视图层次结构更新将从根到叶发生,因此每个视图层次结构客户端均应提供与其层次结构级别相同的优先级编号: 根视图控制器=优先级1 其子级=优先级2 它的子孙=优先级3 等等… 通知调度程序将首先按优先级顺序发送基于优先级的通知,然后再发送与数据相关的通知(例如:查看内容)。 视图层次结构客户端可以写入任何不稳定的视图内容或视图层次结构属性,即不属于优先级相等或较低的优先级合同。 因此,合同如下: “当该组现在稳定的READ(视图层次结构)属性中的至少一个发生更改时,我希望仅在此优先级级别上仅被同步通知一次,并且我可以读/写任何非稳定属性。” 3)标准化,协调,计算数据客户端: 规范化客户端负责解决跟随模型写事务的模型中的任何不一致问题。 协调客户端负责在高层确定应用程序/文档的视图层次结构和上下文,并设置视图层次结构属性。 计算数据客户端负责计算一组属性,这些属性可以由多个视图模型共享,并且应在呈现视图层次结构之前进行计算。 这些客户端具有基于优先级的合同,带有硬编码的负优先级,可以在View Hierarchy客户端之前安排它们。 归一化=优先级-3 协调=优先级-2 计算数据客户端=优先级-1 查看层次结构…优先级为正 查看内容…无优先级/数据驱动 我们可以为客户提供优质服务吗? 当前有许多架构模式被大肆宣传,很明显,它们都试图满足其中一些需求。 据我所知,最接近上述需求的是单向Elm […]