Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>It sounds like what you're after is a mixin: define a series of methods that form the behaviour that you want, and then add that behaviour to only the set of classes that need it.</p> <p>Here is a strategy I've used to great success in my project <a href="https://github.com/sharplet/EnumeratorKit" rel="noreferrer">EnumeratorKit</a>, which adds Ruby-style block enumeration methods to built-in Cocoa collection classes (in particular <a href="https://github.com/sharplet/EnumeratorKit/blob/master/EnumeratorKit/Core/EKEnumerable.h" rel="noreferrer"><code>EKEnumerable.h</code></a> and <a href="https://github.com/sharplet/EnumeratorKit/blob/master/EnumeratorKit/Core/EKEnumerable.m" rel="noreferrer"><code>EKEnumerable.m</code></a>:</p> <ol> <li><p>Define a protocol that describes the behaviour you want. For method implementations you are going to provide, declare them as <code>@optional</code>.</p> <pre class="lang-c prettyprint-override"><code>@protocol WritableView &lt;NSObject&gt; - (void)writeText:(NSString *)text; @optional - (void)setTextToDomainOfUrl:(NSString *)text; - (void)setTextToIntegerValue:(NSInteger)value; - (void)setCapitalizedText:(NSString *)text; @end </code></pre></li> <li><p>Create a class that conforms to that protocol, and implements all the optional methods:</p> <pre class="lang-c prettyprint-override"><code>@interface WritableView : NSObject &lt;WritableView&gt; @end @implementation WritableView - (void)writeText:(NSString *)text { NSAssert(@"expected -writeText: to be implemented by %@", [self class]); } - (void)setTextToDomainOfUrl:(NSString *)text { // implementation will call [self writeText:text] } - (void)setTextToIntegerValue:(NSInteger)value { // implementation will call [self writeText:text] } - (void)setCapitalizedText:(NSString *)text { // implementation will call [self writeText:text] } @end </code></pre></li> <li><p>Create a category on <code>NSObject</code> that can add these methods to any other class at runtime (note that this code doesn't support class methods, only instance methods):</p> <pre class="lang-c prettyprint-override"><code>#import &lt;objc/runtime.h&gt; @interface NSObject (IncludeWritableView) + (void)includeWritableView; @end @implementation + (void)includeWritableView { unsigned int methodCount; Method *methods = class_copyMethodList([WritableView class], &amp;methodCount); for (int i = 0; i &lt; methodCount; i++) { SEL name = method_getName(methods[i]); IMP imp = method_getImplementation(methods[i]); const char *types = method_getTypeEncoding(methods[i]); class_addMethod([self class], name, imp, types); } free(methods); } @end </code></pre></li> </ol> <p>Now in the class where you want to include this behaviour (for example, <code>UILabel</code>):</p> <ol> <li>Adopt the <code>WritableView</code> protocol</li> <li>Implement the required <code>writeText:</code> instance method</li> <li><p>Add this to the top of your implementation:</p> <pre class="lang-c prettyprint-override"><code>@interface UILabel (WritableView) &lt;WritableView&gt; @end @implementation UILabel (WritableView) + (void)load { [self includeWritableView]; } // implementation specific to UILabel - (void)writeText:(NSString *)text { self.text = text; } @end </code></pre></li> </ol> <p>Hope this helps. I've found it a really effective way to implement cross-cutting concerns without having to copy &amp; paste code between multiple categories.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload