Browse Source

Safe area support for iOS 10

Leo Natan 6 years ago
parent
commit
600141395d
No account linked to committer's email address
1 changed files with 122 additions and 0 deletions
  1. 122
    0
      lib/ios/RNNSwizzles.m

+ 122
- 0
lib/ios/RNNSwizzles.m View File

@@ -47,3 +47,125 @@ static id (*__SWZ_initWithEventDispatcher_orig)(id self, SEL _cmd, id eventDispa
47 47
 #endif
48 48
 
49 49
 @end
50
+
51
+#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 /* __IPHONE_11_0 */
52
+
53
+@interface UIView (OS10SafeAreaSupport) @end
54
+
55
+@implementation UIView (OS10SafeAreaSupport)
56
+
57
+- (UIEdgeInsets)_ln_safeAreaInsets
58
+{
59
+	static NSString* const b64 = @"X3ZpZXdDb250cm9sbGVyRm9yQW5jZXN0b3I=";
60
+	UIViewController* vc = [self valueForKey:[[NSString alloc] initWithData:[[NSData alloc] initWithBase64EncodedString:b64 options:0] encoding:NSUTF8StringEncoding]];
61
+	if(vc == nil)
62
+	{
63
+		return UIEdgeInsetsZero;
64
+	}
65
+	
66
+	CGRect myFrameInVCView = [vc.view convertRect:self.bounds fromView:self];
67
+	
68
+	UIEdgeInsets rv = UIEdgeInsetsZero;
69
+	rv.top = CGRectIntersection(myFrameInVCView, CGRectMake(0, 0, vc.view.bounds.size.width, vc.topLayoutGuide.length)).size.height;
70
+	rv.bottom = CGRectIntersection(myFrameInVCView, CGRectMake(0, vc.view.bounds.size.height - vc.bottomLayoutGuide.length, vc.view.bounds.size.width, vc.bottomLayoutGuide.length)).size.height;
71
+	
72
+	if (@available(iOS 11.0, *))
73
+	{
74
+		NSParameterAssert(UIEdgeInsetsEqualToEdgeInsets(self.safeAreaInsets, rv));
75
+	}
76
+	
77
+	return rv;
78
+}
79
+
80
+- (void)_ln_triggerSafeAreaInsetsDidChange
81
+{
82
+	if([self respondsToSelector:@selector(safeAreaInsetsDidChange)])
83
+	{
84
+		[self performSelector:@selector(safeAreaInsetsDidChange)];
85
+	}
86
+}
87
+
88
+- (void)_ln_layoutSubviews
89
+{
90
+	[self _ln_triggerSafeAreaInsetsDidChange];
91
+	
92
+	struct objc_super super = {.receiver = self, .super_class = class_getSuperclass(object_getClass(self))};
93
+	void (*super_class)(struct objc_super*, SEL) = (void*)objc_msgSendSuper;
94
+	super_class(&super, _cmd);
95
+}
96
+
97
+- (void)_ln_setFrame:(CGRect)frame
98
+{
99
+	[self _ln_triggerSafeAreaInsetsDidChange];
100
+	
101
+	struct objc_super super = {.receiver = self, .super_class = class_getSuperclass(object_getClass(self))};
102
+	void (*super_class)(struct objc_super*, SEL, CGRect) = (void*)objc_msgSendSuper;
103
+	super_class(&super, _cmd, frame);
104
+}
105
+
106
+- (void)_ln_setCenter:(CGPoint)center
107
+{
108
+	[self _ln_triggerSafeAreaInsetsDidChange];
109
+	
110
+	struct objc_super super = {.receiver = self, .super_class = class_getSuperclass(object_getClass(self))};
111
+	void (*super_class)(struct objc_super*, SEL, CGPoint) = (void*)objc_msgSendSuper;
112
+	super_class(&super, _cmd, center);
113
+}
114
+
115
+- (void)_ln_setBounds:(CGRect)bounds
116
+{
117
+	[self _ln_triggerSafeAreaInsetsDidChange];
118
+	
119
+	struct objc_super super = {.receiver = self, .super_class = class_getSuperclass(object_getClass(self))};
120
+	void (*super_class)(struct objc_super*, SEL, CGRect) = (void*)objc_msgSendSuper;
121
+	super_class(&super, _cmd, bounds);
122
+}
123
+
124
++ (void)load
125
+{
126
+	static dispatch_once_t onceToken;
127
+	dispatch_once(&onceToken, ^{
128
+		if(NSProcessInfo.processInfo.operatingSystemVersion.majorVersion < 11)
129
+		{
130
+			Class cls = NSClassFromString(@"RCTSafeAreaView");
131
+			if(cls == NULL)
132
+			{
133
+				return;
134
+			}
135
+			
136
+			Method m = class_getInstanceMethod([UIView class], @selector(_ln_safeAreaInsets));
137
+			if(NO == class_addMethod(cls, @selector(safeAreaInsets), method_getImplementation(m), method_getTypeEncoding(m)))
138
+			{
139
+				return;
140
+			}
141
+			
142
+			m = class_getInstanceMethod([UIView class], @selector(_ln_layoutSubviews));
143
+			if(NO == class_addMethod(cls, @selector(layoutSubviews), method_getImplementation(m), method_getTypeEncoding(m)))
144
+			{
145
+				return;
146
+			}
147
+			
148
+			m = class_getInstanceMethod([UIView class], @selector(_ln_setFrame:));
149
+			if(NO == class_addMethod(cls, @selector(setFrame:), method_getImplementation(m), method_getTypeEncoding(m)))
150
+			{
151
+				return;
152
+			}
153
+			
154
+			m = class_getInstanceMethod([UIView class], @selector(_ln_setCenter:));
155
+			if(NO == class_addMethod(cls, @selector(setCenter:), method_getImplementation(m), method_getTypeEncoding(m)))
156
+			{
157
+				return;
158
+			}
159
+			
160
+			m = class_getInstanceMethod([UIView class], @selector(_ln_setBounds:));
161
+			if(NO == class_addMethod(cls, @selector(setBounds:), method_getImplementation(m), method_getTypeEncoding(m)))
162
+			{
163
+				return;
164
+			}
165
+		}
166
+	});
167
+}
168
+
169
+@end
170
+
171
+#endif