草庐IT

ios - 用于管理观察者的 Objective-C 设计模式

coder 2023-07-29 原文

在我的应用程序中,我有一个对象封装了通过 HTTP 与服务器的通信。 如果服务器上发生更改,例如 session 不再有效,或者有新的用户消息等,此对象会发出一些 HTTP 请求以“轮询”。

应用程序的 UI 对象必须将自己注册到通信对象,以便通过 UI 对象实现的协议(protocol)接收通知。注册是通过以下方法完成的:

[communicationObject addObserver: self];

并删除自身:

[communicationObject removeObserver: self];

通信对象将观察者存储在可变数组中。在某些情况下,UI 对象是在 UINavigationController 中推送的 UIViewController。在这种情况下,当用户返回到父 Controller 时,UI Controller 不会被释放,因为通信对象的观察者数组保留了它,并且 UI Controller 不能将自己从观察者中移除,因为 dealloc 方法永远不会被调用(显然)。

问题:这个观察者-通知者是一个糟糕的设计模式吗?有没有一种方法可以在不使用viewWillDisappear方法的情况下检测到UI Controller 被父 Controller 释放?有解决此类情况的最佳做法吗?

最佳答案

最佳实践

如果您正在使用观察者模式,并且您希望 View Controller 观察屏幕上的值,调用addObserver 是个好主意:viewDidAppear 中,removeObserver:viewWillDisappear 中。这不是糟糕的设计或滥用这些方法;实际上,这是标准做法,也是对这些 View Controller 方法的一种很好的使用。

如果您希望 View Controller 继续观察值甚至在它从屏幕上移除后,首先确定这确实是您想要的。如果是,请记住以下几点:

  • 特别是,请确保您的 View Controller 的设置使其具有与之前存在的状态相同的状态,并且新出现在屏幕上时,就好像它是从头开始实例化并立即出现在屏幕上一样。一个不错的方法(通常是我在自己的项目中所做的)是将所有设置代码保存在 setup 方法中,并确保它在实例化和演示时都被调用。
  • 另外,一定要避免在后台进行昂贵的无关计算。通常,这可以通过在呈现 View Controller 时调用 setup 方法来实现,而不是在对象的生命周期内保持一致的状态。
  • 最后,请务必记住, View Controller 只有在屏幕上时才会连接其导出( View / subview ,通常统称为 View 层次结构)。当它关闭但保留时,这些都是 nil。检查其 View 层次结构是否准备就绪的一个好方法是通过 isViewLoaded 属性。

保留与展示

重要的是不要混淆 View Controller (或任何对象,就此而言)被保留在某处,并且它在在屏幕上。这些是非常不同的事件,而且通常不会同时发生。例如,如果您有一个“父” View Controller (例如 UINavigationController)管理一个或多个“子” View Controller ,那么一次可能会实例化并保留多个 View Controller ,而只有一次在屏幕上显示一个。

更好:NSNotificationCenter

如果您愿意,另一个处理全局事件的选项是通过 NSNotificationCenter,它允许您指定一个 selector 来调用观察者,允许匿名发布通知,并允许任意事件对象 (userInfo) 与通知事件相关联。这样,您的 communicationObject 将向 [NSNotificationCenter defaultCenter] 发布通知,您的 View Controller 将在 defaultCenter 上观察通知。您仍然会以类似的方式添加/删除观察者对象,但您会获得一种集中的、更强大的方式来协调全局事件。

关于ios - 用于管理观察者的 Objective-C 设计模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14242971/

有关ios - 用于管理观察者的 Objective-C 设计模式的更多相关文章

  1. ruby - i18n Assets 管理/翻译 UI - 2

    我正在使用i18n从头开始​​构建一个多语言网络应用程序,虽然我自己可以处理一大堆yml文件,但我说的语言(非常)有限,最终我想寻求外部帮助帮助。我想知道这里是否有人在使用UI插件/gem(与django上的django-rosetta不同)来处理多个翻译器,其中一些翻译器不愿意或无法处理存储库中的100多个文件,处理语言数据。谢谢&问候,安德拉斯(如果您已经在ruby​​onrails-talk上遇到了这个问题,我们深表歉意) 最佳答案 有一个rails3branchofthetolkgem在github上。您可以通过在Gemfi

  2. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  3. ruby-on-rails - Rails 常用字符串(用于通知和错误信息等) - 2

    大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje

  4. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  5. ruby - 如何在续集中重新加载表模式? - 2

    鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende

  6. Ruby Sinatra 配置用于生产和开发 - 2

    我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm

  7. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在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返回它复制的字节数,但是当我还没有下

  8. ruby-on-rails - 获取 inf-ruby 以使用 ruby​​ 版本管理器 (rvm) - 2

    我安装了ruby​​版本管理器,并将RVM安装的ruby​​实现设置为默认值,这样'哪个ruby'显示'~/.rvm/ruby-1.8.6-p383/bin/ruby'但是当我在emacs中打开inf-ruby缓冲区时,它使用安装在/usr/bin中的ruby​​。有没有办法让emacs像shell一样尊重ruby​​的路径?谢谢! 最佳答案 我创建了一个emacs扩展来将rvm集成到emacs中。如果您有兴趣,可以在这里获取:http://github.com/senny/rvm.el

  9. Ruby 文件 IO 定界符? - 2

    我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的

  10. ruby - 是否有用于序列化和反序列化各种格式的对象层次结构的模式? - 2

    给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最

随机推荐