NSSet+BlocksKit.h 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. //
  2. // NSSet+BlocksKit.h
  3. // BlocksKit
  4. //
  5. #import <Foundation/Foundation.h>
  6. /** Block extensions for NSSet.
  7. Both inspired by and resembling Smalltalk syntax, these utilities allows for
  8. iteration of a set in a logical way that saves quite a bit of boilerplate code
  9. for filtering or finding objects or an object.
  10. Includes code by the following:
  11. - [Michael Ash](https://github.com/mikeash)
  12. - [Corey Floyd](https://github.com/coreyfloyd)
  13. - [Aleks Nesterow](https://github.com/nesterow)
  14. - [Zach Waldowski](https://github.com/zwaldowski)
  15. @see NSArray(BlocksKit)
  16. @see NSDictionary(BlocksKit)
  17. */
  18. @interface NSSet (BlocksKit)
  19. /** Loops through a set and executes the given block with each object.
  20. @param block A single-argument, void-returning code block.
  21. */
  22. - (void)bk_each:(void (^)(id obj))block;
  23. /** Enumerates through a set concurrently and executes
  24. the given block once for each object.
  25. Enumeration will occur on appropriate background queues. This
  26. will have a noticeable speed increase, especially on dual-core
  27. devices, but you *must* be aware of the thread safety of the
  28. objects you message from within the block.
  29. @param block A single-argument, void-returning code block.
  30. */
  31. - (void)bk_apply:(void (^)(id obj))block;
  32. /** Loops through a set to find the object matching the block.
  33. bk_match: is functionally identical to bk_select:, but will stop and return
  34. on the first match.
  35. @param block A single-argument, BOOL-returning code block.
  36. @return Returns the object if found, `nil` otherwise.
  37. @see bk_select:
  38. */
  39. - (id)bk_match:(BOOL (^)(id obj))block;
  40. /** Loops through a set to find the objects matching the block.
  41. @param block A single-argument, BOOL-returning code block.
  42. @return Returns a set of the objects found.
  43. @see bk_match:
  44. */
  45. - (NSSet *)bk_select:(BOOL (^)(id obj))block;
  46. /** Loops through a set to find the objects not matching the block.
  47. This selector performs *literally* the exact same function as select, but in reverse.
  48. This is useful, as one may expect, for removing objects from a set:
  49. NSSet *new = [reusableWebViews bk_reject:^BOOL(id obj) {
  50. return ([obj isLoading]);
  51. }];
  52. @param block A single-argument, BOOL-returning code block.
  53. @return Returns an array of all objects not found.
  54. */
  55. - (NSSet *)bk_reject:(BOOL (^)(id obj))block;
  56. /** Call the block once for each object and create a set of the return values.
  57. This is sometimes referred to as a transform, mutating one of each object:
  58. NSSet *new = [mimeTypes bk_map:^id(id obj) {
  59. return [@"x-company-" stringByAppendingString:obj]);
  60. }];
  61. @param block A single-argument, object-returning code block.
  62. @return Returns a set of the objects returned by the block.
  63. */
  64. - (NSSet *)bk_map:(id (^)(id obj))block;
  65. /** Arbitrarily accumulate objects using a block.
  66. The concept of this selector is difficult to illustrate in words. The sum can
  67. be any NSObject, including (but not limited to) a string, number, or value.
  68. You can also do something like summing the count of an item:
  69. NSUInteger numberOfBodyParts = [[bodyList bk_reduce:nil withBlock:^id(id sum, id obj) {
  70. return @([sum integerValue] + obj.numberOfAppendages);
  71. }] unsignedIntegerValue];
  72. @param initial The value of the reduction at its start.
  73. @param block A block that takes the current sum and the next object to return the new sum.
  74. @return An accumulated value.
  75. */
  76. - (id)bk_reduce:(id)initial withBlock:(id (^)(id sum, id obj))block;
  77. /** Loops through a set to find whether any object matches the block.
  78. This method is similar to the Scala list `exists`. It is functionally
  79. identical to bk_match: but returns a `BOOL` instead. It is not recommended
  80. to use bk_any: as a check condition before executing bk_match:, since it would
  81. require two loops through the array.
  82. @param block A single-argument, BOOL-returning code block.
  83. @return YES for the first time the block returns YES for an object, NO otherwise.
  84. */
  85. - (BOOL)bk_any:(BOOL (^)(id obj))block;
  86. /** Loops through a set to find whether no objects match the block.
  87. This selector performs *literally* the exact same function as bk_all: but in reverse.
  88. @param block A single-argument, BOOL-returning code block.
  89. @return YES if the block returns NO for all objects in the set, NO otherwise.
  90. */
  91. - (BOOL)bk_none:(BOOL (^)(id obj))block;
  92. /** Loops through a set to find whether all objects match the block.
  93. @param block A single-argument, BOOL-returning code block.
  94. @return YES if the block returns YES for all objects in the set, NO otherwise.
  95. */
  96. - (BOOL)bk_all:(BOOL (^)(id obj))block;
  97. @end