{"id":13695883,"url":"https://github.com/yulingtianxia/MessageThrottle","last_synced_at":"2025-05-03T13:33:53.229Z","repository":{"id":43061146,"uuid":"108521071","full_name":"yulingtianxia/MessageThrottle","owner":"yulingtianxia","description":"A lightweight Objective-C message throttle and debounce library.","archived":false,"fork":false,"pushed_at":"2022-11-08T14:04:23.000Z","size":304,"stargazers_count":826,"open_issues_count":6,"forks_count":66,"subscribers_count":11,"default_branch":"master","last_synced_at":"2024-10-30T02:36:38.856Z","etag":null,"topics":["carthage","cocoapod-pod","debounce","message","objective-c","objective-c-runtime","runtime","throttle"],"latest_commit_sha":null,"homepage":"http://yulingtianxia.com/blog/2017/11/05/Objective-C-Message-Throttle-and-Debounce/","language":"Objective-C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yulingtianxia.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-10-27T08:37:09.000Z","updated_at":"2024-09-04T06:32:26.000Z","dependencies_parsed_at":"2022-07-15T15:01:02.095Z","dependency_job_id":null,"html_url":"https://github.com/yulingtianxia/MessageThrottle","commit_stats":null,"previous_names":[],"tags_count":27,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yulingtianxia%2FMessageThrottle","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yulingtianxia%2FMessageThrottle/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yulingtianxia%2FMessageThrottle/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yulingtianxia%2FMessageThrottle/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yulingtianxia","download_url":"https://codeload.github.com/yulingtianxia/MessageThrottle/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252196009,"owners_count":21709755,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["carthage","cocoapod-pod","debounce","message","objective-c","objective-c-runtime","runtime","throttle"],"created_at":"2024-08-02T18:00:34.356Z","updated_at":"2025-05-03T13:33:52.807Z","avatar_url":"https://github.com/yulingtianxia.png","language":"Objective-C","readme":"\u003cp align=\"center\"\u003e\n\u003ca href=\"https://github.com/yulingtianxia/MessageThrottle\"\u003e\n\u003cimg src=\"Assets/logo.png\" alt=\"MessageThrottle\" /\u003e\n\u003c/a\u003e\n\u003c/p\u003e\n\n[![CI Status](http://img.shields.io/travis/yulingtianxia/MessageThrottle.svg?style=flat)](https://travis-ci.org/yulingtianxia/MessageThrottle)\n[![Version](https://img.shields.io/cocoapods/v/MessageThrottle.svg?style=flat)](http://cocoapods.org/pods/MessageThrottle)\n[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)\n[![codecov](https://codecov.io/gh/yulingtianxia/MessageThrottle/branch/master/graph/badge.svg)](https://codecov.io/gh/yulingtianxia/MessageThrottle)\n[![Codacy Badge](https://api.codacy.com/project/badge/Grade/74890ac9cb4d4be6a8478009ac1c4e52)](https://www.codacy.com/project/yulingtianxia/MessageThrottle/dashboard?utm_source=github.com\u0026amp;utm_medium=referral\u0026amp;utm_content=yulingtianxia/MessageThrottle\u0026amp;utm_campaign=Badge_Grade_Dashboard)\n[![License](https://img.shields.io/cocoapods/l/MessageThrottle.svg?style=flat)](http://cocoapods.org/pods/MessageThrottle)\n[![Platform](https://img.shields.io/cocoapods/p/MessageThrottle.svg?style=flat)](http://cocoapods.org/pods/MessageThrottle)\n[![CocoaPods](https://img.shields.io/cocoapods/dt/MessageThrottle.svg)](http://cocoapods.org/pods/MessageThrottle)\n[![CocoaPods](https://img.shields.io/cocoapods/at/MessageThrottle.svg)](http://cocoapods.org/pods/MessageThrottle)\n[![Twitter Follow](https://img.shields.io/twitter/follow/yulingtianxia.svg?style=social\u0026label=Follow)](https://twitter.com/yulingtianxia)\n\n# MessageThrottle\n\nMessageThrottle is a lightweight, simple library for controlling frequency of forwarding Objective-C messages. You can choose to control existing methods per instance or per class. It's an implementation of function throttle/debounce developed with Objective-C runtime. For a visual explaination of the differences between throttling and debouncing, [see this demo](http://demo.nimius.net/debounce_throttle/).\n\n## 📚 Article\n\n- [Objective-C Message Throttle and Debounce](http://yulingtianxia.com/blog/2017/11/05/Objective-C-Message-Throttle-and-Debounce/)\n- [Associated Object and Dealloc](http://yulingtianxia.com/blog/2017/12/15/Associated-Object-and-Dealloc/)\n- [MessageThrottle Performance Benchmark and Optimization](http://yulingtianxia.com/blog/2018/05/31/MessageThrottle-Performance-Benchmark-and-Optimization/)\n- [MessageThrottle Safety](http://yulingtianxia.com/blog/2018/07/31/MessageThrottle-Safety/)\n\n## 🌟 Features\n\n- [x] Easy to use.\n- [x] Keep your code clear\n- [x] Reserve the whole arguments.\n- [x] Support instance, class and meta class.\n- [x] Support 3 modes: Throttle(Firstly), Throttle(Last) and Debounce.\n- [x] Centralized management of rules.\n- [x] Self-managed rules.\n- [x] Let method **MUST** invoke at the specified conditions.\n- [x] Persistent rules. \n\n## 🔮 Example\n\nTo run the example project, clone the repo and run MTDemo target.\n\n![](Assets/demo.gif)\n\n## 🐒 How to use\n\nThe following example shows how to restrict the frequency of forwarding `- [ViewController foo:]` message to 100 times per second.\n\n```\nStub *s = [Stub new];\nMTRule *rule = [s limitSelector:@selector(foo:) oncePerDuration:0.01]; // returns MTRule instance\n``` \n\nFor more control of rule, you can use `mt_limitSelector:oncePerDuration:usingMode:onMessageQueue:alwaysInvokeBlock:`.\n\nYou can also start with a creation of `MTRule`:\n\n```\nStub *s = [Stub new];\n// You can also assign `Stub.class` or `mt_metaClass(Stub.class)` to `target` argument.\nMTRule *rule = [[MTRule alloc] initWithTarget:s selector:@selector(foo:) durationThreshold:0.01];\nrule.mode = MTModePerformLast; // Or `MTModePerformFirstly`, ect\n[rule apply];\n```\n\nYou can let method **MUST** invoke at the specified conditions using `alwaysInvokeBlock`. The example code above will invoke message immediately if its 1st parameter equals \"1970\". BTW, `alwaysInvokeBlock` can has no parameter, or has one more `MTRule` before message's parameter list.\n\nYou should call `discard` method When you don't need limit `foo:` method.\n\n```\n[rule discard];\n```\n\n**NOTE: `MTRule` is self-managed. If the `target` of rule is a object instance, `MTRule` will discard itself automatically when the `target` is deallocated.**\n\nSome rules may have large `durationThreshold`. You can set property `persistent` to `YES`, and save them on disk by calling `savePersistentRules` method. These persistent rules will be applied after `MTEngine` class is loaded. `savePersistentRules` will be called automatically when receive terminate notification.\n\n```\nrule.persistent = YES;\n[MTEngine.defaultEngine savePersistentRules];\n```\n\n`MTRule` represents the rule of a message throttle, which contains strategy and frequency of sending messages. \n\nYou can assign an instance or (meta)class to `target` property. When you assign an instance to `target`, MessageThrottle will only restrict messages send to this instance. If you want to restrict a class method, just using `mt_metaClass()` to get it's meta class, and assign the meta class to `target`. Rules with instance `target` won't conflict with each other, and have a higher priority than rules with class `target`.\n\n**NOTE: A message can only have one rule per class hierarchy. For example, If there is one rule of message `- [Stub foo:]`, you can't add another rule of message `- [SuperStub foo:]` anymore.** PS: Assume that `Stub` is a subclass of `SuperStub`.\n\n`MTRule` also define the mode of performing selector. There are three modes defined in `MTMode`: `MTModePerformFirstly`, `MTModePerformLast` and `MTModePerformDebounce`. [This demo](http://demo.nimius.net/debounce_throttle/) shows the difference between throttle and debounce.\n\nThe default mode is `MTModePerformDebounce`. `MTModePerformDebounce` will restart timer when another message arrives during `durationThreshold`. So there must be a delay of `durationThreshold` at least. \n\n```\nMTModePerformDebounce:\nstart                                        end\n|           durationThreshold(old)             |\n@----------------------@----------------------\u003e\u003e\n|                      |                 \nignore                 will perform at end of new duration\n                       |---------------------------------------------\u003e\u003e\n                       |           durationThreshold(new)             |\n                       start                                        end\n```\n\n`MTModePerformFirstly` will performs the first message and ignore all following messages during `durationThreshold`.\n\n```\nMTModePerformFirstly:\nstart                                                                end\n|                           durationThreshold                          |\n@-------------------------@----------@---------------@----------------\u003e\u003e\n|                         |          |               |          \nperform immediately       ignore     ignore          ignore     \n```\n\n`MTModePerformLast` performs the last message at end time. Please note that does not perform message immediately, the delay could be `durationThreshold` at most. \n\n```\nMTModePerformLast:\nstart                                                                end\n|                           durationThreshold                          |\n@-------------------------@----------@---------------@----------------\u003e\u003e\n|                         |          |               |          \nignore                    ignore     ignore          will perform at end\n```\n\nWhen using `MTModePerformLast` or `MTModePerformDebounce`, you can designate a dispatch queue which messages perform on. The `messageQueue` is main queue by default. `MTModePerformLast` and `MTModePerformDebounce` modes will also use the last arguments to perform messages.\n\n`MTEngine` is a singleton class. It manages all rules of message throttles. You can use `applyRule:` method to apply a rule or update an old rule that already exists. Using it's `discardRule:` method to discardRule a rule. There is also a readonly property `allRules` for obtaining all rules in current application. \n\n## 📲 Installation\n\n### CocoaPods\n\n[CocoaPods](http://cocoapods.org) is a dependency manager for Cocoa projects. You can install it with the following command:\n\n```bash\n$ gem install cocoapods\n```\n\nTo integrate MessageThrottle into your Xcode project using CocoaPods, specify it in your `Podfile`:\n\n\n```\nsource 'https://github.com/CocoaPods/Specs.git'\nplatform :ios, '11.0'\nuse_frameworks!\ntarget 'MyApp' do\n\tpod 'MessageThrottle'\nend\n```\n\nYou need replace \"MyApp\" with your project's name.\n\nThen, run the following command:\n\n```bash\n$ pod install\n```\n\n### Carthage\n\n[Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks.\n\nYou can install Carthage with [Homebrew](http://brew.sh/) using the following command:\n\n```bash\n$ brew update\n$ brew install carthage\n```\n\nTo integrate MessageThrottle into your Xcode project using Carthage, specify it in your `Cartfile`:\n\n```ogdl\ngithub \"yulingtianxia/MessageThrottle\"\n```\n\nRun `carthage update` to build the framework and drag the built `MessageThrottleKit.framework` into your Xcode project.\n\n### Manual\n\nJust drag the \"MessageThrottle\" document folder into your project.\n\n## ❤️ Contributed\n\n- If you **need help** or you'd like to **ask a general question**, open an issue.\n- If you **found a bug**, open an issue.\n- If you **have a feature request**, open an issue.\n- If you **want to contribute**, submit a pull request.\n\n## 👨🏻‍💻 Author\n\nyulingtianxia, yulingtianxia@gmail.com\n\n## 👮🏻 License\n\nMessageThrottle is available under the MIT license. See the LICENSE file for more info.\n\n","funding_links":[],"categories":["Tools","Object-C 库"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyulingtianxia%2FMessageThrottle","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyulingtianxia%2FMessageThrottle","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyulingtianxia%2FMessageThrottle/lists"}