├── .gitignore ├── .idea ├── vcs.xml ├── xcode.xml ├── modules.xml ├── misc.xml ├── workspace.xml └── ApplicationManager.iml ├── AppBrowser.xcodeproj ├── project.xcworkspace │ ├── xcuserdata │ │ └── lan.xcuserdatad │ │ │ ├── UserInterfaceState.xcuserstate │ │ │ └── xcschemes │ │ │ └── xcschememanagement.plist │ └── contents.xcworkspacedata ├── xcuserdata │ └── lan.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist ├── xcshareddata │ └── xcschemes │ │ └── AppBrowser.xcscheme └── project.pbxproj ├── AppBrowser ├── Controller │ ├── LANAppListViewController.h │ ├── LANAppViewController.h │ ├── LANProListViewController.h │ ├── LANAppListViewController.m │ ├── LANProListViewController.m │ └── LANAppViewController.m ├── Common │ ├── Category │ │ ├── NSArray+LAN.h │ │ ├── NSDictionary+LAN.h │ │ ├── NSArray+LAN.m │ │ ├── UIView+LAN.h │ │ ├── UIView+LAN.m │ │ └── NSDictionary+LAN.m │ ├── RuntimeInvoker.h │ └── RuntimeInvoker.m ├── View │ ├── LANAppListCell.h │ ├── LANPathDisplayView.h │ ├── LANAppListCell.m │ ├── LANProListCell.h │ ├── LANProListCell.m │ └── LANPathDisplayView.m ├── AppDelegate.h ├── main.m ├── Model │ ├── LANAppHelper.h │ └── LANAppHelper.m ├── Info.plist ├── Base.lproj │ └── LaunchScreen.storyboard ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json └── AppDelegate.m ├── PrefixHeader.pch ├── LANGlobalDefine.h └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | .idea/workspace.xml 3 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/xcode.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /AppBrowser.xcodeproj/project.xcworkspace/xcuserdata/lan.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanvsblue/AppBrowser/HEAD/AppBrowser.xcodeproj/project.xcworkspace/xcuserdata/lan.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /AppBrowser/Controller/LANAppListViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 蓝布鲁 on 2016/11/24. 3 | // Copyright (c) 2016 lanvsblueCO. All rights reserved. 4 | // 5 | 6 | #import 7 | 8 | 9 | @interface LANAppListViewController : UIViewController 10 | @end -------------------------------------------------------------------------------- /AppBrowser.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /AppBrowser/Common/Category/NSArray+LAN.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 蓝布鲁 on 2016/11/29. 3 | // Copyright (c) 2016 lanvsblueCO. All rights reserved. 4 | // 5 | 6 | #import 7 | 8 | @interface NSArray (LAN) 9 | 10 | + (instancetype)getProperties:(Class)cls; 11 | 12 | @end -------------------------------------------------------------------------------- /AppBrowser.xcodeproj/project.xcworkspace/xcuserdata/lan.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /AppBrowser/View/LANAppListCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 蓝布鲁 on 2016/11/24. 3 | // Copyright (c) 2016 lanvsblueCO. All rights reserved. 4 | // 5 | 6 | #import 7 | 8 | 9 | @interface LANAppListCell : UITableViewCell 10 | 11 | @property(nonatomic, retain) id application; 12 | 13 | @end -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /AppBrowser/Controller/LANAppViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // LANAppViewController.h 3 | // AppBrowser 4 | // 5 | // Created by 蓝布鲁 on 2016/11/29. 6 | // Copyright (c) 2016 lanvsblueCO. All rights reserved. 7 | // 8 | 9 | 10 | 11 | @interface LANAppViewController : UIViewController 12 | @property (nonatomic, retain) id application; 13 | @end 14 | -------------------------------------------------------------------------------- /AppBrowser/Common/Category/NSDictionary+LAN.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 蓝布鲁 on 2016/11/29. 3 | // Copyright (c) 2016 lanvsblueCO. All rights reserved. 4 | // 5 | 6 | #import 7 | 8 | #define SUPER_CLASS @"Super Class" 9 | 10 | @interface NSDictionary (LAN) 11 | 12 | + (NSDictionary *)getDictionaryFromObject:(id)obj; 13 | 14 | @end -------------------------------------------------------------------------------- /AppBrowser/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // AppBrowser 4 | // 5 | // Created by 蓝布鲁 on 2016/11/24. 6 | // Copyright (c) 2016 lanvsblueCO. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @interface AppDelegate : UIResponder 13 | 14 | @property (strong, nonatomic) UIWindow *window; 15 | 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /PrefixHeader.pch: -------------------------------------------------------------------------------- 1 | // 2 | // PrefixHeader.pch 3 | // AppBrowser 4 | // 5 | // Created by 蓝布鲁 on 2016/11/24. 6 | // Copyright © 2016年 lanvsblueCO. All rights reserved. 7 | // 8 | 9 | #ifndef PrefixHeader_pch 10 | #define PrefixHeader_pch 11 | 12 | #import "LANGlobalDefine.h" 13 | #import "UIView+LAN.h" 14 | #import "RuntimeInvoker.h" 15 | 16 | 17 | #endif /* PrefixHeader_pch */ 18 | -------------------------------------------------------------------------------- /AppBrowser/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // AppBrowser 4 | // 5 | // Created by 蓝布鲁 on 2016/11/24. 6 | // Copyright (c) 2016 lanvsblueCO. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | 13 | int main(int argc, char * argv[]) { 14 | @autoreleasepool { 15 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /AppBrowser/View/LANPathDisplayView.h: -------------------------------------------------------------------------------- 1 | // 2 | // LANPathDisplayView.h 3 | // AppBrowser 4 | // 5 | // Created by 蓝布鲁 on 2016/11/30. 6 | // Copyright (c) 2016 lanvsblueCO. All rights reserved. 7 | // 8 | 9 | 10 | 11 | @interface LANPathDisplayView : UIView 12 | 13 | @property (nonatomic, retain)NSString *displayPath; 14 | 15 | -(NSString *)setDisplayPath:(NSString *)disPath addPath:(NSString *)addPath; 16 | 17 | -(void)setupView; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /AppBrowser/View/LANAppListCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 蓝布鲁 on 2016/11/24. 3 | // Copyright (c) 2016 lanvsblueCO. All rights reserved. 4 | // 5 | 6 | #import "LANAppListCell.h" 7 | #import "LANAppHelper.h" 8 | 9 | 10 | @implementation LANAppListCell { 11 | 12 | } 13 | 14 | - (void)layoutSubviews { 15 | [super layoutSubviews]; 16 | self.imageView.image = [LANAppHelper iconForApplication:self.application]; 17 | self.textLabel.text = [LANAppHelper nameForApplication:self.application]; 18 | 19 | } 20 | @end -------------------------------------------------------------------------------- /AppBrowser/View/LANProListCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // LANProListCell.h 3 | // AppBrowser 4 | // 5 | // Created by 蓝布鲁 on 2016/11/30. 6 | // Copyright (c) 2016 lanvsblueCO. All rights reserved. 7 | // 8 | 9 | 10 | 11 | @interface LANProListCell : UITableViewCell 12 | @property(nonatomic, retain) NSString *title; 13 | @property(nonatomic, retain) NSString *subTitle; 14 | @property(nonatomic, assign) UITableViewCellAccessoryType type; 15 | @property (nonatomic, assign) NSInteger itemCount; 16 | @property(nonatomic, assign) BOOL isFavorite; 17 | @end 18 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /AppBrowser.xcodeproj/xcuserdata/lan.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | AppBrowser.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 1A199ABA0306E42DA9CC2EFA 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /AppBrowser/Controller/LANProListViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // LANProListViewController.h 3 | // AppBrowser 4 | // 5 | // Created by 蓝布鲁 on 2016/11/29. 6 | // Copyright (c) 2016 lanvsblueCO. All rights reserved. 7 | // 8 | 9 | @class LANPathDisplayView; 10 | typedef NS_ENUM(NSInteger,LANPropertiesType) { 11 | LANPropertiesTypeArray = 1, 12 | LANPropertiesTypeDictionary, 13 | LANPropertiesTypeKeyDict, 14 | LANPropertiesTypeValue 15 | }; 16 | 17 | typedef void (^LANItemInfoFetchBlock)(UITableViewCellAccessoryType accessoryType, NSString *title, NSString *subtitle); 18 | 19 | 20 | @interface LANProListViewController : UIViewController 21 | 22 | -(id)initWithProperties:(id)properties; 23 | 24 | @property (nonatomic, retain)LANPathDisplayView *pathDisplayView; 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /AppBrowser/Model/LANAppHelper.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 蓝布鲁 on 2016/11/24. 3 | // Copyright (c) 2016 lanvsblueCO. All rights reserved. 4 | // 5 | 6 | #import 7 | 8 | 9 | @interface LANAppHelper : NSObject 10 | 11 | // operate 12 | +(id)defaultWorkspace; 13 | 14 | +(id)allInstalledApplications; 15 | 16 | +(BOOL)openApplication:(id)application; 17 | 18 | +(BOOL)removeApplication:(id)application; 19 | 20 | 21 | // get app info 22 | +(id)nameForApplication:(id)application; 23 | 24 | +(id)iconForApplication:(id)application; 25 | 26 | +(id)vendorNameForApplication:(id)application; 27 | 28 | +(id)appTypeForApplication:(id)application; 29 | 30 | +(id)bundleIDForApplication:(id)application; 31 | 32 | +(NSDictionary *)infoForApplication:(id)application; 33 | 34 | @end -------------------------------------------------------------------------------- /LANGlobalDefine.h: -------------------------------------------------------------------------------- 1 | // 2 | // LANGlobalDefine.h 3 | // AppBrowser 4 | // 5 | // Created by 蓝布鲁 on 2016/11/24. 6 | // Copyright (c) 2016 lanvsblueCO. All rights reserved. 7 | // 8 | 9 | #ifndef LANGlobalDefine_h 10 | #define LANGlobalDefine_h 11 | 12 | //screen define 13 | #define SCREEN_BOUNDS [UIScreen mainScreen].bounds 14 | #define SCREEN_WIDTH [UIScreen mainScreen].bounds.size.width 15 | #define SCREEN_HEIGHT [UIScreen mainScreen].bounds.size.height 16 | 17 | //const 18 | #define APP_NAME_KEY_PATH @"_infoDictionary.propertyList.CFBundleDisplayName" 19 | #define APP_SHORT_NAME_KEY_PATH @"localizedShortName" 20 | #define APP_BUNDLE_ID_KEY_PATH @"appState.bundleIdentifier" 21 | #define APP_PROPERTY_LIST_KEY_PATH @"_infoDictionary.propertyList" 22 | 23 | #endif /* LANGlobalDefine_h */ 24 | -------------------------------------------------------------------------------- /AppBrowser/Common/Category/NSArray+LAN.m: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 蓝布鲁 on 2016/11/29. 3 | // Copyright (c) 2016 lanvsblueCO. All rights reserved. 4 | // 5 | 6 | #import "NSArray+LAN.h" 7 | #import // 导入运行时文件 8 | @implementation NSArray (Extension) 9 | 10 | //返回当前类的所有属性 11 | + (instancetype)getProperties:(Class)cls{ 12 | 13 | // 获取当前类的所有属性 14 | unsigned int count;// 记录属性个数 15 | objc_property_t *properties = class_copyPropertyList(cls, &count); 16 | // 遍历 17 | NSMutableArray *mArray = [NSMutableArray array]; 18 | for (int i = 0; i < count; i++) { 19 | 20 | // An opaque type that represents an Objective-C declared property. 21 | // objc_property_t 属性类型 22 | objc_property_t property = properties[i]; 23 | // 获取属性的名称 C语言字符串 24 | const char *cName = property_getName(property); 25 | // 转换为Objective C 字符串 26 | NSString *name = [NSString stringWithCString:cName encoding:NSUTF8StringEncoding]; 27 | [mArray addObject:name]; 28 | } 29 | 30 | return mArray.copy; 31 | } 32 | 33 | 34 | @end -------------------------------------------------------------------------------- /AppBrowser/View/LANProListCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // LANProListCell.m 3 | // AppBrowser 4 | // 5 | // Created by 蓝布鲁 on 2016/11/30. 6 | // Copyright (c) 2016 lanvsblueCO. All rights reserved. 7 | // 8 | 9 | #import "LANProListCell.h" 10 | #import "NSDictionary+LAN.h" 11 | 12 | @implementation LANProListCell 13 | 14 | - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { 15 | if (self=[super initWithStyle:style reuseIdentifier:reuseIdentifier]){ 16 | [self initView]; 17 | } 18 | return self; 19 | } 20 | 21 | -(void)initView{ 22 | 23 | } 24 | 25 | -(void)layoutSubviews { 26 | [super layoutSubviews]; 27 | if([self.title isEqualToString:SUPER_CLASS]){ 28 | self.textLabel.font = [UIFont boldSystemFontOfSize:17]; 29 | } 30 | self.textLabel.text = self.title; 31 | self.detailTextLabel.text = self.subTitle; 32 | self.accessoryType = self.type; 33 | } 34 | 35 | - (void)copy:(id)sender { 36 | [UIPasteboard generalPasteboard].string = [NSString stringWithFormat:@"%@ | %@",self.title,self.subTitle]; 37 | } 38 | 39 | //-(void)favoriteItem:(id)sender{ 40 | // NSLog(@"favoriteItem"); 41 | //} 42 | // 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /AppBrowser/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | AppBrowser 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /AppBrowser/Common/Category/UIView+LAN.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 蓝布鲁 on 16/7/16. 3 | // Copyright (c) 2016 lanvsblue. All rights reserved. 4 | // 5 | 6 | #import 7 | 8 | @interface UIView (LAN) 9 | 10 | /* 11 | * @brief 视图左侧X轴坐标 12 | * getters: UIView.frame.origin.x 13 | * setters: UIView.frame.origin.x = originX 14 | */ 15 | @property (nonatomic, assign) CGFloat originX; 16 | 17 | /* 18 | * @brief 视图顶部Y轴坐标 19 | * getters: UIView.frame.origin.y 20 | * setters: UIView.frame.origin.y = originY 21 | */ 22 | @property (nonatomic, assign) CGFloat originY; 23 | 24 | /* 25 | * @brief 视图右侧X轴坐标 26 | * getters: UIView.frame.origin.x + UIView.frame.size.width 27 | * setters: UIView.frame.origin.x = rightX - UIView.frame.size.width 28 | */ 29 | @property (nonatomic, assign) CGFloat rightX; 30 | 31 | /* 32 | * @brief 视图下方Y轴坐标 33 | * getters: UIView.frame.origin.y + UIView.frame.size.height 34 | * setters: UIView.frame.origin.y = bottomY - UIView.frame.size.height 35 | */ 36 | @property (nonatomic, assign) CGFloat bottomY; 37 | 38 | /* 39 | * @brief 视图高度 40 | * getters: UIView.frame.size.height 41 | * setters: UIView.frame.size.height = height 42 | */ 43 | @property (nonatomic, assign) CGFloat height; 44 | 45 | /* 46 | * @brief 视图宽度 47 | * getters: UIView.frame.size.width 48 | * setters: UIView.frame.size.width = width 49 | */ 50 | 51 | 52 | @property (nonatomic, assign)CGFloat width; 53 | 54 | /* 55 | * 获取当前view所在的viewController 56 | */ 57 | @property (nonatomic, readonly) UIViewController *viewController; 58 | 59 | 60 | /* 61 | * 移除所有的子View 62 | */ 63 | - (void)removeAllSubviews; 64 | 65 | /* 66 | * 移除数组中所有的子View 67 | */ 68 | -(void)removeSubViews:(NSArray *)views; 69 | 70 | 71 | 72 | /* 73 | * 不响应父类的事件 74 | */ 75 | -(void)noActionForSuperEvent; 76 | 77 | @end -------------------------------------------------------------------------------- /AppBrowser/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /AppBrowser/View/LANPathDisplayView.m: -------------------------------------------------------------------------------- 1 | // 2 | // LANPathDisplayView.m 3 | // AppBrowser 4 | // 5 | // Created by 蓝布鲁 on 2016/11/30. 6 | // Copyright (c) 2016 lanvsblueCO. All rights reserved. 7 | // 8 | 9 | #import "LANPathDisplayView.h" 10 | 11 | @interface LANPathDisplayView() 12 | 13 | @property (nonatomic, retain)UILabel *pathLabel; 14 | @end 15 | 16 | @implementation LANPathDisplayView{ 17 | NSMutableArray *_pathArray; 18 | } 19 | 20 | - (instancetype)initWithFrame:(CGRect)frame { 21 | if(self=[super initWithFrame:frame]){ 22 | [self initView]; 23 | _pathArray = [[NSMutableArray alloc] init]; 24 | } 25 | return self; 26 | } 27 | 28 | -(void)initView{ 29 | self.backgroundColor = [UIColor grayColor]; 30 | 31 | self.pathLabel = [[UILabel alloc] initWithFrame:CGRectMake(5,0,self.width-5,self.height)]; 32 | [self addSubview:self.pathLabel]; 33 | } 34 | 35 | -(void)setupView { 36 | self.pathLabel.text = self.displayPath; 37 | self.pathLabel.font = [UIFont systemFontOfSize:12]; 38 | self.pathLabel.textColor = [UIColor whiteColor]; 39 | self.pathLabel.lineBreakMode = NSLineBreakByTruncatingHead; 40 | } 41 | 42 | - (void)setDisplayPath:(NSString *)displayPath { 43 | _pathArray = [[displayPath componentsSeparatedByString:@"."] mutableCopy]; 44 | } 45 | 46 | - (NSString *)setDisplayPath:(NSString *)disPath addPath:(NSString *)addPath { 47 | self.displayPath = disPath; 48 | [self addPath:addPath]; 49 | return self.displayPath; 50 | } 51 | 52 | 53 | -(NSString *)displayPath { 54 | return [_pathArray componentsJoinedByString:@"."]; 55 | } 56 | 57 | - (NSString *)addPath:(NSString *)path { 58 | if([path hasPrefix:@"Item "]){ 59 | _pathArray[_pathArray.count-1] = [NSString stringWithFormat:@"%@[%@]",_pathArray[_pathArray.count-1],[path substringFromIndex:5]]; 60 | } else{ 61 | [_pathArray addObject:path]; 62 | } 63 | return self.displayPath; 64 | } 65 | 66 | 67 | @end 68 | -------------------------------------------------------------------------------- /AppBrowser/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "60x60", 35 | "idiom" : "iphone", 36 | "filename" : "icon@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "60x60", 41 | "idiom" : "iphone", 42 | "filename" : "icon@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "idiom" : "ipad", 47 | "size" : "20x20", 48 | "scale" : "1x" 49 | }, 50 | { 51 | "idiom" : "ipad", 52 | "size" : "20x20", 53 | "scale" : "2x" 54 | }, 55 | { 56 | "idiom" : "ipad", 57 | "size" : "29x29", 58 | "scale" : "1x" 59 | }, 60 | { 61 | "idiom" : "ipad", 62 | "size" : "29x29", 63 | "scale" : "2x" 64 | }, 65 | { 66 | "idiom" : "ipad", 67 | "size" : "40x40", 68 | "scale" : "1x" 69 | }, 70 | { 71 | "idiom" : "ipad", 72 | "size" : "40x40", 73 | "scale" : "2x" 74 | }, 75 | { 76 | "idiom" : "ipad", 77 | "size" : "76x76", 78 | "scale" : "1x" 79 | }, 80 | { 81 | "idiom" : "ipad", 82 | "size" : "76x76", 83 | "scale" : "2x" 84 | }, 85 | { 86 | "idiom" : "ipad", 87 | "size" : "83.5x83.5", 88 | "scale" : "2x" 89 | } 90 | ], 91 | "info" : { 92 | "version" : 1, 93 | "author" : "xcode" 94 | } 95 | } -------------------------------------------------------------------------------- /AppBrowser/Model/LANAppHelper.m: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 蓝布鲁 on 2016/11/24. 3 | // Copyright (c) 2016 lanvsblueCO. All rights reserved. 4 | // 5 | 6 | #import "LANAppHelper.h" 7 | #import "NSArray+LAN.h" 8 | #import "NSDictionary+LAN.h" 9 | 10 | 11 | @implementation LANAppHelper { 12 | 13 | } 14 | + (id)defaultWorkspace { 15 | return [@"LSApplicationWorkspace" invokeClassMethod:@"defaultWorkspace"]; 16 | } 17 | 18 | + (id)allInstalledApplications { 19 | return [[self defaultWorkspace] invoke:@"allInstalledApplications"]; 20 | } 21 | 22 | + (BOOL)openApplication:(id)application { 23 | return [[self defaultWorkspace] invoke:@"openApplicationWithBundleID:" args:[self bundleIdentifierForApplication:application],nil]; 24 | } 25 | 26 | + (BOOL)removeApplication:(id)application { 27 | 28 | #if TARGET_IPHONE_SIMULATOR 29 | return [[self defaultWorkspace] invoke:@"uninstallApplication:withOptions:" args:[application bundleIdentifier],nil,nil]; 30 | #elif TARGET_OS_IPHONE//真机 31 | return false; 32 | #endif 33 | 34 | } 35 | 36 | 37 | + (id)nameForApplication:(id)application { 38 | return [([application valueForKeyPath:APP_NAME_KEY_PATH] ?: [application valueForKeyPath:APP_SHORT_NAME_KEY_PATH]) description]; 39 | } 40 | 41 | +(id)bundleIdentifierForApplication:(id)application{ 42 | return [application valueForKey:@"bundleIdentifier"]; 43 | } 44 | 45 | + (id)iconForApplication:(id)application { 46 | return [UIImage invoke:@"_applicationIconImageForBundleIdentifier:format:scale:" 47 | args:[application bundleIdentifier],@"",@([UIScreen mainScreen].scale),nil]; 48 | } 49 | 50 | + (id)vendorNameForApplication:(id)application { 51 | return [[self appTypeForApplication:application] isEqualToString:@"System"]? @"Apple":[application valueForKey:@"vendorName"]; 52 | } 53 | 54 | + (id)appTypeForApplication:(id)application { 55 | return [application valueForKey:@"applicationType"]; 56 | } 57 | 58 | + (id)bundleIDForApplication:(id)application { 59 | return [application valueForKeyPath:APP_BUNDLE_ID_KEY_PATH]; 60 | } 61 | 62 | 63 | +(NSDictionary *)infoForApplication:(id)application{ 64 | return [NSDictionary getDictionaryFromObject:application]; 65 | } 66 | 67 | 68 | 69 | @end 70 | -------------------------------------------------------------------------------- /AppBrowser/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // AppBrowser 4 | // 5 | // Created by 蓝布鲁 on 2016/11/24. 6 | // Copyright (c) 2016 lanvsblueCO. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "LANAppListViewController.h" 11 | 12 | 13 | @interface AppDelegate () 14 | 15 | @end 16 | 17 | @implementation AppDelegate 18 | 19 | 20 | 21 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 22 | self.window = [[UIWindow alloc] initWithFrame:SCREEN_BOUNDS]; 23 | 24 | LANAppListViewController *viewController = [[LANAppListViewController alloc] init]; 25 | UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewController]; 26 | 27 | self.window.rootViewController = navigationController; 28 | [self.window makeKeyAndVisible]; 29 | return YES; 30 | } 31 | 32 | 33 | - (void)applicationWillResignActive:(UIApplication *)application { 34 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 35 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 36 | 37 | } 38 | 39 | 40 | - (void)applicationDidEnterBackground:(UIApplication *)application { 41 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 42 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 43 | 44 | } 45 | 46 | 47 | - (void)applicationWillEnterForeground:(UIApplication *)application { 48 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 49 | } 50 | 51 | 52 | - (void)applicationDidBecomeActive:(UIApplication *)application { 53 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 54 | } 55 | 56 | 57 | - (void)applicationWillTerminate:(UIApplication *)application { 58 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 59 | } 60 | 61 | 62 | @end 63 | -------------------------------------------------------------------------------- /AppBrowser/Common/RuntimeInvoker.h: -------------------------------------------------------------------------------- 1 | // 2 | // RuntimeInvoker.h 3 | // RuntimeInvoker 4 | // 5 | // Created by cyan on 16/5/27. 6 | // Copyright © 2016年 cyan. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSObject (RuntimeInvoker) 12 | 13 | /** 14 | * Invoke a selector with name 15 | * 16 | * @param selector Selector name 17 | * 18 | * @return Return value 19 | */ 20 | - (id)invoke:(NSString *)selector; 21 | 22 | /** 23 | * Invoke a selector with name and args 24 | * 25 | * @param selector Selector name 26 | * @param arg Arguments list (end with nil) 27 | * 28 | * @return Return value 29 | */ 30 | - (id)invoke:(NSString *)selector args:(id)arg, ... ; 31 | 32 | /** 33 | * Invoke a selector with name and args 34 | * 35 | * @param selector Selector name 36 | * @param arguments Arguments list 37 | * 38 | * @return Return value 39 | */ 40 | - (id)invoke:(NSString *)selector arguments:(NSArray *)arguments; 41 | 42 | /** 43 | * Invoke a selector with name (Class Method) 44 | * 45 | * @param selector Selector name 46 | * 47 | * @return Return value 48 | */ 49 | + (id)invoke:(NSString *)selector; 50 | 51 | /** 52 | * Invoke a selector with name and args (Class Method) 53 | * 54 | * @param selector Selector name 55 | * @param arg Arguments list (end with nil) 56 | * 57 | * @return Return value 58 | */ 59 | + (id)invoke:(NSString *)selector args:(id)arg, ... ; 60 | 61 | /** 62 | * Invoke a selector with name and args (Class Method) 63 | * 64 | * @param selector Selector name 65 | * @param arguments Arguments list 66 | * 67 | * @return Return value 68 | */ 69 | + (id)invoke:(NSString *)selector arguments:(NSArray *)arguments; 70 | 71 | @end 72 | 73 | 74 | /** 75 | NSString Category for Class Method 76 | */ 77 | @interface NSString (RuntimeInvoker) 78 | 79 | /** 80 | Invoke class method with NSString 81 | 82 | @param selector Selector name 83 | @return Return value 84 | */ 85 | - (id)invokeClassMethod:(NSString *)selector; 86 | 87 | 88 | /** 89 | Invoke class method with NSString 90 | 91 | @param selector Selector name 92 | @param arg Arguments list (end with nil) 93 | @return Return value 94 | */ 95 | - (id)invokeClassMethod:(NSString *)selector args:(id)arg, ... ; 96 | 97 | 98 | /** 99 | Invoke class method with NSString 100 | 101 | @param selector Selector name 102 | @param arguments Arguments list 103 | @return Return value 104 | */ 105 | - (id)invokeClassMethod:(NSString *)selector arguments:(NSArray *)arguments; 106 | 107 | @end 108 | -------------------------------------------------------------------------------- /AppBrowser/Common/Category/UIView+LAN.m: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 蓝布鲁 on 16/7/16. 3 | // Copyright (c) 2016 lanvsblue. All rights reserved. 4 | // 5 | 6 | #import 7 | #import "UIView+LAN.h" 8 | 9 | 10 | 11 | 12 | @implementation UIView (LAN) 13 | 14 | - (CGFloat)originX { 15 | return self.frame.origin.x; 16 | } 17 | 18 | - (void)setOriginX:(CGFloat)originX { 19 | CGRect frame = self.frame; 20 | frame.origin.x = originX; 21 | self.frame = frame; 22 | } 23 | 24 | - (CGFloat)originY { 25 | return self.frame.origin.y; 26 | } 27 | 28 | - (void)setOriginY:(CGFloat)originY { 29 | CGRect frame = self.frame; 30 | frame.origin.y = originY; 31 | self.frame = frame; 32 | } 33 | 34 | - (CGFloat)rightX { 35 | return self.frame.origin.x + self.frame.size.width; 36 | } 37 | 38 | - (void)setRightX:(CGFloat)rightX { 39 | CGRect frame = self.frame; 40 | frame.origin.x = rightX - self.frame.size.width; 41 | self.frame = frame; 42 | } 43 | 44 | - (CGFloat)bottomY { 45 | return self.frame.origin.y + self.frame.size.height; 46 | } 47 | 48 | - (void)setBottomY:(CGFloat)bottomY { 49 | CGRect frame = self.frame; 50 | frame.origin.y = bottomY - self.frame.size.height; 51 | self.frame = frame; 52 | } 53 | 54 | - (CGFloat)height { 55 | return self.frame.size.height; 56 | } 57 | 58 | - (void)setHeight:(CGFloat)height { 59 | CGRect frame = self.frame; 60 | frame.size.width = height; 61 | self.frame = frame; 62 | } 63 | 64 | - (CGFloat)width { 65 | return self.frame.size.width; 66 | } 67 | 68 | - (void)setWidth:(CGFloat)width { 69 | CGRect frame = self.frame; 70 | frame.size.width = width; 71 | self.frame = frame; 72 | } 73 | 74 | - (UIViewController *)viewController { 75 | for (UIView* next = [self superview]; next; next = next.superview) { 76 | UIResponder *nextResponder = [next nextResponder]; 77 | if ([nextResponder isKindOfClass:[UIViewController class]]) { 78 | return (UIViewController *)nextResponder; 79 | } 80 | } 81 | return nil; 82 | } 83 | 84 | - (void)removeAllSubviews { 85 | while (self.subviews.count) { 86 | UIView* child = self.subviews.lastObject; 87 | [child removeFromSuperview]; 88 | } 89 | } 90 | 91 | -(void)removeSubViews:(NSArray *)views{ 92 | for (UIView *view in views) { 93 | [view removeFromSuperview]; 94 | } 95 | } 96 | 97 | - (void)noActionForSuperEvent { 98 | UITapGestureRecognizer *forbidSuperGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:nil]; 99 | [self addGestureRecognizer:forbidSuperGesture]; 100 | } 101 | 102 | 103 | @end -------------------------------------------------------------------------------- /AppBrowser/Common/Category/NSDictionary+LAN.m: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 蓝布鲁 on 2016/11/29. 3 | // Copyright (c) 2016 lanvsblueCO. All rights reserved. 4 | // 5 | 6 | #import "NSDictionary+LAN.h" 7 | #import "NSArray+LAN.h" 8 | 9 | 10 | @implementation NSDictionary (LAN) 11 | + (NSDictionary *)getDictionaryFromObject:(id)obj{ 12 | NSMutableArray *superObjDic = [[NSMutableArray alloc] init]; 13 | return [self getDictionary:obj objDic:superObjDic convertClass:[obj class]]; 14 | } 15 | 16 | +(id)getDictionary:(id)obj objDic:(NSMutableArray *)superObjDic convertClass:(Class)convertClass{ 17 | 18 | if ([obj isKindOfClass:[NSArray class]]) { 19 | NSMutableArray *subObj = [NSMutableArray array]; 20 | for (id o in obj) { 21 | [subObj addObject:[self getDictionary:o objDic:superObjDic convertClass:[o class]]]; 22 | } 23 | return subObj; 24 | } else if ([obj isKindOfClass:[NSDictionary class]]) { 25 | NSMutableDictionary *subObj = [NSMutableDictionary dictionary]; 26 | for (id o in [obj allKeys]) { 27 | subObj[o] = [self getDictionary:obj[o] objDic:superObjDic convertClass:[obj[o] class]]; 28 | } 29 | return subObj; 30 | } else if ([obj isKindOfClass:[NSURL class]]){ 31 | return [obj absoluteString]; 32 | } else if ([obj isKindOfClass:[NSString class]]) { 33 | return obj; 34 | } else if ([obj isKindOfClass:[NSDate class]]) { 35 | return [obj description]; 36 | } else if ([obj isKindOfClass:[NSNumber class]]) { 37 | return obj; 38 | } else if ([obj isKindOfClass:[NSUUID class]]) { 39 | return [obj UUIDString]; 40 | } else if ([[obj class] isSubclassOfClass:[NSObject class]] && ![obj isKindOfClass:NSClassFromString(@"OS_object")]) { 41 | //is analysis 42 | NSInteger index = [superObjDic indexOfObject:obj]; 43 | if(index != NSNotFound&& [superObjDic[index] class]==convertClass){//if index found and class same 44 | return @{@"Command <<<":@(index)}; 45 | } else { 46 | [superObjDic addObject:obj]; 47 | } 48 | 49 | NSMutableDictionary *info = [[NSMutableDictionary alloc] init]; 50 | 51 | //get all keys 52 | NSArray *allkeys = [NSArray getProperties:convertClass]; 53 | for (NSString *key in allkeys) { 54 | //get value 55 | id value = [obj valueForKey:key]; 56 | 57 | //show class name 58 | NSString *displayKey = [NSString stringWithFormat:@"%@ : %@",key, [value class]]; 59 | info[key] = [self getDictionary:value objDic:superObjDic convertClass:[value class]]; 60 | } 61 | 62 | //get super class info 63 | Class objSuperClass = [convertClass superclass]; 64 | if(objSuperClass!=[NSObject class]){ 65 | NSString *displayKey = [NSString stringWithFormat:@"%@ : %@",SUPER_CLASS, objSuperClass]; 66 | info[SUPER_CLASS] = [self getDictionary:obj objDic:superObjDic convertClass:objSuperClass]; 67 | } 68 | 69 | 70 | return info; 71 | } 72 | return nil; 73 | } 74 | 75 | @end -------------------------------------------------------------------------------- /AppBrowser.xcodeproj/xcshareddata/xcschemes/AppBrowser.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AppBrowser(Application属性查看器,不需要越狱!!!) 2 | 3 | 不需要越狱,调用私有方法 --- 获取完整的已安装应用列表、打开和删除应用操作、应用运行时相关信息的查看。 4 | 5 | 支持iOS10.X 6 | 7 | ## 注意 8 | 9 | 目前AppBrowser不支持iOS11应用查看, 由于iOS11目前还处在Beta版, 系统API还没有稳定下来。等到[Private Header](https://github.com/nst/iOS-Runtime-Headers)更新了iOS11版本,我也会进行更新。 10 | 11 | ## 功能 12 | - [x] 已安装的应用列表 13 | - [x] 应用的详情界面 (打开应用,删除应用,应用的相关信息展示) 14 | - [x] 应用运行时信息展示(LSApplicationProxy) 15 | - [ ] 定制喜欢的字段,展示在应用详情界面 16 | 17 | ## 介绍 18 | 19 | #### 所有已安装应用列表(应用icon+应用名) 20 | 21 | > 为了提供思路,这里只用伪代码,具体的私有代码调用请查看:`AppBrowser/AppBrowser/Model/LANAppHelper.m` 22 | 23 | 获取应用实例: 24 | 25 | ```objc 26 | //首先获取 LSApplicationWorkspace 实例 27 | //对应于LANAppHelper类中的+(id)defaultWorkspace;方法: 28 | id applicationWorkspace = [LSApplicationWorkspace defaultWorkspace]; 29 | 30 | //使用 LSApplicationWorkspace 获取应用列表(LSApplicationProxy对象列表) 31 | //对应于LANAppHelper类中的+(id)allInstalledApplications;方法: 32 | NSArray applicationArray = [applicationWorkspace allInstalledApplications]; 33 | 34 | //取出第一个应用对象 35 | id application = applicationArray[0]; 36 | ``` 37 | 38 | 获取应用名和应用的icon: 39 | ```objc 40 | /* 41 | * APP_NAME_KEY_PATH 和 APP_SHORT_NAME_KEY_PATH 的定义在代码头上 42 | * 应用的名字有可能出现在两个地方: 43 | * 在桌面上显示的普通应用的应用名来自info.plist文件中的CFBundleDisplayName字段 44 | * 在桌面的部分系统应用显示的是localizedShortName 45 | * 对应于LANAppHelper类中的+(id)nameForApplication:(id)application;方法: 46 | */ 47 | 48 | #define APP_NAME_KEY_PATH @"_infoDictionary.propertyList.CFBundleDisplayName" 49 | #define APP_SHORT_NAME_KEY_PATH @"localizedShortName" 50 | 51 | NSString *applicationName = [application valueForKeyPath:APP_NAME_KEY_PATH] ?: 52 | [application valueForKeyPath:APP_SHORT_NAME_KEY_PATH]; 53 | 54 | /* 55 | * 应用的图片可以调用UIImage的私用方法:_applicationIconImageForBundleIdentifier:format:scale: 56 | * 传入BundleID,格式,缩放大小 57 | * 对应于LANAppHelper类中的+(id)iconForApplication:(id)application;方法: 58 | */ 59 | UIImage *applicationImage = [UIImage _applicationIconImageForBundleIdentifier:[application bundleIdentifier] 60 | format:@"" 61 | scale:@([UIScreen mainScreen].scale)]; 62 | ``` 63 | 应用列表界面展示: 64 | 65 | ![应用列表](http://o9gma3fh0.bkt.clouddn.com/2016/12/AppBrowser/Installed%20app%201.png) 66 | 67 | #### 应用运行时详情 68 | 69 | 打开应用: 70 | ```objc 71 | //对应于LANAppHelper类中的+ (BOOL)openApplication:(id)application方法: 72 | [applicationWorkspace openApplicationWithBundleID:[application bundleIdentifier]]; 73 | ``` 74 | 75 | 卸载应用: 76 | ```objc 77 | //对应于LANAppHelper类中的+ (BOOL)removeApplication:(id)application方法: 78 | [applicationWorkspace uninstallApplication:[application bundleIdentifier] withOptions:nil]; 79 | ``` 80 | 81 | 获取info.plist文件: 82 | ```objc 83 | //info.plist文件实例化以后就是_infoDictionary属性,位置在[LSApplicationProxy superClass],也就是在LSBundleProxy类中 84 | #define APP_PROPERTY_LIST_KEY_PATH @"_infoDictionary.propertyList" 85 | ``` 86 | 应用运行时详情界面展示: 87 | 88 | ![应用运行时详情](http://o9gma3fh0.bkt.clouddn.com/2016/12/AppBrowser/app%20info%201.png) 89 | 90 | * 右上角,从左往右第一个按钮用来打开应用;第二个按钮用来卸载这个应用 91 | * INFO按钮用来解析并显示出对应的LSApplicationProxy类 92 | 93 | #### 树形展示LSApplicationProxy类 94 | 通过算法,将LSApplicationProxy类,转换成了字典。 95 | 96 | 转换规则是:属性名为key,属性值为value,如果value是一个可解析的类(除了NSString,NSNumber...等等)或者是个数组或字典,则继续递归解析。 97 | 并且会找到superClass的属性并解析,superClass如果也符合解析原则,也会进入递归解析。 98 | 99 | 具体算法可以查看 LANAppHelper.m文件中的 100 | ```objc 101 | +(NSDictionary *)infoForApplication:(id)application; 102 | ``` 103 | ![解析LSApplicationProxy类](http://o9gma3fh0.bkt.clouddn.com/2016/12/AppBrowser/LSApplicationProxy%201.png) 104 | 105 | ## 功能演示 106 | 107 | #### 已安装的应用列表 108 | ![已安装的应用列表](http://o9gma3fh0.bkt.clouddn.com/2016/12/AppBrowser/installed%20app-squashed1.gif) 109 | 110 | #### 应用详情页 111 | ![应用详情页](http://o9gma3fh0.bkt.clouddn.com/2016/12/AppBrowser/app%20info-squashed1.gif) 112 | 113 | #### 打开应用 114 | ![打开应用](http://o9gma3fh0.bkt.clouddn.com/2016/12/AppBrowser/open%20app-squashed1.gif) 115 | 116 | #### 卸载应用 117 | ![卸载应用](http://o9gma3fh0.bkt.clouddn.com/2016/12/AppBrowser/uninstall%20app-squashed1.gif) 118 | 119 | #### 应用属性列表 120 | ![应用属性列表](http://o9gma3fh0.bkt.clouddn.com/2016/12/AppBrowser/LSApplicationProxy-squashed1.gif) 121 | 122 | ## 参考及引用 123 | * [iOS-Runtime-Headers](https://github.com/nst/iOS-Runtime-Headers) 124 | * [Retriever](https://github.com/cyanzhong/Retriever) 125 | * [RuntimeInvoker](https://github.com/cyanzhong/RuntimeInvoker) 126 | -------------------------------------------------------------------------------- /AppBrowser/Controller/LANAppListViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 蓝布鲁 on 2016/11/24. 3 | // Copyright (c) 2016 lanvsblueCO. All rights reserved. 4 | // 5 | 6 | #import "LANAppListViewController.h" 7 | #import "LANAppHelper.h" 8 | #import "LANAppListCell.h" 9 | #import "LANAppViewController.h" 10 | #import "NSArray+LAN.h" 11 | 12 | @interface LANAppListViewController() 13 | 14 | @property (nonatomic, retain)UITableView *tableView; 15 | @property (nonatomic, retain)UISearchController *searchController; 16 | 17 | @end 18 | 19 | @implementation LANAppListViewController { 20 | NSArray *_installedAppArray; 21 | NSMutableArray *_list; 22 | } 23 | 24 | -(void)viewWillAppear:(BOOL)animated { 25 | [super viewWillAppear:animated]; 26 | 27 | [self refresh]; 28 | } 29 | 30 | - (void)viewDidLoad { 31 | [super viewDidLoad]; 32 | self.title = @"Installed App(0)"; 33 | 34 | //setup view in controller 35 | [self setupView]; 36 | 37 | //get data & refresh tableView 38 | [self refresh]; 39 | } 40 | 41 | -(void)setupView{ 42 | 43 | //init tableView 44 | self.tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain]; 45 | self.tableView.delegate = self; 46 | self.tableView.dataSource = self; 47 | [self.view addSubview:self.tableView]; 48 | 49 | //init searchController 50 | self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil]; 51 | self.searchController.searchResultsUpdater = self; 52 | self.searchController.dimsBackgroundDuringPresentation = false; 53 | self.tableView.tableHeaderView = self.searchController.searchBar; 54 | 55 | //init refreshControl 56 | UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init]; 57 | refreshControl.backgroundColor = [UIColor groupTableViewBackgroundColor]; 58 | [refreshControl addTarget:self 59 | action:@selector(didRefreshControlValueChanged:) 60 | forControlEvents:UIControlEventValueChanged]; 61 | [self.tableView addSubview:refreshControl]; 62 | 63 | 64 | } 65 | 66 | -(void)refresh{ 67 | _installedAppArray = [[LANAppHelper allInstalledApplications] sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) { 68 | NSString *name1 = [LANAppHelper nameForApplication:obj1]; 69 | NSString *name2 = [LANAppHelper nameForApplication:obj2]; 70 | return [name1 compare:name2 options:NSCaseInsensitiveSearch]; 71 | }]; 72 | _list = [_installedAppArray mutableCopy]; 73 | 74 | self.title = [NSString stringWithFormat:@"Installed App(%d)",_installedAppArray.count]; 75 | 76 | [self.tableView reloadData]; 77 | } 78 | 79 | - (void)didRefreshControlValueChanged:(UIRefreshControl *)sender { 80 | [self refresh]; 81 | [sender performSelector:@selector(endRefreshing) withObject:nil afterDelay:1.5]; 82 | } 83 | 84 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 85 | return _list.count; 86 | } 87 | 88 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 89 | LANAppListCell *cell = [tableView cellForRowAtIndexPath:indexPath]; 90 | if (cell==nil){ 91 | cell = [[LANAppListCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cellID"]; 92 | cell.application = _list[indexPath.row]; 93 | } 94 | return cell; 95 | } 96 | 97 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 98 | [tableView deselectRowAtIndexPath:indexPath animated:true]; 99 | NSObject *application = _list[indexPath.row]; 100 | 101 | LANAppViewController *appViewController = [[LANAppViewController alloc] init]; 102 | appViewController.application = application; 103 | self.searchController.active = NO; 104 | self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Installed App" style:UIBarButtonItemStylePlain target:nil action:nil]; 105 | [self.navigationController pushViewController:appViewController animated:true]; 106 | 107 | // NSLog(@"class name:%@,properties:%@",NSStringFromClass([application class]),[NSArray getProperties:[application class]]); 108 | // NSLog(@"class name:%@,properties:%@",NSStringFromClass([application superclass]),[NSArray getProperties:[application superclass]]); 109 | // NSLog(@"class name:%@,properties:%@",NSStringFromClass([[application superclass] superclass]),[NSArray getProperties:[[application superclass] superclass]]); 110 | } 111 | 112 | - (void)updateSearchResultsForSearchController:(UISearchController *)searchController { 113 | _list = [[NSMutableArray alloc] init]; 114 | NSString *searchText = searchController.searchBar.text.lowercaseString; 115 | if(searchText.length==0){ 116 | _list = [_installedAppArray mutableCopy]; 117 | [self.tableView reloadData]; 118 | } else{ 119 | for (id application in _installedAppArray) { 120 | NSString *appName = [LANAppHelper nameForApplication:application]; 121 | if([appName.lowercaseString containsString:searchText]){ 122 | [_list addObject:application]; 123 | } 124 | } 125 | [self.tableView reloadData]; 126 | } 127 | } 128 | 129 | 130 | @end 131 | -------------------------------------------------------------------------------- /AppBrowser/Controller/LANProListViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // LANProListViewController.m 3 | // AppBrowser 4 | // 5 | // Created by 蓝布鲁 on 2016/11/29. 6 | // Copyright (c) 2016 lanvsblueCO. All rights reserved. 7 | // 8 | 9 | #import "LANProListViewController.h" 10 | #import "LANProListCell.h" 11 | #import "LANPathDisplayView.h" 12 | #import "NSDictionary+LAN.h" 13 | 14 | @interface LANProListViewController () 15 | 16 | @property(nonatomic, retain) UITableView *tableView; 17 | 18 | 19 | @end 20 | 21 | @implementation LANProListViewController{ 22 | NSDictionary * _properties; 23 | NSArray *_allKeys; 24 | } 25 | 26 | - (id)initWithProperties:(id)properties { 27 | if(self=[super init]){ 28 | if([properties isKindOfClass:[NSDictionary class]]){ 29 | _allKeys = [properties allKeys]; 30 | _properties = properties; 31 | } else if ([properties isKindOfClass:[NSArray class]]){ 32 | _allKeys = properties; 33 | } 34 | 35 | //sort keys 36 | _allKeys = [_allKeys sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) { 37 | if([obj1 isKindOfClass:[NSString class]]){ 38 | 39 | //top item is super class 40 | if([obj1 isEqualToString:SUPER_CLASS]){ 41 | return NSOrderedAscending; 42 | } else if([obj2 isEqualToString:SUPER_CLASS]){ 43 | return NSOrderedDescending; 44 | } 45 | return [obj1 compare:obj2 options:NSCaseInsensitiveSearch]; 46 | } else if ([obj1 isKindOfClass:[NSNumber class]]){ 47 | return [obj1 compare:obj2]; 48 | } 49 | return NSOrderedSame; 50 | 51 | }]; 52 | } 53 | 54 | [self initDisplayView]; 55 | return self; 56 | } 57 | 58 | 59 | - (void)viewDidLoad { 60 | [super viewDidLoad]; 61 | //init tableview 62 | self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0,0,SCREEN_WIDTH,SCREEN_HEIGHT-20) style:UITableViewStylePlain]; 63 | self.tableView.dataSource = self; 64 | self.tableView.delegate = self; 65 | [self.view addSubview:self.tableView]; 66 | 67 | [self.pathDisplayView setupView]; 68 | [self.view addSubview:self.pathDisplayView]; 69 | 70 | //init menu 71 | // UIMenuItem *favoriteItem = [[UIMenuItem alloc] initWithTitle:@"Favorite" action:@selector(favoriteItem:)]; 72 | // UIMenuController *menuController = [UIMenuController sharedMenuController]; 73 | // [menuController setMenuItems:@[favoriteItem]]; 74 | // [menuController update]; 75 | } 76 | 77 | -(void)initDisplayView{ 78 | //init pathDisplayView 79 | self.pathDisplayView = [[LANPathDisplayView alloc] initWithFrame:CGRectMake(0,SCREEN_HEIGHT-20,SCREEN_WIDTH,20)]; 80 | } 81 | 82 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 83 | return _allKeys.count; 84 | } 85 | 86 | - (LANPropertiesType)infoTypeAtIndexPath:(NSIndexPath *)indexPath { 87 | id key = _allKeys[indexPath.row]; 88 | id value = _properties[key]; 89 | if ([value isKindOfClass:NSDictionary.class]) { 90 | return LANPropertiesTypeDictionary; 91 | } else if ([value isKindOfClass:NSArray.class]) { 92 | return LANPropertiesTypeArray; 93 | } else if ([key isKindOfClass:NSDictionary.class]) { 94 | return LANPropertiesTypeKeyDict; 95 | } else { 96 | return LANPropertiesTypeValue; 97 | } 98 | } 99 | 100 | - (void)fetchInfoWithIndexPath:(NSIndexPath *)indexPath completionHandler:(LANItemInfoFetchBlock)block { 101 | id key = _allKeys[indexPath.row]; 102 | LANPropertiesType type = [self infoTypeAtIndexPath:indexPath]; 103 | if (type == LANPropertiesTypeValue) { 104 | block(UITableViewCellAccessoryNone, [key description], [_properties[key] description] ?: @""); 105 | } else { 106 | NSString *title; 107 | if (type == LANPropertiesTypeKeyDict) { 108 | title = [NSString stringWithFormat:@"Item %d", (int)indexPath.row]; 109 | } else { 110 | title = [key description]; 111 | } 112 | block(UITableViewCellAccessoryDisclosureIndicator, title, [NSString stringWithFormat:@"%d items", _properties ? [_properties[key] count] : [key count]]); 113 | } 114 | } 115 | 116 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 117 | __block LANProListCell *cell = [tableView cellForRowAtIndexPath:indexPath]; 118 | if(cell==nil){ 119 | [self fetchInfoWithIndexPath:indexPath completionHandler:^(UITableViewCellAccessoryType accessoryType, NSString *title, NSString *subtitle) { 120 | if(accessoryType==UITableViewCellAccessoryDisclosureIndicator){ 121 | cell = [[LANProListCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"CellID"]; 122 | } else{ 123 | cell = [[LANProListCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"CellID"]; 124 | } 125 | cell.title = title; 126 | cell.subTitle = subtitle; 127 | cell.type = accessoryType; 128 | 129 | }]; 130 | 131 | } 132 | return cell; 133 | } 134 | 135 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 136 | [tableView deselectRowAtIndexPath:indexPath animated:YES]; 137 | id key = _allKeys[indexPath.row]; 138 | if ([self infoTypeAtIndexPath:indexPath] != LANPropertiesTypeValue) { 139 | id info = _properties ? _properties[key] : key; 140 | LANProListViewController *infoController = [[LANProListViewController alloc] initWithProperties:info]; 141 | [self fetchInfoWithIndexPath:indexPath completionHandler:^(UITableViewCellAccessoryType accessoryType, NSString *title, NSString *subtitle) { 142 | infoController.title = title; 143 | [infoController.pathDisplayView setDisplayPath:self.pathDisplayView.displayPath addPath:title]; 144 | }]; 145 | [self.navigationController pushViewController:infoController animated:YES]; 146 | } 147 | } 148 | 149 | - (BOOL)tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath { 150 | return true; 151 | } 152 | 153 | - (BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender { 154 | return (action==@selector(copy:)||action==@selector(favoriteItem:)); 155 | } 156 | 157 | - (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender { 158 | 159 | } 160 | 161 | 162 | 163 | 164 | 165 | @end 166 | -------------------------------------------------------------------------------- /AppBrowser/Controller/LANAppViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // LANAppViewController.m 3 | // AppBrowser 4 | // 5 | // Created by 蓝布鲁 on 2016/11/29. 6 | // Copyright (c) 2016 lanvsblueCO. All rights reserved. 7 | // 8 | 9 | #import "LANAppViewController.h" 10 | #import "LANAppHelper.h" 11 | #import "LANProListViewController.h" 12 | #import "LANPathDisplayView.h" 13 | #import "LANProListCell.h" 14 | 15 | @interface LANAppViewController () 16 | 17 | @property(nonatomic, retain) UIImageView *imageView; 18 | @property (nonatomic, retain) UITableView *tableView; 19 | 20 | @end 21 | 22 | @implementation LANAppViewController{ 23 | NSDictionary *_infoDictionary; 24 | NSArray *_allKeys; 25 | } 26 | 27 | - (void)viewDidLoad { 28 | [super viewDidLoad]; 29 | self.title = [LANAppHelper nameForApplication:self.application]; 30 | self.view.backgroundColor = [UIColor whiteColor]; 31 | 32 | [self setupView]; 33 | 34 | //refresh 35 | [self refresh]; 36 | 37 | 38 | } 39 | 40 | 41 | 42 | - (void)setupView { 43 | 44 | //setup navigation item 45 | [self setupNavigation]; 46 | 47 | //setup header view 48 | [self setupHeaderView]; 49 | 50 | //setup property tableView 51 | [self setupTableView]; 52 | 53 | } 54 | 55 | -(void)setupNavigation{ 56 | UIBarButtonItem *removeItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemTrash 57 | target:self 58 | action:@selector(removeApp)]; 59 | 60 | UIBarButtonItem *openItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction 61 | target:self 62 | action:@selector(openApp)]; 63 | self.navigationItem.rightBarButtonItems = @[removeItem, openItem]; 64 | } 65 | 66 | -(void)setupHeaderView{ 67 | //header view 68 | UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0,64,SCREEN_WIDTH,150)]; 69 | headerView.layer.borderWidth = 0.2; 70 | headerView.layer.borderColor = [UIColor lightGrayColor].CGColor; 71 | 72 | UIBlurEffect *effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleExtraLight]; 73 | UIVisualEffectView *effectView = [[UIVisualEffectView alloc] initWithEffect:effect]; 74 | effectView.frame = CGRectMake(0,0,headerView.width,headerView.height); 75 | [headerView addSubview:effectView]; 76 | 77 | [self.view addSubview:headerView]; 78 | 79 | //image of application 80 | UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(15,15,headerView.height-30,headerView.height-30)]; 81 | imageView.image = [LANAppHelper iconForApplication:self.application]; 82 | [headerView addSubview:imageView]; 83 | 84 | //app name 85 | UILabel *nameLabel = [[UILabel alloc] initWithFrame:CGRectMake(imageView.rightX+15,imageView.originY,0,0)]; 86 | nameLabel.font = [UIFont systemFontOfSize:15]; 87 | nameLabel.text = [LANAppHelper nameForApplication:self.application]; 88 | [nameLabel sizeToFit]; 89 | [headerView addSubview:nameLabel]; 90 | 91 | //vendor name 92 | UILabel *vendorLabel = [[UILabel alloc] initWithFrame:CGRectMake(imageView.rightX+15,nameLabel.bottomY+5,0,0)]; 93 | vendorLabel.text = [LANAppHelper vendorNameForApplication:self.application]?[LANAppHelper vendorNameForApplication:self.application]:@" "; 94 | vendorLabel.font = [UIFont systemFontOfSize:12]; 95 | vendorLabel.textColor = [UIColor grayColor]; 96 | vendorLabel.numberOfLines = 0; 97 | [vendorLabel sizeToFit]; 98 | [headerView addSubview:vendorLabel]; 99 | 100 | //bundle identifier 101 | UILabel *bundleLabel = [[UILabel alloc] initWithFrame:CGRectMake(imageView.rightX+15,vendorLabel.bottomY+5,0,0)]; 102 | bundleLabel.text = [LANAppHelper bundleIDForApplication:self.application]; 103 | bundleLabel.font = [UIFont systemFontOfSize:12]; 104 | bundleLabel.textColor = [UIColor grayColor]; 105 | [bundleLabel sizeToFit]; 106 | [headerView addSubview:bundleLabel]; 107 | 108 | //properties 109 | UIButton *propertiesButton = [UIButton buttonWithType:UIButtonTypeSystem]; 110 | propertiesButton.frame = CGRectMake(headerView.rightX-60-15,imageView.bottomY-30,60,30); 111 | [propertiesButton setTitle:@"INFO" forState:UIControlStateNormal]; 112 | [propertiesButton setTitleColor:[UIColor colorWithRed:0.08 green:0.49 blue:0.98 alpha:1.00] forState:UIControlStateNormal]; 113 | propertiesButton.layer.masksToBounds = true; 114 | propertiesButton.layer.cornerRadius = 3; 115 | propertiesButton.layer.borderColor = [UIColor colorWithRed:0.08 green:0.49 blue:0.98 alpha:1.00].CGColor; 116 | propertiesButton.layer.borderWidth = 1; 117 | propertiesButton.layer.shadowOffset = CGSizeZero; 118 | [propertiesButton addTarget:self action:@selector(propertiesButtonTapped) forControlEvents:UIControlEventTouchUpInside]; 119 | [headerView addSubview:propertiesButton]; 120 | } 121 | 122 | -(void)setupTableView{ 123 | self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0,150+64,SCREEN_WIDTH,self.view.height-150-64) 124 | style:UITableViewStyleGrouped]; 125 | self.tableView.delegate = self; 126 | self.tableView.dataSource = self; 127 | [self.view addSubview:self.tableView]; 128 | } 129 | 130 | -(void)refresh{ 131 | //get info.plist 132 | _infoDictionary = [self.application valueForKeyPath:APP_PROPERTY_LIST_KEY_PATH]; 133 | _allKeys = [_infoDictionary.allKeys sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) { 134 | if([obj1 isKindOfClass:[NSString class]]){ 135 | return [obj1 compare:obj2 options:NSCaseInsensitiveSearch]; 136 | } else if ([obj1 isKindOfClass:[NSNumber class]]){ 137 | return [obj1 compare:obj2]; 138 | } 139 | return NSOrderedSame; 140 | }]; 141 | } 142 | 143 | - (LANPropertiesType)infoTypeAtIndexPath:(NSIndexPath *)indexPath { 144 | id key = _allKeys[indexPath.row]; 145 | id value = _infoDictionary[key]; 146 | if ([value isKindOfClass:NSDictionary.class]) { 147 | return LANPropertiesTypeDictionary; 148 | } else if ([value isKindOfClass:NSArray.class]) { 149 | return LANPropertiesTypeArray; 150 | } else if ([key isKindOfClass:NSDictionary.class]) { 151 | return LANPropertiesTypeKeyDict; 152 | } else { 153 | return LANPropertiesTypeValue; 154 | } 155 | } 156 | 157 | - (void)fetchInfoWithIndexPath:(NSIndexPath *)indexPath completionHandler:(LANItemInfoFetchBlock)block { 158 | id key = _allKeys[indexPath.row]; 159 | LANPropertiesType type = [self infoTypeAtIndexPath:indexPath]; 160 | if (type == LANPropertiesTypeValue) { 161 | block(UITableViewCellAccessoryNone, [key description], [_infoDictionary[key] description] ?: @""); 162 | } else { 163 | NSString *title; 164 | if (type == LANPropertiesTypeKeyDict) { 165 | title = [NSString stringWithFormat:@"Item %d", (int)indexPath.row]; 166 | } else { 167 | title = [key description]; 168 | } 169 | block(UITableViewCellAccessoryDisclosureIndicator, title, [NSString stringWithFormat:@"%d items", _infoDictionary ? [_infoDictionary[key] count] : [key count]]); 170 | } 171 | } 172 | 173 | - (void)removeApp { 174 | //if it is simulator , can be uninstall 175 | 176 | #if TARGET_OS_SIMULATOR 177 | [LANAppHelper removeApplication:self.application]; 178 | [self.navigationController popViewControllerAnimated:true]; 179 | #elif TARGET_OS_IPHONE 180 | 181 | 182 | UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Uninstall failed" 183 | message:@"It only can be used on simulator" 184 | preferredStyle:UIAlertControllerStyleAlert]; 185 | 186 | UIAlertAction *done = [UIAlertAction actionWithTitle:@"Done" 187 | style:UIAlertActionStyleDefault 188 | handler:^(UIAlertAction *action) { 189 | 190 | }]; 191 | [alert addAction:done]; 192 | #endif 193 | 194 | } 195 | 196 | - (void)openApp { 197 | [LANAppHelper openApplication:self.application]; 198 | } 199 | 200 | -(void)propertiesButtonTapped{ 201 | LANProListViewController *controller = [[LANProListViewController alloc] 202 | initWithProperties:[LANAppHelper infoForApplication:self.application]]; 203 | controller.pathDisplayView.displayPath = @"LSApplicationProxy"; 204 | controller.title = @"LSApplicationProxy"; 205 | [self.navigationController pushViewController:controller animated:true]; 206 | } 207 | 208 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 209 | return _infoDictionary.count; 210 | } 211 | 212 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 213 | return 1; 214 | } 215 | 216 | - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { 217 | UIView *header = [[UIView alloc] init]; 218 | UILabel *headerLabel = [[UILabel alloc] initWithFrame:CGRectMake(20,20,200,20)]; 219 | headerLabel.text = @"info.plist"; 220 | headerLabel.font = [UIFont systemFontOfSize:15]; 221 | headerLabel.textColor = [UIColor grayColor]; 222 | [header addSubview:headerLabel]; 223 | return header; 224 | } 225 | 226 | - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { 227 | return 50; 228 | } 229 | 230 | 231 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 232 | __block LANProListCell *cell = [tableView cellForRowAtIndexPath:indexPath]; 233 | if(cell==nil){ 234 | [self fetchInfoWithIndexPath:indexPath completionHandler:^(UITableViewCellAccessoryType accessoryType, NSString *title, NSString *subtitle) { 235 | if(accessoryType==UITableViewCellAccessoryDisclosureIndicator){ 236 | cell = [[LANProListCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"CellID"]; 237 | } else{ 238 | cell = [[LANProListCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"CellID"]; 239 | } 240 | cell.title = title; 241 | cell.subTitle = subtitle; 242 | cell.type = accessoryType; 243 | 244 | }]; 245 | 246 | } 247 | return cell; 248 | } 249 | 250 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 251 | [tableView deselectRowAtIndexPath:indexPath animated:YES]; 252 | id key = _allKeys[indexPath.row]; 253 | if ([self infoTypeAtIndexPath:indexPath] != LANPropertiesTypeValue) { 254 | id info = _infoDictionary; 255 | LANProListViewController *infoController = [[LANProListViewController alloc] initWithProperties:info]; 256 | [self fetchInfoWithIndexPath:indexPath completionHandler:^(UITableViewCellAccessoryType accessoryType, NSString *title, NSString *subtitle) { 257 | infoController.title = title; 258 | [infoController.pathDisplayView setDisplayPath:@"_infoDictionary.propertyList" addPath:title]; 259 | }]; 260 | [self.navigationController pushViewController:infoController animated:YES]; 261 | } 262 | } 263 | 264 | 265 | @end 266 | -------------------------------------------------------------------------------- /AppBrowser/Common/RuntimeInvoker.m: -------------------------------------------------------------------------------- 1 | // 2 | // RuntimeInvoker.m 3 | // RuntimeInvoker 4 | // 5 | // Created by cyan on 16/5/27. 6 | // Copyright © 2016年 cyan. All rights reserved. 7 | // 8 | 9 | #import "RuntimeInvoker.h" 10 | #import 11 | 12 | #define _DEFINE_ARRAY(arg) \ 13 | NSMutableArray *array = [NSMutableArray arrayWithObject:arg];\ 14 | va_list args;\ 15 | va_start(args, arg);\ 16 | id next = nil;\ 17 | while ((next = va_arg(args,id))) {\ 18 | [array addObject:next];\ 19 | }\ 20 | va_end(args);\ 21 | 22 | #pragma mark - NSMethodSignature Category 23 | 24 | // Objective-C type encoding: http://nshipster.com/type-encodings/ 25 | typedef NS_ENUM(NSInteger, RIMethodArgumentType) { 26 | RIMethodArgumentTypeUnknown = 0, 27 | RIMethodArgumentTypeChar, 28 | RIMethodArgumentTypeInt, 29 | RIMethodArgumentTypeShort, 30 | RIMethodArgumentTypeLong, 31 | RIMethodArgumentTypeLongLong, 32 | RIMethodArgumentTypeUnsignedChar, 33 | RIMethodArgumentTypeUnsignedInt, 34 | RIMethodArgumentTypeUnsignedShort, 35 | RIMethodArgumentTypeUnsignedLong, 36 | RIMethodArgumentTypeUnsignedLongLong, 37 | RIMethodArgumentTypeFloat, 38 | RIMethodArgumentTypeDouble, 39 | RIMethodArgumentTypeBool, 40 | RIMethodArgumentTypeVoid, 41 | RIMethodArgumentTypeCharacterString, 42 | RIMethodArgumentTypeCGPoint, 43 | RIMethodArgumentTypeCGSize, 44 | RIMethodArgumentTypeCGRect, 45 | RIMethodArgumentTypeUIEdgeInsets, 46 | RIMethodArgumentTypeObject, 47 | RIMethodArgumentTypeClass 48 | }; 49 | 50 | @implementation NSMethodSignature (RuntimeInvoker) 51 | 52 | /** 53 | * Get type of return value 54 | * 55 | * @return Return value type 56 | */ 57 | - (RIMethodArgumentType)returnType { 58 | return [NSMethodSignature argumentTypeWithEncode:[self methodReturnType]]; 59 | } 60 | 61 | /** 62 | * Type encoding for argument 63 | * 64 | * @param encode Encode for argument 65 | * 66 | * @return RIMethodArgumentType 67 | */ 68 | + (RIMethodArgumentType)argumentTypeWithEncode:(const char *)encode { 69 | 70 | if (strcmp(encode, @encode(char)) == 0) { 71 | return RIMethodArgumentTypeChar; 72 | } else if (strcmp(encode, @encode(int)) == 0) { 73 | return RIMethodArgumentTypeInt; 74 | } else if (strcmp(encode, @encode(short)) == 0) { 75 | return RIMethodArgumentTypeShort; 76 | } else if (strcmp(encode, @encode(long)) == 0) { 77 | return RIMethodArgumentTypeLong; 78 | } else if (strcmp(encode, @encode(long long)) == 0) { 79 | return RIMethodArgumentTypeLongLong; 80 | } else if (strcmp(encode, @encode(unsigned char)) == 0) { 81 | return RIMethodArgumentTypeUnsignedChar; 82 | } else if (strcmp(encode, @encode(unsigned int)) == 0) { 83 | return RIMethodArgumentTypeUnsignedInt; 84 | } else if (strcmp(encode, @encode(unsigned short)) == 0) { 85 | return RIMethodArgumentTypeUnsignedShort; 86 | } else if (strcmp(encode, @encode(unsigned long)) == 0) { 87 | return RIMethodArgumentTypeUnsignedLong; 88 | } else if (strcmp(encode, @encode(unsigned long long)) == 0) { 89 | return RIMethodArgumentTypeUnsignedLongLong; 90 | } else if (strcmp(encode, @encode(float)) == 0) { 91 | return RIMethodArgumentTypeFloat; 92 | } else if (strcmp(encode, @encode(double)) == 0) { 93 | return RIMethodArgumentTypeDouble; 94 | } else if (strcmp(encode, @encode(BOOL)) == 0) { 95 | return RIMethodArgumentTypeBool; 96 | } else if (strcmp(encode, @encode(void)) == 0) { 97 | return RIMethodArgumentTypeVoid; 98 | } else if (strcmp(encode, @encode(char *)) == 0) { 99 | return RIMethodArgumentTypeCharacterString; 100 | } else if (strcmp(encode, @encode(id)) == 0) { 101 | return RIMethodArgumentTypeObject; 102 | } else if (strcmp(encode, @encode(Class)) == 0) { 103 | return RIMethodArgumentTypeClass; 104 | } else if (strcmp(encode, @encode(CGPoint)) == 0) { 105 | return RIMethodArgumentTypeCGPoint; 106 | } else if (strcmp(encode, @encode(CGSize)) == 0) { 107 | return RIMethodArgumentTypeCGSize; 108 | } else if (strcmp(encode, @encode(CGRect)) == 0) { 109 | return RIMethodArgumentTypeCGRect; 110 | } else if (strcmp(encode, @encode(UIEdgeInsets)) == 0) { 111 | return RIMethodArgumentTypeUIEdgeInsets; 112 | } else { 113 | return RIMethodArgumentTypeUnknown; 114 | } 115 | } 116 | 117 | /** 118 | * Get type of argument at index 119 | * 120 | * @param index Argument index 121 | * 122 | * @return Return value type 123 | */ 124 | - (RIMethodArgumentType)argumentTypeAtIndex:(NSInteger)index { 125 | const char *encode = [self getArgumentTypeAtIndex:index]; 126 | return [NSMethodSignature argumentTypeWithEncode:encode]; 127 | } 128 | 129 | /** 130 | * Setup arguments for invocation 131 | * 132 | * @param arguments Arguments 133 | * 134 | * @return NSInvocation 135 | */ 136 | - (NSInvocation *)invocationWithArguments:(NSArray *)arguments { 137 | 138 | NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:self]; 139 | 140 | NSAssert(arguments == nil || [arguments isKindOfClass:[NSArray class]], @"# RuntimeInvoker # arguments is not an array"); 141 | 142 | [arguments enumerateObjectsUsingBlock:^(id _Nonnull argument, NSUInteger idx, BOOL * _Nonnull stop) { 143 | 144 | NSInteger index = idx + 2; // start with 2 145 | RIMethodArgumentType type = [self argumentTypeAtIndex:index]; 146 | 147 | switch (type) { 148 | case RIMethodArgumentTypeChar: { 149 | char value = [argument charValue]; 150 | [invocation setArgument:&value atIndex:index]; 151 | } break; 152 | case RIMethodArgumentTypeInt: { 153 | int value = [argument intValue]; 154 | [invocation setArgument:&value atIndex:index]; 155 | } break; 156 | case RIMethodArgumentTypeShort: { 157 | short value = [argument shortValue]; 158 | [invocation setArgument:&value atIndex:index]; 159 | } break; 160 | case RIMethodArgumentTypeLong: { 161 | long value = [argument longValue]; 162 | [invocation setArgument:&value atIndex:index]; 163 | } break; 164 | case RIMethodArgumentTypeLongLong: { 165 | long long value = [argument longLongValue]; 166 | [invocation setArgument:&value atIndex:index]; 167 | } break; 168 | case RIMethodArgumentTypeUnsignedChar: { 169 | unsigned char value = [argument unsignedCharValue]; 170 | [invocation setArgument:&value atIndex:index]; 171 | } break; 172 | case RIMethodArgumentTypeUnsignedInt: { 173 | unsigned int value = [argument unsignedIntValue]; 174 | [invocation setArgument:&value atIndex:index]; 175 | } break; 176 | case RIMethodArgumentTypeUnsignedShort: { 177 | unsigned short value = [argument unsignedShortValue]; 178 | [invocation setArgument:&value atIndex:index]; 179 | } break; 180 | case RIMethodArgumentTypeUnsignedLong: { 181 | unsigned long value = [argument unsignedLongValue]; 182 | [invocation setArgument:&value atIndex:index]; 183 | } break; 184 | case RIMethodArgumentTypeUnsignedLongLong: { 185 | unsigned long long value = [argument unsignedLongLongValue]; 186 | [invocation setArgument:&value atIndex:index]; 187 | } break; 188 | case RIMethodArgumentTypeFloat: { 189 | float value = [argument floatValue]; 190 | [invocation setArgument:&value atIndex:index]; 191 | } break; 192 | case RIMethodArgumentTypeDouble: { 193 | double value = [argument doubleValue]; 194 | [invocation setArgument:&value atIndex:index]; 195 | } break; 196 | case RIMethodArgumentTypeBool: { 197 | BOOL value = [argument boolValue]; 198 | [invocation setArgument:&value atIndex:index]; 199 | } break; 200 | case RIMethodArgumentTypeVoid: { 201 | 202 | } break; 203 | case RIMethodArgumentTypeCharacterString: { 204 | const char *value = [argument UTF8String]; 205 | [invocation setArgument:&value atIndex:index]; 206 | } break; 207 | case RIMethodArgumentTypeObject: { 208 | [invocation setArgument:&argument atIndex:index]; 209 | } break; 210 | case RIMethodArgumentTypeClass: { 211 | Class value = [argument class]; 212 | [invocation setArgument:&value atIndex:index]; 213 | } break; 214 | 215 | default: break; 216 | } 217 | }]; 218 | 219 | return invocation; 220 | } 221 | 222 | @end 223 | 224 | #pragma mark - NSInvocation Category 225 | 226 | @implementation NSInvocation (RuntimeInvoker) 227 | 228 | /** 229 | * Invoke a selector 230 | * 231 | * @param target Target 232 | * @param selector Selector 233 | * @param type Return value type 234 | * 235 | * @return Return value 236 | */ 237 | - (id)invoke:(id)target selector:(SEL)selector returnType:(RIMethodArgumentType)type { 238 | self.target = target; 239 | self.selector = selector; 240 | [self invoke]; 241 | return [self returnValueForType:type]; 242 | } 243 | 244 | /** 245 | * Boxing returnType of NSMethodSignature 246 | * 247 | * @param signature Signature 248 | * 249 | * @return Boxed value 250 | */ 251 | - (id)returnValueForType:(RIMethodArgumentType)type { 252 | 253 | __unsafe_unretained id returnValue; 254 | 255 | switch (type) { 256 | case RIMethodArgumentTypeChar: { 257 | char value; 258 | [self getReturnValue:&value]; 259 | returnValue = @(value); 260 | } break; 261 | case RIMethodArgumentTypeInt: { 262 | int value; 263 | [self getReturnValue:&value]; 264 | returnValue = @(value); 265 | } break; 266 | case RIMethodArgumentTypeShort: { 267 | short value; 268 | [self getReturnValue:&value]; 269 | returnValue = @(value); 270 | } break; 271 | case RIMethodArgumentTypeLong: { 272 | long value; 273 | [self getReturnValue:&value]; 274 | returnValue = @(value); 275 | } break; 276 | case RIMethodArgumentTypeLongLong: { 277 | long long value; 278 | [self getReturnValue:&value]; 279 | returnValue = @(value); 280 | } break; 281 | case RIMethodArgumentTypeUnsignedChar: { 282 | unsigned char value; 283 | [self getReturnValue:&value]; 284 | returnValue = @(value); 285 | } break; 286 | case RIMethodArgumentTypeUnsignedInt: { 287 | unsigned int value; 288 | [self getReturnValue:&value]; 289 | returnValue = @(value); 290 | } break; 291 | case RIMethodArgumentTypeUnsignedShort: { 292 | unsigned short value; 293 | [self getReturnValue:&value]; 294 | returnValue = @(value); 295 | } break; 296 | case RIMethodArgumentTypeUnsignedLong: { 297 | unsigned long value; 298 | [self getReturnValue:&value]; 299 | returnValue = @(value); 300 | } break; 301 | case RIMethodArgumentTypeUnsignedLongLong: { 302 | unsigned long long value; 303 | [self getReturnValue:&value]; 304 | returnValue = @(value); 305 | } break; 306 | case RIMethodArgumentTypeFloat: { 307 | float value; 308 | [self getReturnValue:&value]; 309 | returnValue = @(value); 310 | } break; 311 | case RIMethodArgumentTypeDouble: { 312 | double value; 313 | [self getReturnValue:&value]; 314 | returnValue = @(value); 315 | } break; 316 | case RIMethodArgumentTypeBool: { 317 | BOOL value; 318 | [self getReturnValue:&value]; 319 | returnValue = @(value); 320 | } break; 321 | case RIMethodArgumentTypeCharacterString: { 322 | const char *value; 323 | [self getReturnValue:&value]; 324 | returnValue = [NSString stringWithUTF8String:value]; 325 | } break; 326 | case RIMethodArgumentTypeCGPoint: { 327 | CGPoint value; 328 | [self getReturnValue:&value]; 329 | returnValue = [NSValue valueWithCGPoint:value]; 330 | } break; 331 | case RIMethodArgumentTypeCGSize: { 332 | CGSize value; 333 | [self getReturnValue:&value]; 334 | returnValue = [NSValue valueWithCGSize:value]; 335 | } break; 336 | case RIMethodArgumentTypeCGRect: { 337 | CGRect value; 338 | [self getReturnValue:&value]; 339 | returnValue = [NSValue valueWithCGRect:value]; 340 | } break; 341 | case RIMethodArgumentTypeUIEdgeInsets: { 342 | UIEdgeInsets value; 343 | [self getReturnValue:&value]; 344 | returnValue = [NSValue valueWithUIEdgeInsets:value]; 345 | } break; 346 | case RIMethodArgumentTypeObject: 347 | case RIMethodArgumentTypeClass: 348 | [self getReturnValue:&returnValue]; 349 | break; 350 | default: break; 351 | } 352 | return returnValue; 353 | } 354 | 355 | @end 356 | 357 | #pragma mark - NSObject Category 358 | 359 | @implementation NSObject (RuntimeInvoker) 360 | 361 | id _invoke(id target, NSString *selector, NSArray *arguments) { 362 | SEL sel = NSSelectorFromString(selector); 363 | NSMethodSignature *signature = [target methodSignatureForSelector:sel]; 364 | if (signature) { 365 | NSInvocation *invocation = [signature invocationWithArguments:arguments]; 366 | id returnValue = [invocation invoke:target selector:sel returnType:signature.returnType]; 367 | return returnValue; 368 | } else { 369 | NSLog(@"# RuntimeInvoker # selector: \"%@\" NOT FOUND", selector); 370 | return nil; 371 | } 372 | } 373 | 374 | - (id)invoke:(NSString *)selector arguments:(NSArray *)arguments { 375 | return _invoke(self, selector, arguments); 376 | } 377 | 378 | - (id)invoke:(NSString *)selector { 379 | return [self invoke:selector arguments:nil]; 380 | } 381 | 382 | - (id)invoke:(NSString *)selector args:(id)arg, ... { 383 | _DEFINE_ARRAY(arg); 384 | return [self invoke:selector arguments:array]; 385 | } 386 | 387 | + (id)invoke:(NSString *)selector { 388 | return [self.class invoke:selector arguments:nil]; 389 | } 390 | 391 | + (id)invoke:(NSString *)selector args:(id)arg, ... { 392 | _DEFINE_ARRAY(arg); 393 | return [self.class invoke:selector arguments:array]; 394 | } 395 | 396 | + (id)invoke:(NSString *)selector arguments:(NSArray *)arguments { 397 | return _invoke(self.class, selector, arguments); 398 | } 399 | 400 | @end 401 | 402 | @implementation NSString (RuntimeInvoker) 403 | 404 | - (id)invokeClassMethod:(NSString *)selector { 405 | return [self invokeClassMethod:selector arguments:nil]; 406 | } 407 | 408 | - (id)invokeClassMethod:(NSString *)selector args:(id)arg, ... { 409 | _DEFINE_ARRAY(arg); 410 | return [self invokeClassMethod:selector arguments:array]; 411 | } 412 | 413 | - (id)invokeClassMethod:(NSString *)selector arguments:(NSArray *)arguments { 414 | return [NSClassFromString(self) invoke:selector arguments:arguments]; 415 | } 416 | 417 | @end 418 | -------------------------------------------------------------------------------- /AppBrowser.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 48; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1A199041E0466BA5F9BB1F11 /* LANAppHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A19967D98091DBB5C8E1D46 /* LANAppHelper.m */; }; 11 | 1A1990D3CA98281F7798BAC2 /* UIView+LAN.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A19989C3C9A63560335D2F7 /* UIView+LAN.m */; }; 12 | 1A19913A21A77F3698BA5F22 /* NSArray+LAN.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A199660E6CFB68AE2207409 /* NSArray+LAN.m */; }; 13 | 1A19913DBC063139E455FB1B /* LANProListCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A199577A796360041C4F1F3 /* LANProListCell.m */; }; 14 | 1A1991AFE54A0FC9CD0473DD /* NSDictionary+LAN.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1997EB459C56D2C64D0018 /* NSDictionary+LAN.m */; }; 15 | 1A19920A9D1DEA3ECAF17675 /* LANAppViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A19965D34B7914B70421EC7 /* LANAppViewController.m */; }; 16 | 1A199231ED464FE2CBF0BB1E /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A199F9CD9029FC50A3D78D1 /* AppDelegate.m */; }; 17 | 1A1992BE7D796198EBC175C1 /* LANAppListCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1994DDC19CA7384C38B140 /* LANAppListCell.m */; }; 18 | 1A19937BC28F8488AE04D9DF /* LANAppListViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A199ABBB88F0D9A2797316F /* LANAppListViewController.m */; }; 19 | 1A1994D0A04E9C345A89F2F9 /* RuntimeInvoker.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1992DE59F4730B2B128E84 /* RuntimeInvoker.m */; }; 20 | 1A1996B5FF33C7D3AF28939E /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 1A199CE6A084BA342C2CF69B /* Info.plist */; }; 21 | 1A199771F6938A6F6D1FE478 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 1A199EF5E749068E073330A0 /* LaunchScreen.storyboard */; }; 22 | 1A1997C74B30FDB729B998D3 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1999B9E8A8D4DC813E38C8 /* main.m */; }; 23 | 1A1997C9B7D6A71B93067E79 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A1992578298797C6C033A18 /* Assets.xcassets */; }; 24 | 1A199B633E5859BFA2F9840F /* LANPathDisplayView.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1991B514F189D87CFE5C47 /* LANPathDisplayView.m */; }; 25 | 1A199D4C0656B11F435557BF /* LANProListViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A199E76C44E5E0A79320D94 /* LANProListViewController.m */; }; 26 | /* End PBXBuildFile section */ 27 | 28 | /* Begin PBXFileReference section */ 29 | 1A199070418BA7768EFF524C /* AppBrowser.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AppBrowser.app; sourceTree = BUILT_PRODUCTS_DIR; }; 30 | 1A1990F733EAD68BE39C7606 /* LANAppViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = LANAppViewController.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; 31 | 1A1991B514F189D87CFE5C47 /* LANPathDisplayView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = LANPathDisplayView.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; 32 | 1A1992578298797C6C033A18 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 33 | 1A1992DE59F4730B2B128E84 /* RuntimeInvoker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RuntimeInvoker.m; sourceTree = ""; }; 34 | 1A19947893E0B5F6EE991C44 /* LANPathDisplayView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = LANPathDisplayView.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; 35 | 1A1994965A43007728F16861 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 36 | 1A1994DDC19CA7384C38B140 /* LANAppListCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LANAppListCell.m; sourceTree = ""; }; 37 | 1A199577A796360041C4F1F3 /* LANProListCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = LANProListCell.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; 38 | 1A19959F2A916B842D7E2CF7 /* LANProListCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = LANProListCell.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; 39 | 1A19965D34B7914B70421EC7 /* LANAppViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = LANAppViewController.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; 40 | 1A199660E6CFB68AE2207409 /* NSArray+LAN.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSArray+LAN.m"; sourceTree = ""; }; 41 | 1A19967D98091DBB5C8E1D46 /* LANAppHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LANAppHelper.m; sourceTree = ""; }; 42 | 1A19972B4AFD6BBBAE33FA37 /* LANGlobalDefine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = LANGlobalDefine.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; 43 | 1A1997478E74D7F61A16DC70 /* LANAppHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LANAppHelper.h; sourceTree = ""; }; 44 | 1A1997EB459C56D2C64D0018 /* NSDictionary+LAN.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDictionary+LAN.m"; sourceTree = ""; }; 45 | 1A1998933E55A45AA0CAAF17 /* LANAppListViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LANAppListViewController.h; sourceTree = ""; }; 46 | 1A19989C3C9A63560335D2F7 /* UIView+LAN.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+LAN.m"; sourceTree = ""; }; 47 | 1A1998AEA713F2260D109C6C /* NSDictionary+LAN.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDictionary+LAN.h"; sourceTree = ""; }; 48 | 1A1999B9E8A8D4DC813E38C8 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = main.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; 49 | 1A199ABBB88F0D9A2797316F /* LANAppListViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LANAppListViewController.m; sourceTree = ""; }; 50 | 1A199B075D8374A60D616BBA /* LANProListViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = LANProListViewController.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; 51 | 1A199B95CA3359E5E928B5A9 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = AppDelegate.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; 52 | 1A199C1950487A700143D855 /* LANAppListCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LANAppListCell.h; sourceTree = ""; }; 53 | 1A199CE6A084BA342C2CF69B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.info; path = Info.plist; sourceTree = ""; }; 54 | 1A199D3A36FDA81D6E83E757 /* RuntimeInvoker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RuntimeInvoker.h; sourceTree = ""; }; 55 | 1A199D735C4AC99AF7291BB3 /* NSArray+LAN.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSArray+LAN.h"; sourceTree = ""; }; 56 | 1A199E76C44E5E0A79320D94 /* LANProListViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = LANProListViewController.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; 57 | 1A199F8538322DC9F6BB3C74 /* UIView+LAN.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+LAN.h"; sourceTree = ""; }; 58 | 1A199F9CD9029FC50A3D78D1 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = AppDelegate.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; 59 | 3F4BE5E31DE6E4A400A93B5A /* PrefixHeader.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = PrefixHeader.pch; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; 60 | /* End PBXFileReference section */ 61 | 62 | /* Begin PBXFrameworksBuildPhase section */ 63 | 1A199E7B40982D21C790F4E0 /* Frameworks */ = { 64 | isa = PBXFrameworksBuildPhase; 65 | buildActionMask = 2147483647; 66 | files = ( 67 | ); 68 | runOnlyForDeploymentPostprocessing = 0; 69 | }; 70 | /* End PBXFrameworksBuildPhase section */ 71 | 72 | /* Begin PBXGroup section */ 73 | 1A1994AAC5272E8BD9F27C4F /* View */ = { 74 | isa = PBXGroup; 75 | children = ( 76 | 1A1994DDC19CA7384C38B140 /* LANAppListCell.m */, 77 | 1A199C1950487A700143D855 /* LANAppListCell.h */, 78 | 1A19959F2A916B842D7E2CF7 /* LANProListCell.h */, 79 | 1A199577A796360041C4F1F3 /* LANProListCell.m */, 80 | 1A19947893E0B5F6EE991C44 /* LANPathDisplayView.h */, 81 | 1A1991B514F189D87CFE5C47 /* LANPathDisplayView.m */, 82 | ); 83 | path = View; 84 | sourceTree = ""; 85 | }; 86 | 1A1995E0721C4EE08AFF6EF1 /* Controller */ = { 87 | isa = PBXGroup; 88 | children = ( 89 | 1A1998933E55A45AA0CAAF17 /* LANAppListViewController.h */, 90 | 1A199ABBB88F0D9A2797316F /* LANAppListViewController.m */, 91 | 1A1990F733EAD68BE39C7606 /* LANAppViewController.h */, 92 | 1A19965D34B7914B70421EC7 /* LANAppViewController.m */, 93 | 1A199B075D8374A60D616BBA /* LANProListViewController.h */, 94 | 1A199E76C44E5E0A79320D94 /* LANProListViewController.m */, 95 | ); 96 | path = Controller; 97 | sourceTree = ""; 98 | }; 99 | 1A1996DC38201052FBB6A32F /* Category */ = { 100 | isa = PBXGroup; 101 | children = ( 102 | 1A199F8538322DC9F6BB3C74 /* UIView+LAN.h */, 103 | 1A19989C3C9A63560335D2F7 /* UIView+LAN.m */, 104 | 1A199660E6CFB68AE2207409 /* NSArray+LAN.m */, 105 | 1A199D735C4AC99AF7291BB3 /* NSArray+LAN.h */, 106 | 1A1997EB459C56D2C64D0018 /* NSDictionary+LAN.m */, 107 | 1A1998AEA713F2260D109C6C /* NSDictionary+LAN.h */, 108 | ); 109 | path = Category; 110 | sourceTree = ""; 111 | }; 112 | 1A1997F53AF87C2858BE40A7 /* Common */ = { 113 | isa = PBXGroup; 114 | children = ( 115 | 1A1996DC38201052FBB6A32F /* Category */, 116 | 1A199D3A36FDA81D6E83E757 /* RuntimeInvoker.h */, 117 | 1A1992DE59F4730B2B128E84 /* RuntimeInvoker.m */, 118 | ); 119 | path = Common; 120 | sourceTree = ""; 121 | }; 122 | 1A1999410672D29B8FEC961F /* Products */ = { 123 | isa = PBXGroup; 124 | children = ( 125 | 1A199070418BA7768EFF524C /* AppBrowser.app */, 126 | ); 127 | name = Products; 128 | sourceTree = ""; 129 | }; 130 | 1A1999BB55A35AAF4BFA9264 /* AppBrowser */ = { 131 | isa = PBXGroup; 132 | children = ( 133 | 1A199CE6A084BA342C2CF69B /* Info.plist */, 134 | 1A1992578298797C6C033A18 /* Assets.xcassets */, 135 | 1A199EF5E749068E073330A0 /* LaunchScreen.storyboard */, 136 | 1A199FE804FA083FADEC3983 /* Supporting Files */, 137 | 1A199B95CA3359E5E928B5A9 /* AppDelegate.h */, 138 | 1A199F9CD9029FC50A3D78D1 /* AppDelegate.m */, 139 | 1A1995E0721C4EE08AFF6EF1 /* Controller */, 140 | 1A1997F53AF87C2858BE40A7 /* Common */, 141 | 1A199D78CC9E036892E450AA /* Model */, 142 | 1A1994AAC5272E8BD9F27C4F /* View */, 143 | ); 144 | path = AppBrowser; 145 | sourceTree = ""; 146 | }; 147 | 1A199B0251663A8FA17404C3 = { 148 | isa = PBXGroup; 149 | children = ( 150 | 3F4BE5E31DE6E4A400A93B5A /* PrefixHeader.pch */, 151 | 1A1999410672D29B8FEC961F /* Products */, 152 | 1A1999BB55A35AAF4BFA9264 /* AppBrowser */, 153 | 1A19972B4AFD6BBBAE33FA37 /* LANGlobalDefine.h */, 154 | ); 155 | sourceTree = ""; 156 | }; 157 | 1A199D78CC9E036892E450AA /* Model */ = { 158 | isa = PBXGroup; 159 | children = ( 160 | 1A19967D98091DBB5C8E1D46 /* LANAppHelper.m */, 161 | 1A1997478E74D7F61A16DC70 /* LANAppHelper.h */, 162 | ); 163 | path = Model; 164 | sourceTree = ""; 165 | }; 166 | 1A199FE804FA083FADEC3983 /* Supporting Files */ = { 167 | isa = PBXGroup; 168 | children = ( 169 | 1A1999B9E8A8D4DC813E38C8 /* main.m */, 170 | ); 171 | name = "Supporting Files"; 172 | sourceTree = ""; 173 | }; 174 | /* End PBXGroup section */ 175 | 176 | /* Begin PBXNativeTarget section */ 177 | 1A199ABA0306E42DA9CC2EFA /* AppBrowser */ = { 178 | isa = PBXNativeTarget; 179 | buildConfigurationList = 1A1998425D1B08BE3DC10E8B /* Build configuration list for PBXNativeTarget "AppBrowser" */; 180 | buildPhases = ( 181 | 1A1991C4D5037AA720D67B81 /* Sources */, 182 | 1A199E7B40982D21C790F4E0 /* Frameworks */, 183 | 1A1996F3029634F03EE89CF2 /* Resources */, 184 | ); 185 | buildRules = ( 186 | ); 187 | dependencies = ( 188 | ); 189 | name = AppBrowser; 190 | productName = ApplicationManager; 191 | productReference = 1A199070418BA7768EFF524C /* AppBrowser.app */; 192 | productType = "com.apple.product-type.application"; 193 | }; 194 | /* End PBXNativeTarget section */ 195 | 196 | /* Begin PBXProject section */ 197 | 1A199A8FE21D4DA332F0F482 /* Project object */ = { 198 | isa = PBXProject; 199 | attributes = { 200 | CLASSPREFIX = LAN; 201 | ORGANIZATIONNAME = lanvsblueCO.; 202 | }; 203 | buildConfigurationList = 1A1999ECC1DE83EE7CC8A61F /* Build configuration list for PBXProject "AppBrowser" */; 204 | compatibilityVersion = "Xcode 8.0"; 205 | developmentRegion = English; 206 | hasScannedForEncodings = 0; 207 | knownRegions = ( 208 | en, 209 | ); 210 | mainGroup = 1A199B0251663A8FA17404C3; 211 | productRefGroup = 1A1999410672D29B8FEC961F /* Products */; 212 | projectDirPath = ""; 213 | projectRoot = ""; 214 | targets = ( 215 | 1A199ABA0306E42DA9CC2EFA /* AppBrowser */, 216 | ); 217 | }; 218 | /* End PBXProject section */ 219 | 220 | /* Begin PBXResourcesBuildPhase section */ 221 | 1A1996F3029634F03EE89CF2 /* Resources */ = { 222 | isa = PBXResourcesBuildPhase; 223 | buildActionMask = 2147483647; 224 | files = ( 225 | 1A1996B5FF33C7D3AF28939E /* Info.plist in Resources */, 226 | 1A1997C9B7D6A71B93067E79 /* Assets.xcassets in Resources */, 227 | 1A199771F6938A6F6D1FE478 /* LaunchScreen.storyboard in Resources */, 228 | ); 229 | runOnlyForDeploymentPostprocessing = 0; 230 | }; 231 | /* End PBXResourcesBuildPhase section */ 232 | 233 | /* Begin PBXSourcesBuildPhase section */ 234 | 1A1991C4D5037AA720D67B81 /* Sources */ = { 235 | isa = PBXSourcesBuildPhase; 236 | buildActionMask = 2147483647; 237 | files = ( 238 | 1A1997C74B30FDB729B998D3 /* main.m in Sources */, 239 | 1A199231ED464FE2CBF0BB1E /* AppDelegate.m in Sources */, 240 | 1A19937BC28F8488AE04D9DF /* LANAppListViewController.m in Sources */, 241 | 1A1990D3CA98281F7798BAC2 /* UIView+LAN.m in Sources */, 242 | 1A199041E0466BA5F9BB1F11 /* LANAppHelper.m in Sources */, 243 | 1A1994D0A04E9C345A89F2F9 /* RuntimeInvoker.m in Sources */, 244 | 1A1992BE7D796198EBC175C1 /* LANAppListCell.m in Sources */, 245 | 1A19920A9D1DEA3ECAF17675 /* LANAppViewController.m in Sources */, 246 | 1A19913A21A77F3698BA5F22 /* NSArray+LAN.m in Sources */, 247 | 1A1991AFE54A0FC9CD0473DD /* NSDictionary+LAN.m in Sources */, 248 | 1A199D4C0656B11F435557BF /* LANProListViewController.m in Sources */, 249 | 1A19913DBC063139E455FB1B /* LANProListCell.m in Sources */, 250 | 1A199B633E5859BFA2F9840F /* LANPathDisplayView.m in Sources */, 251 | ); 252 | runOnlyForDeploymentPostprocessing = 0; 253 | }; 254 | /* End PBXSourcesBuildPhase section */ 255 | 256 | /* Begin PBXVariantGroup section */ 257 | 1A199EF5E749068E073330A0 /* LaunchScreen.storyboard */ = { 258 | isa = PBXVariantGroup; 259 | children = ( 260 | 1A1994965A43007728F16861 /* Base */, 261 | ); 262 | name = LaunchScreen.storyboard; 263 | sourceTree = ""; 264 | }; 265 | /* End PBXVariantGroup section */ 266 | 267 | /* Begin XCBuildConfiguration section */ 268 | 1A19937A0CF58CBC2B2AB597 /* Debug */ = { 269 | isa = XCBuildConfiguration; 270 | buildSettings = { 271 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 272 | DEVELOPMENT_TEAM = MXJL78S842; 273 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 274 | GCC_PREFIX_HEADER = PrefixHeader.pch; 275 | INFOPLIST_FILE = AppBrowser/Info.plist; 276 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 277 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 278 | PRODUCT_BUNDLE_IDENTIFIER = com.lanvsblue.AppBrowser; 279 | PRODUCT_NAME = "$(TARGET_NAME)"; 280 | TARGETED_DEVICE_FAMILY = 1; 281 | }; 282 | name = Debug; 283 | }; 284 | 1A199709F4C3D1D2449008A9 /* Release */ = { 285 | isa = XCBuildConfiguration; 286 | buildSettings = { 287 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 288 | DEVELOPMENT_TEAM = MXJL78S842; 289 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 290 | GCC_PREFIX_HEADER = PrefixHeader.pch; 291 | INFOPLIST_FILE = AppBrowser/Info.plist; 292 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 293 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 294 | PRODUCT_BUNDLE_IDENTIFIER = com.lanvsblue.AppBrowser; 295 | PRODUCT_NAME = "$(TARGET_NAME)"; 296 | TARGETED_DEVICE_FAMILY = 1; 297 | }; 298 | name = Release; 299 | }; 300 | 1A1998BEFADADFF82EA8605C /* Debug */ = { 301 | isa = XCBuildConfiguration; 302 | buildSettings = { 303 | ALWAYS_SEARCH_USER_PATHS = NO; 304 | CLANG_ANALYZER_NONNULL = YES; 305 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 306 | CLANG_CXX_LIBRARY = "libc++"; 307 | CLANG_ENABLE_MODULES = YES; 308 | CLANG_ENABLE_OBJC_ARC = YES; 309 | CLANG_WARN_BOOL_CONVERSION = YES; 310 | CLANG_WARN_CONSTANT_CONVERSION = YES; 311 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 312 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 313 | CLANG_WARN_EMPTY_BODY = YES; 314 | CLANG_WARN_ENUM_CONVERSION = YES; 315 | CLANG_WARN_INFINITE_RECURSION = YES; 316 | CLANG_WARN_INT_CONVERSION = YES; 317 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 318 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 319 | CLANG_WARN_UNREACHABLE_CODE = YES; 320 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 321 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 322 | COPY_PHASE_STRIP = NO; 323 | DEBUG_INFORMATION_FORMAT = dwarf; 324 | ENABLE_STRICT_OBJC_MSGSEND = YES; 325 | ENABLE_TESTABILITY = YES; 326 | GCC_C_LANGUAGE_STANDARD = gnu99; 327 | GCC_DYNAMIC_NO_PIC = NO; 328 | GCC_NO_COMMON_BLOCKS = YES; 329 | GCC_OPTIMIZATION_LEVEL = 0; 330 | GCC_PREPROCESSOR_DEFINITIONS = ( 331 | "DEBUG=1", 332 | "$(inherited)", 333 | ); 334 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 335 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 336 | GCC_WARN_UNDECLARED_SELECTOR = YES; 337 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 338 | GCC_WARN_UNUSED_FUNCTION = YES; 339 | GCC_WARN_UNUSED_VARIABLE = YES; 340 | IPHONEOS_DEPLOYMENT_TARGET = 10.1; 341 | MTL_ENABLE_DEBUG_INFO = YES; 342 | ONLY_ACTIVE_ARCH = YES; 343 | SDKROOT = iphoneos; 344 | TARGETED_DEVICE_FAMILY = "1,2"; 345 | }; 346 | name = Debug; 347 | }; 348 | 1A199C3B61232BAACC376987 /* Release */ = { 349 | isa = XCBuildConfiguration; 350 | buildSettings = { 351 | ALWAYS_SEARCH_USER_PATHS = NO; 352 | CLANG_ANALYZER_NONNULL = YES; 353 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 354 | CLANG_CXX_LIBRARY = "libc++"; 355 | CLANG_ENABLE_MODULES = YES; 356 | CLANG_ENABLE_OBJC_ARC = YES; 357 | CLANG_WARN_BOOL_CONVERSION = YES; 358 | CLANG_WARN_CONSTANT_CONVERSION = YES; 359 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 360 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 361 | CLANG_WARN_EMPTY_BODY = YES; 362 | CLANG_WARN_ENUM_CONVERSION = YES; 363 | CLANG_WARN_INFINITE_RECURSION = YES; 364 | CLANG_WARN_INT_CONVERSION = YES; 365 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 366 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 367 | CLANG_WARN_UNREACHABLE_CODE = YES; 368 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 369 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 370 | COPY_PHASE_STRIP = NO; 371 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 372 | ENABLE_NS_ASSERTIONS = NO; 373 | ENABLE_STRICT_OBJC_MSGSEND = YES; 374 | GCC_C_LANGUAGE_STANDARD = gnu99; 375 | GCC_NO_COMMON_BLOCKS = YES; 376 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 377 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 378 | GCC_WARN_UNDECLARED_SELECTOR = YES; 379 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 380 | GCC_WARN_UNUSED_FUNCTION = YES; 381 | GCC_WARN_UNUSED_VARIABLE = YES; 382 | IPHONEOS_DEPLOYMENT_TARGET = 10.1; 383 | MTL_ENABLE_DEBUG_INFO = NO; 384 | SDKROOT = iphoneos; 385 | TARGETED_DEVICE_FAMILY = "1,2"; 386 | VALIDATE_PRODUCT = YES; 387 | }; 388 | name = Release; 389 | }; 390 | /* End XCBuildConfiguration section */ 391 | 392 | /* Begin XCConfigurationList section */ 393 | 1A1998425D1B08BE3DC10E8B /* Build configuration list for PBXNativeTarget "AppBrowser" */ = { 394 | isa = XCConfigurationList; 395 | buildConfigurations = ( 396 | 1A19937A0CF58CBC2B2AB597 /* Debug */, 397 | 1A199709F4C3D1D2449008A9 /* Release */, 398 | ); 399 | defaultConfigurationIsVisible = 0; 400 | defaultConfigurationName = Release; 401 | }; 402 | 1A1999ECC1DE83EE7CC8A61F /* Build configuration list for PBXProject "AppBrowser" */ = { 403 | isa = XCConfigurationList; 404 | buildConfigurations = ( 405 | 1A1998BEFADADFF82EA8605C /* Debug */, 406 | 1A199C3B61232BAACC376987 /* Release */, 407 | ); 408 | defaultConfigurationIsVisible = 0; 409 | defaultConfigurationName = Release; 410 | }; 411 | /* End XCConfigurationList section */ 412 | }; 413 | rootObject = 1A199A8FE21D4DA332F0F482 /* Project object */; 414 | } 415 | -------------------------------------------------------------------------------- /.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 16 | 17 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 60 | 61 | 92 | 93 | 94 | 95 | 96 | true 97 | DEFINITION_ORDER 98 | 99 | 100 | 101 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 138 | 139 | 142 | 143 | 144 | 145 | 148 | 149 | 152 | 153 | 156 | 157 | 158 | 159 | 162 | 163 | 166 | 167 | 170 | 171 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | project 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 234 | 235 | 236 | 237 | 1479977957989 238 | 262 | 263 | 264 | 265 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 305 | 308 | 309 | 310 | 312 | 313 | 314 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | -------------------------------------------------------------------------------- /.idea/ApplicationManager.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | --------------------------------------------------------------------------------