{"id":18270377,"url":"https://github.com/Tricertops/Block-KVO","last_synced_at":"2025-04-05T01:30:33.279Z","repository":{"id":4349646,"uuid":"5485693","full_name":"Tricertops/Block-KVO","owner":"Tricertops","description":"Objective-C Key-Value Observing made easier with blocks","archived":false,"fork":false,"pushed_at":"2024-02-17T14:51:09.000Z","size":185,"stargazers_count":399,"open_issues_count":3,"forks_count":65,"subscribers_count":21,"default_branch":"master","last_synced_at":"2025-03-12T19:01:48.527Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/Tricertops.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2012-08-20T19:26:22.000Z","updated_at":"2025-02-23T21:05:06.000Z","dependencies_parsed_at":"2023-07-05T19:16:55.600Z","dependency_job_id":null,"html_url":"https://github.com/Tricertops/Block-KVO","commit_stats":{"total_commits":141,"total_committers":16,"mean_commits":8.8125,"dds":"0.14893617021276595","last_synced_commit":"5136f0d85e42abbabc09bfe29b703998e066b9a0"},"previous_names":["imartinkiss/block-kvo"],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tricertops%2FBlock-KVO","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tricertops%2FBlock-KVO/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tricertops%2FBlock-KVO/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tricertops%2FBlock-KVO/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Tricertops","download_url":"https://codeload.github.com/Tricertops/Block-KVO/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247276022,"owners_count":20912285,"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":[],"created_at":"2024-11-05T11:38:33.338Z","updated_at":"2025-04-05T01:30:33.006Z","avatar_url":"https://github.com/Tricertops.png","language":"Objective-C","readme":"Block Observing\n=============\n\n\nOverview\n--------\n**Key-Value Observing made easier with blocks.**\n\nThis is an **extension to Key-Value Observation** mechanism and allows you to use **blocks as observation handlers**.\nBlock Observing can be used and mixed with classic KVO without any problems.\n\nYou should be familiar with the concepts of [Key-Value Observing](http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/KeyValueObserving/KeyValueObserving.html) and [Key-Value Coding](http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/KeyValueCoding/Articles/KeyValueCoding.html#//apple_ref/doc/uid/10000107-SW1).\n\nLibrary and example app in this project are for iOS, but you can use in OS X project too by importing the source files directly.\n\n\nIntegration\n-----------\n1. **Drag** the project into your project (as a child or sibling).\n2. Add `Block Observing` to _**Target Dependencies**_ in _Build Phases_.\n3. Add `libBlockObserving.a` to _**Link Binary With Libraries**_ in _Build Phases_.\n4. Add **`-ObjC` and `-all_load`** as _Other Linker Flags_ in _Build Settings_.\n5. Make sure you have _Header Search Paths_ in _Build Settings_ set up (e.g. `Libraries/**`).\n6. Import `MTKObserving.h` to your files (usually in `Prefix.pch`).\n\n\u003e **CocoaPods** central repositary will no longer be updated. Use this:\n\u003e `pod 'Block-KVO', :git =\u003e 'https://github.com/Tricertops/Block-KVO.git'`\n\nFeatures\n--------\n\n\n### Observe using block ###\nAny object can observe _its own_ key-path using block handler. _Caller and receiver must be the same object and the key-path must be relative to the receiver._\n\n```objc\n[self observeProperty:@keypath(self.profile.username) withBlock:\n ^(__weak typeof(self) self, NSString *oldUsername, NSString *newUsername) {\n     self.usernameLabel.text = newUsername;\n }];\n```\n\nBlock arguments has no specific type (so they are `id`). You are supposed to specifiy the type by yourself as you want. Primitive values are wrapped by `NSNumber` or `NSValue` instances\n\n\n### Quick macros\n\nThe above code example using provided macro:\n\n```objc\nMTKObservePropertySelf(profile.username, NSString *, {\n    self.usernameLabel.text = new;\n});\n```\n\n\n### Equality check ###\n**IMPORTANT: This is different from the standard KVO.**\n\nOnce the value of observed property changes, but the values are _equal_ (using `-isEqual:` method) the observation blocks are _not_ invoked. For example `self.title = self.title;` will _not_ trigger observation.\n\n\n### No retain cycles inside the blocks ###\nAll observation blocks have first argument the receive/caller with name `self`. It overrides method argument `self`, but contains the same object. The only difference is `__weak` attribute. In the example code above, you can use `self` and will not cause retain cycle.\n\n\n### Observe Using Selector ###\nIf you want to get out of the current scope, you can just provide selector instead of block.\n\n```objc\n[self observeProperty:@keypath(self.profile.username) withSelector:@selector(didChangeUsernameFrom:to:)];\n```\n\n\n### Observe more key-paths at once ###\nThere are methods that take an array of key-paths and one block (or selector).\n\n\n### One-way binding (mapping) ###\nMap property to another property. Once the source key-path changes, destination is updated with the new value. Transform the value as you wish.\n\n```objc\n[self map:@keypath(self.profile.isLogged) to:@keypath(self.isLoggedLabel.text) transform:\n ^NSString *(NSNumber *isLogged) {\n     return (isLogged.boolValue ? @\"Logged In\" : @\"Not Logged In\");\n }];\n```\n\nAlso, there is convenience method for specifying replacement for null value.\n\n```objc\n[self map:@keypath(self.profile.username) to:@(self.usernameLabel.text) null:@\"Unknown\"];\n```\n\n\n### Two-way binding (mapping) ###\nTwo-way binding can be achieved by using two one-way bindings. Don't worry about recursion, because observation is supressed if the values are equal.\n\n```objc\n[self map:@keypath(self.task.isDone) to:@keypath(self.doneButton.selected) null:nil];\n[self map:@keypath(self.doneButton.selected) to:@keypath(self.task.isDone) null:nil];\n```\n\n\n### Observe NSNotifications using blocks ###\nImproved observation of notifications using blocks. `NSNotificationCenter` provides some support for this, but here you don't need to worry about removing those blocks or retain cycles.\n\n\n### Remove Observations\nRemoving is now automatic.\n\n---\n\n_The MIT License_  \n_Copyright © 2012 – 2016 Martin Kiss_\n","funding_links":[],"categories":["etc"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FTricertops%2FBlock-KVO","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FTricertops%2FBlock-KVO","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FTricertops%2FBlock-KVO/lists"}