Created
January 3, 2020 21:49
-
-
Save jbruchanov/ccefec4c93f6ceb5252478ad6dea1d39 to your computer and use it in GitHub Desktop.
UITor - macos
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// AppDelegate.m | |
// uitor | |
// | |
// Created by Jiri Bruchanov on 03/01/2020. | |
// Copyright © 2020 Jiri Bruchanov. All rights reserved. | |
// | |
//WEB Server https://github.com/swisspol/GCDWebServer | |
#import "AppDelegate.h" | |
@interface AppDelegate () | |
@end | |
@implementation AppDelegate | |
GCDWebServer* _webServer; | |
-(GCDWebServerDataResponse*) runOnMainThread : (GCDWebServerDataResponse* (^)(void))action { | |
__block GCDWebServerDataResponse *result = nil; | |
dispatch_semaphore_t semaphor = dispatch_semaphore_create(0); | |
dispatch_async(dispatch_get_main_queue(), ^{ | |
result = action(); | |
dispatch_semaphore_signal(semaphor); | |
}); | |
dispatch_semaphore_wait(semaphor, DISPATCH_TIME_FOREVER); | |
// dispatch_release(semaphor); | |
return result; | |
} | |
-(UIView*)findView:(int) position withRootView:(UIView*) view withPosition:(int*) counter { | |
if((*counter) == position){ | |
return view; | |
} | |
if([view.subviews count] > 0){ | |
for (UIView *childView in view.subviews) { | |
(*counter)++; | |
UIView *result = [self findView:position withRootView:childView withPosition:counter]; | |
if(result){ | |
return result; | |
} | |
} | |
} | |
return nil; | |
} | |
-(NSDictionary*) getData:(UIView*) view{ | |
NSMutableDictionary *data = [[NSMutableDictionary alloc]init]; | |
if ([view isKindOfClass:[UITextField class]]) { | |
UITextField *v = (UITextField*)view; | |
[data setObject:v.text forKey:@"Text"]; | |
} else if ([view isKindOfClass:[UIButton class]]) { | |
UIButton *v = (UIButton*)view; | |
//[data setObject:v.titleLabel.text forKey:@"TitleLabel.Text"]; | |
} | |
[data setObject:@"-" forKey:@"Owner:"]; | |
[data setObject:NSStringFromClass([view class]) forKey:@"Type"]; | |
[data setObject:@1 forKey:@"_ScaleX"]; | |
[data setObject:@1 forKey:@"_ScaleY"]; | |
[data setObject:@0 forKey:@"_Visibility"]; | |
BOOL isVisible = !view.hidden; | |
BOOL isViewGroup = [view.subviews count] > 0; | |
BOOL hasBackground = view.backgroundColor != nil; | |
BOOL shouldRender = isVisible && !isViewGroup; | |
[data setObject:@(shouldRender) forKey:@"_RenderViewContent"]; | |
float scale = [UIScreen mainScreen].scale; | |
CGRect bounds = [view convertRect:view.bounds toView:nil]; | |
[data setObject:@(bounds.origin.x * scale) forKey:@"LocationScreenX"]; | |
[data setObject:@(bounds.origin.y * scale) forKey:@"LocationScreenY"]; | |
[data setObject:@(view.bounds.size.width * scale) forKey:@"Width"]; | |
[data setObject:@(view.bounds.size.height * scale) forKey:@"Height"]; | |
return data; | |
} | |
-(void)fillData:(NSMutableDictionary*) data withView:(UIView*) view withLevel:(int) level withPosition:(int*) position { | |
[data setObject:@0 forKey:@"IDi"]; | |
[data setObject:@"" forKey:@"IDs"]; | |
[data setObject:@"" forKey:@"Owner:"]; | |
[data setObject:@(level) forKey:@"Level"]; | |
[data setObject:@(*position) forKey:@"Position"]; | |
[data setObject:[self getData:view] forKey:@"Data"]; | |
if([view.subviews count] > 0){ | |
NSMutableArray* arr = [[NSMutableArray alloc]init]; | |
[data setObject:arr forKey:@"Nodes"]; | |
for (UIView *childView in view.subviews) { | |
NSMutableDictionary *childData = [[NSMutableDictionary alloc]init]; | |
[arr addObject:childData]; | |
(*position)++; | |
[self fillData:childData withView:childView withLevel:level+1 withPosition:position]; | |
} | |
} | |
} | |
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { | |
// Override point for customization after application launch. | |
// Create server | |
_webServer = [[GCDWebServer alloc] init]; | |
// Add a handler to respond to GET requests on any URL | |
[_webServer addDefaultHandlerForMethod:@"GET" | |
requestClass:[GCDWebServerRequest class] | |
processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) { | |
NSString *url = request.URL.absoluteString; | |
NSString *relativePath = [url substringFromIndex:[_webServer.serverURL.absoluteString length]]; | |
NSLog(@"URL %@", relativePath); | |
__block NSData *data = nil; | |
if([relativePath isEqualToString:@"screen/0"]) { | |
// Native Bounds - Detect Screen size in Pixels. | |
return [self runOnMainThread: ^{ | |
CGFloat width = [UIScreen mainScreen].nativeBounds.size.width; | |
CGFloat height = [UIScreen mainScreen].nativeBounds.size.height; | |
UIWindow *keyWindow = [[UIApplication sharedApplication].windows objectAtIndex:0]; | |
CGSize size = CGSizeMake(width, height); | |
UIGraphicsBeginImageContextWithOptions(size, NO, [UIScreen mainScreen].scale); | |
if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) { | |
UIGraphicsBeginImageContextWithOptions(keyWindow.bounds.size, NO, [UIScreen mainScreen].scale); | |
} else { | |
UIGraphicsBeginImageContext(keyWindow.bounds.size); | |
} | |
[keyWindow.layer renderInContext:UIGraphicsGetCurrentContext()]; | |
UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); | |
UIGraphicsEndImageContext; | |
NSData *data = UIImagePNGRepresentation(image); | |
return [GCDWebServerDataResponse responseWithData:data contentType:@"image/png"]; | |
}]; | |
} else if ([relativePath isEqualToString:@"viewhierarchy/0"]) { | |
return [self runOnMainThread: ^{ | |
UIWindow *keyWindow = [[UIApplication sharedApplication].windows objectAtIndex:0]; | |
NSMutableDictionary *dict = [[NSMutableDictionary alloc]init]; | |
int pos = 0; | |
[self fillData:dict withView:keyWindow.rootViewController.view withLevel:0 withPosition:&pos]; | |
NSError* error; | |
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dict | |
options:(NSJSONWritingOptions) (false ? NSJSONWritingPrettyPrinted : 0) | |
error:&error]; | |
NSData *data = jsonData; | |
return [GCDWebServerDataResponse responseWithData:data contentType:@"application/json"]; | |
}]; | |
} else if ([relativePath isEqualToString:@"screens"]) { | |
NSData *data = [@"[\"IOSSample\"]" dataUsingEncoding:NSUTF8StringEncoding]; | |
return [GCDWebServerDataResponse responseWithData:data contentType:@"application/json"]; | |
} else if ([relativePath isEqualToString:@"config"]) { | |
NSMutableDictionary *config = [[NSMutableDictionary alloc]init]; | |
[config setObject:@[@"LayoutInspectorPage",@"TidyTreePage", @"ThreeDPage", @"ScreenshotPage"] forKey:@"Pages"]; | |
[config setObject:@NO forKey:@"Groovy"]; | |
[config setObject:@1 forKey:@"ServerVersion"]; | |
[config setObject:@"#F00" forKey:@"SelectionColor"]; | |
[config setObject:@{ | |
@"MODEL": @"IOS", | |
@"MANUFACTURER": @"Apple", | |
@"API": @1, | |
} forKey:@"Devivce"]; | |
NSError* error; | |
NSData *data = [NSJSONSerialization dataWithJSONObject:config | |
options:(NSJSONWritingOptions) (false ? NSJSONWritingPrettyPrinted : 0) | |
error:&error]; | |
return [GCDWebServerDataResponse responseWithData:data contentType:@"application/json"]; | |
} else if ([relativePath hasPrefix:@"view/0/"]) { | |
return [self runOnMainThread: ^{ | |
NSArray *items = [relativePath componentsSeparatedByString:@"/"]; | |
int position = [[items objectAtIndex:(items.count - 1)] integerValue]; | |
UIWindow *keyWindow = [[UIApplication sharedApplication].windows objectAtIndex:0]; | |
int pos = 0; | |
UIView *view = [self findView:position withRootView:keyWindow.rootViewController.view withPosition:&pos]; | |
UIGraphicsBeginImageContext(CGSizeMake(view.frame.size.width, view.frame.size.height)); | |
[view drawViewHierarchyInRect:CGRectMake(0, 0, view.frame.size.width, view.frame.size.height) afterScreenUpdates:YES]; | |
UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); | |
UIGraphicsEndImageContext(); | |
data = UIImagePNGRepresentation(image); | |
return [GCDWebServerDataResponse responseWithData:data contentType:@"image/png"]; | |
}]; | |
} else { | |
NSData *data = [@"{}" dataUsingEncoding:NSUTF8StringEncoding]; | |
return [GCDWebServerDataResponse responseWithData:data contentType:@"application/json"]; | |
} | |
}]; | |
// Start server on port 8080 | |
[_webServer startWithPort:8081 bonjourName:nil]; | |
NSLog(@"Visit %@ in your web browser", _webServer.serverURL); | |
return YES; | |
} | |
#pragma mark - UISceneSession lifecycle | |
- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options { | |
// Called when a new scene session is being created. | |
// Use this method to select a configuration to create the new scene with. | |
return [[UISceneConfiguration alloc] initWithName:@"Default Configuration" sessionRole:connectingSceneSession.role]; | |
} | |
- (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet<UISceneSession *> *)sceneSessions { | |
// Called when the user discards a scene session. | |
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. | |
// Use this method to release any resources that were specific to the discarded scenes, as they will not return. | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment