@@ -25,24 +25,31 @@ of this software and associated documentation files (the "Software"), to deal
2525#import < objc/runtime.h>
2626#import " UITextView+Placeholder.h"
2727
28- @interface DeallocHooker : NSObject
28+ @implementation UITextView (Placeholder)
2929
30- @property ( nonatomic , strong ) void (^willDealloc)( void );
30+ # pragma mark - Swizzle Dealloc
3131
32- @end
32+ + (void )load {
33+ [super load ];
3334
34- @implementation DeallocHooker
35+ // is this the best solution?
36+ method_exchangeImplementations (class_getInstanceMethod (self.class , NSSelectorFromString (@" dealloc" )),
37+ class_getInstanceMethod (self.class , @selector (swizzledDealloc )));
38+ }
3539
36- - (void )dealloc {
37- if (self.willDealloc ) {
38- self.willDealloc ();
40+ - (void )swizzledDealloc {
41+ [[NSNotificationCenter defaultCenter ] removeObserver: self ];
42+ for (NSString *key in self.class .observingKeys ) {
43+ @try {
44+ [self removeObserver: self forKeyPath: key];
45+ }
46+ @catch (NSException *exception) {
47+ // Do nothing
48+ }
3949 }
50+ [self swizzledDealloc ];
4051}
4152
42- @end
43-
44-
45- @implementation UITextView (Placeholder)
4653
4754#pragma mark - Class Methods
4855#pragma mark `defaultPlaceholderColor`
@@ -59,6 +66,19 @@ + (UIColor *)defaultPlaceholderColor {
5966}
6067
6168
69+ #pragma mark - `observingKeys`
70+
71+ + (NSArray *)observingKeys {
72+ return @[@" attributedText" ,
73+ @" bounds" ,
74+ @" font" ,
75+ @" frame" ,
76+ @" text" ,
77+ @" textAlignment" ,
78+ @" textContainerInset" ];
79+ }
80+
81+
6282#pragma mark - Properties
6383#pragma mark `placeholderLabel`
6484
@@ -80,25 +100,9 @@ - (UILabel *)placeholderLabel {
80100 name: UITextViewTextDidChangeNotification
81101 object: self ];
82102
83- NSArray *observingKeys = @[@" attributedText" ,
84- @" bounds" ,
85- @" font" ,
86- @" frame" ,
87- @" text" ,
88- @" textAlignment" ,
89- @" textContainerInset" ];
90- for (NSString *key in observingKeys) {
103+ for (NSString *key in self.class .observingKeys ) {
91104 [self addObserver: self forKeyPath: key options: NSKeyValueObservingOptionNew context: nil ];
92105 }
93-
94- DeallocHooker *hooker = [[DeallocHooker alloc ] init ];
95- hooker.willDealloc = ^{
96- [[NSNotificationCenter defaultCenter ] removeObserver: self ];
97- for (NSString *key in observingKeys) {
98- [self removeObserver: self forKeyPath: key];
99- }
100- };
101- objc_setAssociatedObject (self, @" deallocHooker" , hooker, OBJC_ASSOCIATION_RETAIN_NONATOMIC );
102106 }
103107 return label;
104108}
0 commit comments