├── .gitignore ├── Categooey的高级使用.md ├── OCDeepLearning.xcodeproj ├── project.pbxproj └── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ └── IDEWorkspaceChecks.plist ├── OCDeepLearning ├── AClass.h ├── AClass.m ├── Animal.h ├── Animal.m ├── AppDelegate+Addtions.h ├── AppDelegate+Addtions.m ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json ├── BClass.h ├── BClass.m ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── BaseViewController.h ├── BaseViewController.m ├── Bird.h ├── Bird.m ├── BlockLearning.h ├── BlockLearning.m ├── CTMediator │ ├── CTMediator.h │ └── CTMediator.m ├── Category │ ├── LearnCategory+Addtion1.h │ ├── LearnCategory+Addtion1.m │ ├── LearnCategory+Addtion2.h │ ├── LearnCategory+Addtion2.m │ ├── LearnCategory.h │ ├── LearnCategory.m │ ├── NSObject+Additions.h │ └── NSObject+Additions.m ├── Course+CoreDataClass.h ├── Course+CoreDataClass.m ├── Course+CoreDataProperties.h ├── Course+CoreDataProperties.m ├── DPProtocol.h ├── DPViewController.h ├── DPViewController.m ├── GBRuntimeLog │ ├── NSObject+GBRuntimeLog.h │ └── NSObject+GBRuntimeLog.m ├── GCDLearning.h ├── GCDLearning.m ├── Grade+CoreDataClass.h ├── Grade+CoreDataClass.m ├── Grade+CoreDataProperties.h ├── Grade+CoreDataProperties.m ├── Info.plist ├── LearnDatasourceClass.h ├── LearnDatasourceClass.m ├── LearnInitializeBaseClass.h ├── LearnInitializeBaseClass.m ├── LearnInitializeChildClass.h ├── LearnInitializeChildClass.m ├── LearnInitializeFatherClass.h ├── LearnInitializeFatherClass.m ├── LearnSelfAndSuper.h ├── LearnSelfAndSuper.m ├── LearnUIWebView.h ├── LearnUIWebView.m ├── LearnWKWebView.h ├── LearnWKWebView.m ├── LearnWebViewController.h ├── LearnWebViewController.m ├── MainViewController.h ├── MainViewController.m ├── NSObject+Extension.h ├── NSObject+Extension.m ├── NSObject+MakeModel.h ├── NSObject+MakeModel.m ├── NSObject+PrivateMethod.h ├── NSObject+PrivateMethod.m ├── NSObject+Runtime.h ├── NSObject+Runtime.m ├── NSObject+a.h ├── New Group │ ├── CTMediator.h │ └── CTMediator.m ├── OCAutoReleasePool.h ├── OCAutoReleasePool.m ├── OCAutorelease.h ├── OCAutorelease.m ├── OCBaseCellModel.h ├── OCBaseCellModel.m ├── OCBaseManager.h ├── OCBaseManager.m ├── OCBaseTableViewCell+ConfigModel.h ├── OCBaseTableViewCell+ConfigModel.m ├── OCBaseTableViewCell.h ├── OCBaseTableViewCell.m ├── OCBaseTableViewController.h ├── OCBaseTableViewController.m ├── OCDLLayer.h ├── OCDLLayer.m ├── OCDLView.h ├── OCDLView.m ├── OCDataSourceManager.h ├── OCDataSourceManager.m ├── OCDeepLearning.xcdatamodeld │ └── OCDeepLearningModel.xcdatamodel │ │ └── contents ├── OCDeepLearningModel.xcdatamodeld │ └── OCDeepLearningModel.xcdatamodel │ │ └── contents ├── OCFuntionStyleViewController.h ├── OCFuntionStyleViewController.m ├── OCLearningOOP+GetPrivate.h ├── OCLearningOOP+GetPrivate.m ├── OCLearningOOP.h ├── OCLearningOOP.m ├── OCSaveDataTableViewController.h ├── OCSaveDataTableViewController.m ├── OCSaveManager.h ├── OCSaveManager.m ├── OC_AClass.h ├── OC_AClass.m ├── OC_IMP.h ├── OC_IMP.m ├── OC_Method.h ├── OC_Method.m ├── OC_Method.temp_caseinsensitive_rename.m ├── OC_SEL.h ├── OC_SEL.m ├── Person+ForwardMessage.h ├── Person+ForwardMessage.m ├── Person.h ├── Person.m ├── REDEMEProtocol.h ├── ReadMeNSObjcet.h ├── ReadMeNSObjcet.m ├── SecondTestViewController.h ├── SecondTestViewController.m ├── Student+CoreDataClass.h ├── Student+CoreDataClass.m ├── Student+CoreDataProperties.h ├── Student+CoreDataProperties.m ├── StudentDataManager.h ├── StudentDataManager.m ├── TestViewController.h ├── TestViewController.m ├── ThirdViewController.h ├── ThirdViewController.m ├── UserModel.h ├── UserModel.m ├── ViewController+SwizzlingMethod.h ├── ViewController+SwizzlingMethod.m ├── ViewController.h ├── ViewController.m ├── appletrace.h ├── appletrace.mm └── main.m ├── OCDeepLearningTests ├── Info.plist └── OCDeepLearningTests.m ├── OCDeepLearningUITests ├── Info.plist └── OCDeepLearningUITests.m ├── OCLearningNote.md ├── PrefixHeader.pch ├── README.md ├── SEL-IMP-Method解析.md ├── appletrace.framework ├── .gitignore ├── Info.plist └── appletrace ├── category的高级使用.md └── 消息转发流程.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xccheckout 23 | *.xcscmblueprint 24 | 25 | ## Obj-C/Swift specific 26 | *.hmap 27 | *.ipa 28 | *.dSYM.zip 29 | *.dSYM 30 | 31 | # CocoaPods 32 | # 33 | # We recommend against adding the Pods directory to your .gitignore. However 34 | # you should judge for yourself, the pros and cons are mentioned at: 35 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 36 | # 37 | # Pods/ 38 | # 39 | # Add this line if you want to avoid checking in source code from the Xcode workspace 40 | # *.xcworkspace 41 | 42 | # Carthage 43 | # 44 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 45 | # Carthage/Checkouts 46 | 47 | Carthage/Build 48 | 49 | # fastlane 50 | # 51 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 52 | # screenshots whenever they are needed. 53 | # For more information about the recommended setup visit: 54 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 55 | 56 | fastlane/report.xml 57 | fastlane/Preview.html 58 | fastlane/screenshots/**/*.png 59 | fastlane/test_output 60 | 61 | # Code Injection 62 | # 63 | # After new code Injection tools there's a generated folder /iOSInjectionProject 64 | # https://github.com/johnno1962/injectionforxcode 65 | 66 | iOSInjectionProject/ -------------------------------------------------------------------------------- /Categooey的高级使用.md: -------------------------------------------------------------------------------- 1 | # category的高级使用 2 | 3 | 4 | [toc] 5 | 6 | > Category是在`Objective-C 2.0`时提供的新的语言特性,其原因简单,不管类设计的多么完美,总有无法预测的状况,Category就是作为一种方式来扩展类的。 7 | 8 | 关于基础部分,网上很多相关文档可供查阅,此文不赘述。 9 | 作者只做分类的底层及高级用法作使用说明。 10 | 11 | ### 1. 分类为什么会覆盖掉类的同名方法,对应的类方法是不存在了么? 12 | 13 | ``` 14 | 1. category的方法没有“完全替换掉”原来类已经有的方法,也就是说如果category和原来类都有methodA,那么category附加完成之后,类的方法列表里会有两个methodA 15 | 2. category的方法被放到了新方法列表的前面,而原来类的方法被放到了新方法列表的后面,这也就是我们平常所说的category的方法会“覆盖”掉原来类的同名方法,这是因为运行时在查找方法的时候是顺着方法列表的顺序查找的,它只要一找到对应名字的方法,就会罢休^_^,殊不知后面可能还有一样名字的方法。 16 | ``` 17 | ### 2. 怎么解除分类对类方法的覆盖? 18 | 19 | ``` 20 | /* 21 | 怎么调用到原来类中被category覆盖掉的方法? 22 | 对于这个问题,我们已经知道category其实并不是完全替换掉原来类的同名方法,只是category在方法列表的前面而已,所以我们只要顺着方法列表找到最后一个对应名字的方法,就可以调用原来类的方法: 23 | */ 24 | + (void)useClassMethodInsteadCayegoryMethod: (SEL)seletor { 25 | 26 | if (self) { 27 | unsigned int methodCount; 28 | Method *methodList = class_copyMethodList([self class], &methodCount); 29 | IMP lastImp = NULL; 30 | SEL lastSel = NULL; 31 | for (NSInteger i = 0; i < methodCount; i++) { 32 | Method method = methodList[i]; 33 | NSString *methodName = [NSString stringWithCString:sel_getName(method_getName(method)) 34 | encoding:NSUTF8StringEncoding]; 35 | NSString *selectorName = NSStringFromSelector(seletor); 36 | if ([selectorName isEqualToString:methodName]) { 37 | lastImp = method_getImplementation(method); 38 | lastSel = method_getName(method); 39 | } 40 | } 41 | typedef void (*fn)(id,SEL); 42 | 43 | if (lastImp != NULL) { 44 | fn f = (fn)lastImp; 45 | f(self,lastSel); 46 | } 47 | free(methodList); 48 | } 49 | } 50 | ``` 51 | 52 | ### 3.category怎么关联对象的? 53 | ``` 54 | #import 55 | #import "LearnCategoryClass.h" 56 | 57 | @interface LearnCategoryClass (Addition) 58 | 59 | @property(nonatomic, strong) NSString *newName; 60 | 61 | ``` 62 | ------- 63 | 64 | ``` 65 | 66 | #import "LearnCategoryClass+Addition.h" 67 | #import 68 | 69 | @implementation LearnCategoryClass (Addition) 70 | 71 | - (void)testCategory { 72 | NSLog(@"分类里是%@,方法名是%s",[self class], __PRETTY_FUNCTION__); 73 | } 74 | 75 | //运行时动态添加set和get方法(Xcode9 更新了提醒功能,超级牛逼。比如此处在分类里声明了属性,但不添加set/get方法会warnning,这里说下,厉害了我的苹果) 76 | - (void)setNewName:(NSString *)newName 77 | { 78 | objc_setAssociatedObject(self, 79 | "newName", 80 | newName, 81 | OBJC_ASSOCIATION_COPY); 82 | } 83 | 84 | - (NSString*)newName 85 | { 86 | NSString *nameObject = objc_getAssociatedObject(self, "newName"); 87 | return nameObject; 88 | } 89 | @end 90 | ``` 91 | 92 | 93 | ### 4.多个category,哪个方法优先执行? 94 | 好吧,这其实不是一个问题,是一串问题。 95 | 可以分为: 96 | > 1. category里的方法是什么时候注册到Class的`method_list`的,在`+load`阶段么? 97 | 2. 如果有多个category,怎么办? 98 | 99 | 我们知道,在类class和category中都可以有`+load`方法,那么有两个问题: 100 | > 1. 在class的`+load`方法调用的时候,我们可以调用category中声明的方法么? 101 | 2. 这么多个`+load`方法,调用顺序是咋样的呢? 102 | 103 | -------- 104 | 105 | >答案是 106 | 1. 可以调用,而且附加category到类的工作会先于`+load`方法的执行; 107 | 2. `+load`的执行顺序是先class,后category,而category的`+load`执行顺序是根据编译顺序决定的。 108 | 109 | 可以这么理解方法的调用。 110 | 有一个类似有压栈入栈的栈结构,先把class里的methodA添加到methodList中,然后添加分类中的方法,编译器会从上到下找分类,先找到的分类就先放入methodList中,后找到的就后放入。 111 | 所以最终形成了一个Class里的方法在最底层,最后编译的分类在最上层的栈结构。 112 | 而方法的调用是从上到下执行的,冉调用对应的方法,就会从methodList里找对应的SEL,找到就停止,所以Class和前面便轻易的分类虽然都在methodList里,但因为找到了就不会继续查找。 113 | 以上就是方法掉用顺序的原理。 114 | 当然,编译顺序可以在 `Build Phases`里的`Compile Source`里修改。 115 | 116 | ## 奇葩问答: 117 | 118 | * 如果在分类里声明了,但不实现,`method_list`里不会有,当然也不会调用分类方法。但若是实现了,即使不在.h文件声明,也会调用分类的方法; 119 | * 如果分类里是`- (void)testCategory`,而Class里是`- (int)testCategory`;返回值不同,也会覆盖,因为虽然返回值不同,但OC里,这两者依然是一个方法。 120 | * 对于多个分类,方法的调用是执行最后编译的分类方法; 121 | 122 | 123 | ------- 124 | ## 文末 125 | 关于category及其OC的深入研究,请转移到[Github—>OCDeepLearning](https://github.com/walkertop/OCDeepLearning) 126 | 欢迎star和issues参与讨论。 127 | 128 | 129 | 130 | 之于category的更底层实现,可以参照:[参考文章](https://tech.meituan.com/DiveIntoCategory.html) 131 | 132 | 133 | 134 | 135 | -------------------------------------------------------------------------------- /OCDeepLearning.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /OCDeepLearning.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /OCDeepLearning/AClass.h: -------------------------------------------------------------------------------- 1 | // 2 | // AClass.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2017/7/10. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "BClass.h" 11 | 12 | @interface AClass : NSObject 13 | 14 | @property(nonatomic, copy) NSString *Aname; 15 | 16 | + (void)load; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /OCDeepLearning/AClass.m: -------------------------------------------------------------------------------- 1 | // 2 | // AClass.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2017/7/10. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "AClass.h" 10 | 11 | @implementation AClass 12 | 13 | + (void)load { 14 | // BClass *b = [[BClass alloc] init]; 15 | // NSLog(@"%@",b); 16 | // NSLog(@"当前类是%@",[self class]); 17 | } 18 | 19 | + (void)initialize { 20 | // BClass *b = [[BClass alloc] init]; 21 | // NSLog(@"%@",b); 22 | // NSLog(@"当前类是%@",[self class]); 23 | } 24 | @end 25 | -------------------------------------------------------------------------------- /OCDeepLearning/Animal.h: -------------------------------------------------------------------------------- 1 | // 2 | // Animal.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2017/7/13. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface Animal : NSObject 12 | - (void)swim; 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /OCDeepLearning/Animal.m: -------------------------------------------------------------------------------- 1 | // 2 | // Animal.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2017/7/13. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "Animal.h" 10 | #import 11 | 12 | @implementation Animal 13 | 14 | /** 15 | 手动添加swim方法,在resolveInstanceMethod里,添加swim 16 | */ 17 | void swim(id self,SEL _cmd) { 18 | NSLog(@"消息转发时增加了swim方法"); 19 | } 20 | + (BOOL)resolveInstanceMethod:(SEL)sel { 21 | if (sel == NSSelectorFromString(@"swim")) { 22 | class_addMethod(self, @selector(swim), swim, "v@:@"); 23 | return YES; 24 | } 25 | return [super resolveInstanceMethod:sel]; 26 | } 27 | 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /OCDeepLearning/AppDelegate+Addtions.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate+Addtions.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/6/5. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate (Addtions) 12 | 13 | 14 | - (void)setupRootVC; 15 | 16 | //- (void)configCoreData; 17 | @end 18 | -------------------------------------------------------------------------------- /OCDeepLearning/AppDelegate+Addtions.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate+Addtions.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/6/5. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate+Addtions.h" 10 | #import "TestViewController.h" 11 | #import "OCBaseTableViewController.h" 12 | #import "MainViewController.h" 13 | #import "ThirdViewController.h" 14 | #import "OCFuntionStyleViewController.h" 15 | #import "ViewController.h" 16 | 17 | //@interface AppDelegate (Addtions) 18 | // 19 | //@property (nonatomic, readwrite, strong) NSManagedObjectModel *managedObjectModel; 20 | // 21 | //@end 22 | 23 | 24 | @implementation AppDelegate (Addtions) 25 | 26 | - (void)setupRootVC { 27 | UITabBarController *tabbarVC = [[UITabBarController alloc] init]; 28 | UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:tabbarVC]; 29 | 30 | // MainViewController *firstVC = [[MainViewController alloc] init]; 31 | // firstVC.view.backgroundColor = [UIColor grayColor]; 32 | 33 | ViewController *firstVC = [[ViewController alloc] init]; 34 | firstVC.title = @"测试list"; 35 | 36 | // UITableViewController *secondTableVC = [[OCBaseTableViewController alloc] initWithStyle:UITableViewStylePlain]; 37 | // secondTableVC.title = @"第二页"; 38 | 39 | OCFuntionStyleViewController *funtionStyleVC = [[OCFuntionStyleViewController alloc] init]; 40 | funtionStyleVC.title = @"功能"; 41 | 42 | TestViewController *testVC = [[TestViewController alloc] init]; 43 | testVC.title = @"Test"; 44 | testVC.navigationController.title = @"TEST"; 45 | tabbarVC.navigationController.title = @"dsd"; 46 | 47 | ThirdViewController *thirdVC = [[ThirdViewController alloc] init]; 48 | thirdVC.title = @"第三页"; 49 | 50 | tabbarVC.viewControllers = @[firstVC,funtionStyleVC,thirdVC,testVC]; 51 | 52 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 53 | self.window.rootViewController = nav; 54 | [self.window makeKeyAndVisible]; 55 | } 56 | 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /OCDeepLearning/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2017/7/7. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /OCDeepLearning/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2017/7/7. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "AppDelegate+Addtions.h" 11 | #import 12 | #import "CTMediator.h" 13 | 14 | 15 | 16 | 17 | @interface AppDelegate () 18 | 19 | //@property(nonatomic, strong) NSManagedObjectModel *managedObjectModel; 20 | //@property(nonatomic, strong) NSPersistentStoreCoordinator *persistentStoreCoordinator; 21 | 22 | @end 23 | 24 | @implementation AppDelegate 25 | 26 | 27 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 28 | // Override point for customization after application launch. 29 | 30 | [self setupRootVC]; 31 | return YES; 32 | } 33 | 34 | 35 | - (void)applicationWillResignActive:(UIApplication *)application { 36 | // 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. 37 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 38 | } 39 | 40 | 41 | - (void)applicationDidEnterBackground:(UIApplication *)application { 42 | // 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. 43 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 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 | - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary *)options 62 | { 63 | return [[[CTMediator sharedInstance] performActionWithUrl:url completion:nil] boolValue]; 64 | } 65 | 66 | 67 | 68 | #pragma mark - privete method 69 | 70 | 71 | @end 72 | -------------------------------------------------------------------------------- /OCDeepLearning/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 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /OCDeepLearning/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /OCDeepLearning/BClass.h: -------------------------------------------------------------------------------- 1 | // 2 | // BClass.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2017/7/10. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface BClass : NSObject 12 | 13 | + (void)load; 14 | @end 15 | -------------------------------------------------------------------------------- /OCDeepLearning/BClass.m: -------------------------------------------------------------------------------- 1 | // 2 | // BClass.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2017/7/10. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "BClass.h" 10 | #import "AClass.h" 11 | #import "ViewController.h" 12 | 13 | @implementation BClass 14 | 15 | + (void)load{ 16 | // NSLog(@"-----这事BClass的Load方法-------"); 17 | // AClass *a = [[AClass alloc] init]; 18 | // NSLog(@"%@",a); 19 | // a.Aname = @"A的新值"; 20 | // [a setAname:@"ddd"]; 21 | // NSLog(@"当前类是%@",[self class]); 22 | // 23 | // ViewController *vc = [[ViewController alloc] init]; 24 | // [vc.view setBackgroundColor: [UIColor yellowColor]]; 25 | // 26 | // NSMutableArray *array = [NSMutableArray array]; 27 | // 28 | // [array addObject:vc]; 29 | // NSLog(@"数组的内容是%@",array); 30 | 31 | } 32 | 33 | + (void)initialize { 34 | // NSLog(@"-----这事BClass的initialize方法-------"); 35 | // AClass *a = [[AClass alloc] init]; 36 | // NSLog(@"%@",a); 37 | // a.Aname = @"A的initialize方法"; 38 | // [a setAname:@"ddd"]; 39 | // NSLog(@"当前类是%@",[self class]); 40 | } 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /OCDeepLearning/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 | -------------------------------------------------------------------------------- /OCDeepLearning/Base.lproj/Main.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 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /OCDeepLearning/BaseViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // BaseViewController.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/6/26. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface BaseViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /OCDeepLearning/BaseViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // BaseViewController.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/6/26. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "BaseViewController.h" 10 | 11 | @interface BaseViewController () 12 | 13 | @end 14 | 15 | @implementation BaseViewController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | // Do any additional setup after loading the view. 20 | } 21 | 22 | - (void)didReceiveMemoryWarning { 23 | [super didReceiveMemoryWarning]; 24 | // Dispose of any resources that can be recreated. 25 | } 26 | 27 | /* 28 | #pragma mark - Navigation 29 | 30 | // In a storyboard-based application, you will often want to do a little preparation before navigation 31 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 32 | // Get the new view controller using [segue destinationViewController]. 33 | // Pass the selected object to the new view controller. 34 | } 35 | */ 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /OCDeepLearning/Bird.h: -------------------------------------------------------------------------------- 1 | // 2 | // Bird.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2017/7/13. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface Bird : NSObject 12 | 13 | - (void)fly; 14 | @end 15 | -------------------------------------------------------------------------------- /OCDeepLearning/Bird.m: -------------------------------------------------------------------------------- 1 | // 2 | // Bird.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2017/7/13. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "Bird.h" 10 | 11 | @implementation Bird 12 | 13 | -(void)fly { 14 | NSLog(@"小鸟fly"); 15 | } 16 | @end 17 | -------------------------------------------------------------------------------- /OCDeepLearning/BlockLearning.h: -------------------------------------------------------------------------------- 1 | // 2 | // BlockLearning.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/8/14. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef int(^OCIntBlock)(int a, int b); 12 | 13 | @interface BlockLearning : NSObject 14 | 15 | @property(nonatomic, assign) OCIntBlock intblock; 16 | 17 | + (instancetype)sharedInstance; 18 | 19 | - (void)testBlockLearning; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /OCDeepLearning/BlockLearning.m: -------------------------------------------------------------------------------- 1 | // 2 | // BlockLearning.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/8/14. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "BlockLearning.h" 10 | 11 | @interface BlockLearning () 12 | 13 | @property(nonatomic, copy) NSArray *intArray; 14 | 15 | 16 | @end 17 | 18 | @implementation BlockLearning 19 | 20 | + (instancetype)sharedInstance { 21 | static BlockLearning *sharedInstance = nil; 22 | static dispatch_once_t onceToken; 23 | dispatch_once(&onceToken, ^{ 24 | sharedInstance = [[self alloc] init]; 25 | }); 26 | return sharedInstance; 27 | } 28 | 29 | - (void)testBlockLearning { 30 | 31 | int (^testBlock)(int a, int b) = ^(int a, int b) { 32 | return a + b; 33 | }; 34 | 35 | self.intblock = ^int(int a, int b) { 36 | return a - b; 37 | }; 38 | 39 | int sum = testBlock(3,4); 40 | int all = self.intblock(5,6); 41 | NSLog(@"sum的值%d,all的值%d",sum, all); 42 | } 43 | 44 | 45 | /* 46 | * block根据内存分布,有三种类型: 47 | 1. 堆区block 48 | 2. 栈区block 49 | 3. 全局区block 50 | 51 | */ 52 | 53 | - (void)learnBlockMemeryLayout { 54 | 55 | 56 | } 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /OCDeepLearning/CTMediator/CTMediator.h: -------------------------------------------------------------------------------- 1 | // 2 | // CTMediator.h 3 | // CTMediator 4 | // 5 | // Created by casa on 16/3/13. 6 | // Copyright © 2016年 casa. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface CTMediator : NSObject 12 | 13 | + (instancetype)sharedInstance; 14 | 15 | // 远程App调用入口 16 | - (id)performActionWithUrl:(NSURL *)url completion:(void(^)(NSDictionary *info))completion; 17 | // 本地组件调用入口 18 | - (id)performTarget:(NSString *)targetName action:(NSString *)actionName params:(NSDictionary *)params shouldCacheTarget:(BOOL)shouldCacheTarget; 19 | - (void)releaseCachedTargetWithTargetName:(NSString *)targetName; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /OCDeepLearning/CTMediator/CTMediator.m: -------------------------------------------------------------------------------- 1 | // 2 | // CTMediator.m 3 | // CTMediator 4 | // 5 | // Created by casa on 16/3/13. 6 | // Copyright © 2016年 casa. All rights reserved. 7 | // 8 | 9 | #import "CTMediator.h" 10 | #import 11 | 12 | @interface CTMediator () 13 | 14 | @property (nonatomic, strong) NSMutableDictionary *cachedTarget; 15 | 16 | @end 17 | 18 | @implementation CTMediator 19 | 20 | #pragma mark - public methods 21 | + (instancetype)sharedInstance 22 | { 23 | static CTMediator *mediator; 24 | static dispatch_once_t onceToken; 25 | dispatch_once(&onceToken, ^{ 26 | mediator = [[CTMediator alloc] init]; 27 | }); 28 | return mediator; 29 | } 30 | 31 | /* 32 | scheme://[target]/[action]?[params] 33 | 34 | url sample: 35 | aaa://targetA/actionB?id=1234 36 | */ 37 | 38 | - (id)performActionWithUrl:(NSURL *)url completion:(void (^)(NSDictionary *))completion 39 | { 40 | NSMutableDictionary *params = [[NSMutableDictionary alloc] init]; 41 | NSString *urlString = [url query]; 42 | for (NSString *param in [urlString componentsSeparatedByString:@"&"]) { 43 | NSArray *elts = [param componentsSeparatedByString:@"="]; 44 | if([elts count] < 2) continue; 45 | [params setObject:[elts lastObject] forKey:[elts firstObject]]; 46 | } 47 | 48 | // 这里这么写主要是出于安全考虑,防止黑客通过远程方式调用本地模块。这里的做法足以应对绝大多数场景,如果要求更加严苛,也可以做更加复杂的安全逻辑。 49 | NSString *actionName = [url.path stringByReplacingOccurrencesOfString:@"/" withString:@""]; 50 | if ([actionName hasPrefix:@"native"]) { 51 | return @(NO); 52 | } 53 | 54 | // 这个demo针对URL的路由处理非常简单,就只是取对应的target名字和method名字,但这已经足以应对绝大部份需求。如果需要拓展,可以在这个方法调用之前加入完整的路由逻辑 55 | id result = [self performTarget:url.host action:actionName params:params shouldCacheTarget:NO]; 56 | if (completion) { 57 | if (result) { 58 | completion(@{@"result":result}); 59 | } else { 60 | completion(nil); 61 | } 62 | } 63 | return result; 64 | } 65 | 66 | - (id)performTarget:(NSString *)targetName action:(NSString *)actionName params:(NSDictionary *)params shouldCacheTarget:(BOOL)shouldCacheTarget 67 | { 68 | 69 | NSString *targetClassString = [NSString stringWithFormat:@"Target_%@", targetName]; 70 | NSString *actionString = [NSString stringWithFormat:@"Action_%@:", actionName]; 71 | Class targetClass; 72 | 73 | NSObject *target = self.cachedTarget[targetClassString]; 74 | if (target == nil) { 75 | targetClass = NSClassFromString(targetClassString); 76 | target = [[targetClass alloc] init]; 77 | } 78 | 79 | SEL action = NSSelectorFromString(actionString); 80 | 81 | if (target == nil) { 82 | // 这里是处理无响应请求的地方之一,这个demo做得比较简单,如果没有可以响应的target,就直接return了。实际开发过程中是可以事先给一个固定的target专门用于在这个时候顶上,然后处理这种请求的 83 | [self NoTargetActionResponseWithTargetString:targetClassString selectorString:actionString originParams:params]; 84 | return nil; 85 | } 86 | 87 | if (shouldCacheTarget) { 88 | self.cachedTarget[targetClassString] = target; 89 | } 90 | 91 | if ([target respondsToSelector:action]) { 92 | return [self safePerformAction:action target:target params:params]; 93 | } else { 94 | // 有可能target是Swift对象 95 | actionString = [NSString stringWithFormat:@"Action_%@WithParams:", actionName]; 96 | action = NSSelectorFromString(actionString); 97 | if ([target respondsToSelector:action]) { 98 | return [self safePerformAction:action target:target params:params]; 99 | } else { 100 | // 这里是处理无响应请求的地方,如果无响应,则尝试调用对应target的notFound方法统一处理 101 | SEL action = NSSelectorFromString(@"notFound:"); 102 | if ([target respondsToSelector:action]) { 103 | return [self safePerformAction:action target:target params:params]; 104 | } else { 105 | // 这里也是处理无响应请求的地方,在notFound都没有的时候,这个demo是直接return了。实际开发过程中,可以用前面提到的固定的target顶上的。 106 | [self NoTargetActionResponseWithTargetString:targetClassString selectorString:actionString originParams:params]; 107 | [self.cachedTarget removeObjectForKey:targetClassString]; 108 | return nil; 109 | } 110 | } 111 | } 112 | } 113 | 114 | - (void)releaseCachedTargetWithTargetName:(NSString *)targetName 115 | { 116 | NSString *targetClassString = [NSString stringWithFormat:@"Target_%@", targetName]; 117 | [self.cachedTarget removeObjectForKey:targetClassString]; 118 | } 119 | 120 | #pragma mark - private methods 121 | - (void)NoTargetActionResponseWithTargetString:(NSString *)targetString selectorString:(NSString *)selectorString originParams:(NSDictionary *)originParams 122 | { 123 | SEL action = NSSelectorFromString(@"Action_response:"); 124 | NSObject *target = [[NSClassFromString(@"Target_NoTargetAction") alloc] init]; 125 | 126 | NSMutableDictionary *params = [[NSMutableDictionary alloc] init]; 127 | params[@"originParams"] = originParams; 128 | params[@"targetString"] = targetString; 129 | params[@"selectorString"] = selectorString; 130 | 131 | [self safePerformAction:action target:target params:params]; 132 | } 133 | 134 | - (id)safePerformAction:(SEL)action target:(NSObject *)target params:(NSDictionary *)params 135 | { 136 | NSMethodSignature* methodSig = [target methodSignatureForSelector:action]; 137 | if(methodSig == nil) { 138 | return nil; 139 | } 140 | const char* retType = [methodSig methodReturnType]; 141 | 142 | if (strcmp(retType, @encode(void)) == 0) { 143 | NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig]; 144 | [invocation setArgument:¶ms atIndex:2]; 145 | [invocation setSelector:action]; 146 | [invocation setTarget:target]; 147 | [invocation invoke]; 148 | return nil; 149 | } 150 | 151 | if (strcmp(retType, @encode(NSInteger)) == 0) { 152 | NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig]; 153 | [invocation setArgument:¶ms atIndex:2]; 154 | [invocation setSelector:action]; 155 | [invocation setTarget:target]; 156 | [invocation invoke]; 157 | NSInteger result = 0; 158 | [invocation getReturnValue:&result]; 159 | return @(result); 160 | } 161 | 162 | if (strcmp(retType, @encode(BOOL)) == 0) { 163 | NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig]; 164 | [invocation setArgument:¶ms atIndex:2]; 165 | [invocation setSelector:action]; 166 | [invocation setTarget:target]; 167 | [invocation invoke]; 168 | BOOL result = 0; 169 | [invocation getReturnValue:&result]; 170 | return @(result); 171 | } 172 | 173 | if (strcmp(retType, @encode(CGFloat)) == 0) { 174 | NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig]; 175 | [invocation setArgument:¶ms atIndex:2]; 176 | [invocation setSelector:action]; 177 | [invocation setTarget:target]; 178 | [invocation invoke]; 179 | CGFloat result = 0; 180 | [invocation getReturnValue:&result]; 181 | return @(result); 182 | } 183 | 184 | if (strcmp(retType, @encode(NSUInteger)) == 0) { 185 | NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig]; 186 | [invocation setArgument:¶ms atIndex:2]; 187 | [invocation setSelector:action]; 188 | [invocation setTarget:target]; 189 | [invocation invoke]; 190 | NSUInteger result = 0; 191 | [invocation getReturnValue:&result]; 192 | return @(result); 193 | } 194 | 195 | #pragma clang diagnostic push 196 | #pragma clang diagnostic ignored "-Warc-performSelector-leaks" 197 | return [target performSelector:action withObject:params]; 198 | #pragma clang diagnostic pop 199 | } 200 | 201 | #pragma mark - getters and setters 202 | - (NSMutableDictionary *)cachedTarget 203 | { 204 | if (_cachedTarget == nil) { 205 | _cachedTarget = [[NSMutableDictionary alloc] init]; 206 | } 207 | return _cachedTarget; 208 | } 209 | 210 | @end 211 | -------------------------------------------------------------------------------- /OCDeepLearning/Category/LearnCategory+Addtion1.h: -------------------------------------------------------------------------------- 1 | // 2 | // LearnCategory+Addtion1.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2017/7/26. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "LearnCategory.h" 10 | 11 | @interface LearnCategory (Addtion1) 12 | @property(nonatomic, strong) NSString *newName; 13 | //- (void)testCategory; //即使不声明,也依然会调用 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /OCDeepLearning/Category/LearnCategory+Addtion1.m: -------------------------------------------------------------------------------- 1 | // 2 | // LearnCategory+Addtion1.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2017/7/26. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "LearnCategory+Addtion1.h" 10 | #import 11 | 12 | @implementation LearnCategory (Addtion1) 13 | 14 | - (void)testCategory { 15 | NSLog(@"第一个分类的名字是%@,方法名称为%s",[self class], __func__); 16 | } 17 | 18 | //运行时动态添加set和get方法(Xcode9 更新了提醒功能,超级牛逼。比如此处在分类里声明了属性,但不添加set/get方法会warnning,这里说下,厉害了我的苹果) 19 | - (void)setNewName:(NSString *)newName 20 | { 21 | objc_setAssociatedObject(self, 22 | "newName", 23 | newName, 24 | OBJC_ASSOCIATION_COPY); 25 | } 26 | 27 | - (NSString*)newName 28 | { 29 | NSString *nameObject = objc_getAssociatedObject(self, "newName"); 30 | return nameObject; 31 | } 32 | @end 33 | -------------------------------------------------------------------------------- /OCDeepLearning/Category/LearnCategory+Addtion2.h: -------------------------------------------------------------------------------- 1 | // 2 | // LearnCategory+Addtion2.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2017/7/26. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "LearnCategory.h" 10 | 11 | @interface LearnCategory (Addtion2) 12 | - (void)testCategory; 13 | @end 14 | -------------------------------------------------------------------------------- /OCDeepLearning/Category/LearnCategory+Addtion2.m: -------------------------------------------------------------------------------- 1 | // 2 | // LearnCategory+Addtion2.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2017/7/26. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "LearnCategory+Addtion2.h" 10 | 11 | @implementation LearnCategory (Addtion2) 12 | - (void)testCategory { 13 | NSLog(@"第二个分类的名字是%@,方法名称为%s",[self class], __func__); 14 | } 15 | @end 16 | -------------------------------------------------------------------------------- /OCDeepLearning/Category/LearnCategory.h: -------------------------------------------------------------------------------- 1 | // 2 | // LearnCategory.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2017/7/26. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface LearnCategory : NSObject 12 | 13 | @property(nonatomic, strong) NSString *name; 14 | 15 | - (void)testCategory; 16 | @end 17 | -------------------------------------------------------------------------------- /OCDeepLearning/Category/LearnCategory.m: -------------------------------------------------------------------------------- 1 | // 2 | // LearnCategory.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2017/7/26. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "LearnCategory.h" 10 | 11 | @implementation LearnCategory 12 | 13 | - (void)testCategory { 14 | NSLog(@"本类的名字是%@,方法名称为%s",[self class], __func__); 15 | } 16 | @end 17 | -------------------------------------------------------------------------------- /OCDeepLearning/Category/NSObject+Additions.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+Additions.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2018/7/29. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSObject (Additions) 12 | 13 | //- (void)doesNotRecognizeSelector:(SEL)aSelector; 14 | @end 15 | -------------------------------------------------------------------------------- /OCDeepLearning/Category/NSObject+Additions.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+Additions.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2018/7/29. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "NSObject+Additions.h" 10 | 11 | @implementation NSObject (Additions) 12 | 13 | 14 | - (void)oc_viewDidLoad { 15 | [self oc_viewDidLoad]; 16 | NSLog(@"类的名字是%@",self); 17 | } 18 | 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /OCDeepLearning/Course+CoreDataClass.h: -------------------------------------------------------------------------------- 1 | // 2 | // Course+CoreDataClass.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/6/22. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | // 9 | 10 | #import 11 | #import 12 | 13 | @class Student; 14 | 15 | NS_ASSUME_NONNULL_BEGIN 16 | 17 | @interface Course : NSManagedObject 18 | 19 | @end 20 | 21 | NS_ASSUME_NONNULL_END 22 | 23 | #import "Course+CoreDataProperties.h" 24 | -------------------------------------------------------------------------------- /OCDeepLearning/Course+CoreDataClass.m: -------------------------------------------------------------------------------- 1 | // 2 | // Course+CoreDataClass.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/6/22. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | // 9 | 10 | #import "Course+CoreDataClass.h" 11 | 12 | @implementation Course 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /OCDeepLearning/Course+CoreDataProperties.h: -------------------------------------------------------------------------------- 1 | // 2 | // Course+CoreDataProperties.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/6/22. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | // 9 | 10 | #import "Course+CoreDataClass.h" 11 | 12 | 13 | NS_ASSUME_NONNULL_BEGIN 14 | 15 | @interface Course (CoreDataProperties) 16 | 17 | + (NSFetchRequest *)fetchRequest; 18 | 19 | @property (nullable, nonatomic, copy) NSString *courseName; 20 | @property (nullable, nonatomic, copy) NSString *courseID; 21 | @property (nullable, nonatomic, retain) Student *courseStudent; 22 | 23 | @end 24 | 25 | NS_ASSUME_NONNULL_END 26 | -------------------------------------------------------------------------------- /OCDeepLearning/Course+CoreDataProperties.m: -------------------------------------------------------------------------------- 1 | // 2 | // Course+CoreDataProperties.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/6/22. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | // 9 | 10 | #import "Course+CoreDataProperties.h" 11 | 12 | @implementation Course (CoreDataProperties) 13 | 14 | + (NSFetchRequest *)fetchRequest { 15 | return [[NSFetchRequest alloc] initWithEntityName:@"Course"]; 16 | } 17 | 18 | @dynamic courseName; 19 | @dynamic courseID; 20 | @dynamic courseStudent; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /OCDeepLearning/DPProtocol.h: -------------------------------------------------------------------------------- 1 | // 2 | // DPProtocol.h 3 | // OCDeepLearning 4 | // 5 | // Created by 郭彬 on 2020/3/24. 6 | // Copyright © 2020 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @protocol DPProtocol 14 | 15 | - (void)didSelected: (NSString *) name; 16 | - (Int)selectedIndex: (NSIndexPath *)indexPath; 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /OCDeepLearning/DPViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // DPViewController.h 3 | // OCDeepLearning 4 | // 5 | // Created by 郭彬 on 2020/3/24. 6 | // Copyright © 2020 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface DPViewController : UIViewController 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /OCDeepLearning/DPViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // DPViewController.m 3 | // OCDeepLearning 4 | // 5 | // Created by 郭彬 on 2020/3/24. 6 | // Copyright © 2020 walker彬. All rights reserved. 7 | // 8 | 9 | #import "DPViewController.h" 10 | 11 | @interface DPViewController () 12 | 13 | @property (nonatomic, strong) UITableView *tableView; 14 | 15 | @end 16 | 17 | @implementation DPViewController 18 | 19 | - (void)viewDidLoad { 20 | [super viewDidLoad]; 21 | // Do any additional setup after loading the view. 22 | [self setupUI]; 23 | } 24 | 25 | 26 | - (void)setupUI { 27 | self.tableView.frame = self.view.bounds; 28 | [self.view addSubview: self.tableView]; 29 | } 30 | 31 | - (UITableView *)tableView { 32 | UITableView *tableView = [[UITableView alloc] initWithFrame: CGRectZero style: UITableViewStylePlain]; 33 | tableView.rowHeight = 50; 34 | [tableView registerClass: [UITableViewCell class] forCellReuseIdentifier: @"dddd"]; 35 | tableView.delegate = self; 36 | tableView.dataSource = self; 37 | return tableView; 38 | } 39 | 40 | /* 41 | 42 | #pragma mark - Navigation 43 | 44 | // In a storyboard-based application, you will often want to do a little preparation before navigation 45 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 46 | // Get the new view controller using [segue destinationViewController]. 47 | // Pass the selected object to the new view controller. 48 | } 49 | */ 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /OCDeepLearning/GBRuntimeLog/NSObject+GBRuntimeLog.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+GBRuntimeLog.h 3 | // GBRuntime 4 | // 5 | // Created by walker彬 on 2017/7/5. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSObject (GBRuntimeLog) 12 | 13 | + (NSArray *)classes; //获取当前类 14 | + (NSArray *)properties; //获取所有属性 (获取属性) 15 | + (NSArray *)instanceVariables; //获取实例变量 (可以获取私有成员变量) 16 | 17 | + (NSArray *)classMethods; //获取类方法 (可以获取私有方法) 18 | + (NSArray *)instanceMethods; //获取实例方法 (可以获取私有方法) 19 | + (NSArray *)methodLists; //获取所有的方法列表 20 | 21 | + (NSArray *)protocols; //获取协议 22 | + (NSDictionary *)descriptionForProtocol:(Protocol *)proto; //获取某个协议的描述 23 | 24 | + (NSString *)parentClassHierarchy; //获取继承链条 25 | @end 26 | -------------------------------------------------------------------------------- /OCDeepLearning/GBRuntimeLog/NSObject+GBRuntimeLog.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+GBRuntimeLog.m 3 | // GBRuntime 4 | // 5 | // Created by walker彬 on 2017/7/5. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "NSObject+GBRuntimeLog.h" 10 | #import 11 | 12 | 13 | @interface NSString (GBRuntimeLog) 14 | 15 | + (NSString *)decodeType:(const char *)cString; 16 | 17 | @end 18 | 19 | @implementation NSObject (GBRuntimeLog) 20 | 21 | //https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html 22 | + (NSString *)decodeType:(const char *)cString { 23 | if (!strcmp(cString, @encode(id))) return @"id"; 24 | if (!strcmp(cString, @encode(void))) return @"void"; 25 | if (!strcmp(cString, @encode(float))) return @"float"; 26 | if (!strcmp(cString, @encode(int))) return @"int"; 27 | if (!strcmp(cString, @encode(BOOL))) return @"BOOL"; 28 | if (!strcmp(cString, @encode(char *))) return @"char *"; 29 | if (!strcmp(cString, @encode(double))) return @"double"; 30 | if (!strcmp(cString, @encode(Class))) return @"class"; 31 | if (!strcmp(cString, @encode(SEL))) return @"SEL"; 32 | if (!strcmp(cString, @encode(unsigned int))) return @"unsigned int"; 33 | 34 | //@TODO: do handle bitmasks 35 | NSString *result = [NSString stringWithCString:cString encoding:NSUTF8StringEncoding]; 36 | if ([[result substringToIndex:1] isEqualToString:@"@"] && [result rangeOfString:@"?"].location == NSNotFound) { 37 | result = [[result substringWithRange:NSMakeRange(2, result.length - 3)] stringByAppendingString:@"*"]; 38 | } else 39 | if ([[result substringToIndex:1] isEqualToString:@"^"]) { 40 | result = [NSString stringWithFormat:@"%@ *", 41 | [NSString decodeType:[[result substringFromIndex:1] cStringUsingEncoding:NSUTF8StringEncoding]]]; 42 | } 43 | return result; 44 | } 45 | 46 | 47 | static void getSuper(Class class, NSMutableString *result) { 48 | [result appendFormat:@" -> %@", NSStringFromClass(class)]; 49 | if ([class superclass]) { getSuper([class superclass], result); } 50 | } 51 | 52 | 53 | + (NSArray *)classes { 54 | unsigned int classesCount; 55 | Class *classes = objc_copyClassList(&classesCount); 56 | NSMutableArray *result = [NSMutableArray array]; 57 | for (unsigned int i = 0 ; i < classesCount; i++) { 58 | [result addObject:NSStringFromClass(classes[i])]; 59 | } 60 | return [result sortedArrayUsingSelector:@selector(compare:)]; 61 | } 62 | 63 | + (NSArray *)classMethods { 64 | return [self methodsForClass:object_getClass([self class]) typeFormat:@"+"]; 65 | } 66 | 67 | + (NSArray *)instanceMethods { 68 | return [self methodsForClass:[self class] typeFormat:@"-"]; 69 | } 70 | 71 | + (NSArray *)properties { 72 | unsigned int outCount; 73 | objc_property_t *properties = class_copyPropertyList([self class], &outCount); 74 | NSMutableArray *result = [NSMutableArray array]; 75 | for (unsigned int i = 0; i < outCount; i++) { 76 | [result addObject:[self formattedPropery:properties[i]]]; 77 | } 78 | free(properties); 79 | return result.count ? [result copy] : nil; 80 | } 81 | 82 | + (NSArray *)methodLists { 83 | NSMutableArray *methodListArray = [NSMutableArray array]; 84 | if ([self instanceMethods].count > 0) { 85 | [methodListArray addObject:[self instanceMethods]]; 86 | } 87 | if ([self classMethods].count > 0) { 88 | [methodListArray addObject:[self classMethods]]; 89 | } 90 | return methodListArray; 91 | } 92 | 93 | + (NSArray *)instanceVariables { 94 | unsigned int outCount; 95 | Ivar *ivars = class_copyIvarList([self class], &outCount); 96 | NSMutableArray *result = [NSMutableArray array]; 97 | for (unsigned int i = 0; i < outCount; i++) { 98 | NSString *type = [NSString decodeType:ivar_getTypeEncoding(ivars[i])]; 99 | NSString *name = [NSString stringWithCString:ivar_getName(ivars[i]) encoding:NSUTF8StringEncoding]; 100 | NSString *ivarDescription = [NSString stringWithFormat:@"%@ %@", type, name]; 101 | [result addObject:ivarDescription]; 102 | } 103 | free(ivars); 104 | return result.count ? [result copy] : nil; 105 | } 106 | 107 | + (NSArray *)protocols { 108 | unsigned int outCount; 109 | Protocol * const *protocols = class_copyProtocolList([self class], &outCount); 110 | 111 | NSMutableArray *result = [NSMutableArray array]; 112 | for (unsigned int i = 0; i < outCount; i++) { 113 | unsigned int adoptedCount; 114 | Protocol * const *adotedProtocols = protocol_copyProtocolList(protocols[i], &adoptedCount); 115 | NSString *protocolName = [NSString stringWithCString:protocol_getName(protocols[i]) encoding:NSUTF8StringEncoding]; 116 | 117 | NSMutableArray *adoptedProtocolNames = [NSMutableArray array]; 118 | for (unsigned int idx = 0; idx < adoptedCount; idx++) { 119 | [adoptedProtocolNames addObject:[NSString stringWithCString:protocol_getName(adotedProtocols[idx]) encoding:NSUTF8StringEncoding]]; 120 | } 121 | NSString *protocolDescription = protocolName; 122 | 123 | if (adoptedProtocolNames.count) { 124 | protocolDescription = [NSString stringWithFormat:@"%@ <%@>", protocolName, [adoptedProtocolNames componentsJoinedByString:@", "]]; 125 | } 126 | [result addObject:protocolDescription]; 127 | //free(adotedProtocols); 128 | } 129 | //free((__bridge void *)(*protocols)); 130 | return result.count ? [result copy] : nil; 131 | } 132 | 133 | + (NSDictionary *)descriptionForProtocol:(Protocol *)proto { 134 | NSMutableDictionary *methodsAndProperties = [NSMutableDictionary dictionary]; 135 | 136 | NSArray *requiredMethods = [[[self class] formattedMethodsForProtocol:proto required:YES instance:NO] arrayByAddingObjectsFromArray:[[self class]formattedMethodsForProtocol:proto required:YES instance:YES]]; 137 | 138 | NSArray *optionalMethods = [[[self class] formattedMethodsForProtocol:proto required:NO instance:NO] arrayByAddingObjectsFromArray:[[self class]formattedMethodsForProtocol:proto required:NO instance:YES]]; 139 | 140 | unsigned int propertiesCount; 141 | NSMutableArray *propertyDescriptions = [NSMutableArray array]; 142 | objc_property_t *properties = protocol_copyPropertyList(proto, &propertiesCount); 143 | for (unsigned int i = 0; i < propertiesCount; i++) { 144 | [propertyDescriptions addObject:[self formattedPropery:properties[i]]]; 145 | } 146 | 147 | if (requiredMethods.count) { 148 | [methodsAndProperties setObject:requiredMethods forKey:@"@required"]; 149 | } 150 | if (optionalMethods.count) { 151 | [methodsAndProperties setObject:optionalMethods forKey:@"@optional"]; 152 | } if (propertyDescriptions.count) { 153 | [methodsAndProperties setObject:[propertyDescriptions copy] forKey:@"@properties"]; 154 | } 155 | 156 | free(properties); 157 | return methodsAndProperties.count ? [methodsAndProperties copy ] : nil; 158 | } 159 | 160 | + (NSString *)parentClassHierarchy { 161 | NSMutableString *result = [NSMutableString string]; 162 | getSuper([self class], result); 163 | return result; 164 | } 165 | 166 | #pragma mark - Private 167 | 168 | + (NSArray *)methodsForClass:(Class)class typeFormat:(NSString *)type { 169 | unsigned int outCount; 170 | Method *methods = class_copyMethodList(class, &outCount); 171 | NSMutableArray *result = [NSMutableArray array]; 172 | for (unsigned int i = 0; i < outCount; i++) { 173 | NSString *methodDescription = [NSString stringWithFormat:@"%@ (%@)%@", 174 | type, 175 | [NSString decodeType:method_copyReturnType(methods[i])], 176 | NSStringFromSelector(method_getName(methods[i]))]; 177 | 178 | NSInteger args = method_getNumberOfArguments(methods[i]); 179 | NSMutableArray *selParts = [[methodDescription componentsSeparatedByString:@":"] mutableCopy]; 180 | NSInteger offset = 2; //1-st arg is object (@), 2-nd is SEL (:) 181 | 182 | for (int idx = offset; idx < args; idx++) { 183 | NSString *returnType = [NSString decodeType:method_copyArgumentType(methods[i], idx)]; 184 | selParts[idx - offset] = [NSString stringWithFormat:@"%@:(%@)arg%d", 185 | selParts[idx - offset], 186 | returnType, 187 | idx - 2]; 188 | } 189 | [result addObject:[selParts componentsJoinedByString:@" "]]; 190 | } 191 | free(methods); 192 | return result.count ? [result copy] : nil; 193 | } 194 | 195 | + (NSArray *)formattedMethodsForProtocol:(Protocol *)proto required:(BOOL)required instance:(BOOL)instance { 196 | unsigned int methodCount; 197 | struct objc_method_description *methods = protocol_copyMethodDescriptionList(proto, required, instance, &methodCount); 198 | NSMutableArray *methodsDescription = [NSMutableArray array]; 199 | for (unsigned int i = 0; i < methodCount; i++) { 200 | [methodsDescription addObject: 201 | [NSString stringWithFormat:@"%@ (%@)%@", 202 | instance ? @"-" : @"+", 203 | #warning return correct type 204 | @"void", 205 | NSStringFromSelector(methods[i].name)]]; 206 | } 207 | 208 | free(methods); 209 | return [methodsDescription copy]; 210 | } 211 | 212 | + (NSString *)formattedPropery:(objc_property_t)prop { 213 | unsigned int attrCount; 214 | objc_property_attribute_t *attrs = property_copyAttributeList(prop, &attrCount); 215 | NSMutableDictionary *attributes = [NSMutableDictionary dictionary]; 216 | for (unsigned int idx = 0; idx < attrCount; idx++) { 217 | NSString *name = [NSString stringWithCString:attrs[idx].name encoding:NSUTF8StringEncoding]; 218 | NSString *value = [NSString stringWithCString:attrs[idx].value encoding:NSUTF8StringEncoding]; 219 | [attributes setObject:value forKey:name]; 220 | } 221 | free(attrs); 222 | NSMutableString *property = [NSMutableString stringWithFormat:@"@property "]; 223 | NSMutableArray *attrsArray = [NSMutableArray array]; 224 | 225 | //https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtPropertyIntrospection.html#//apple_ref/doc/uid/TP40008048-CH101-SW5 226 | [attrsArray addObject:[attributes objectForKey:@"N"] ? @"nonatomic" : @"atomic"]; 227 | 228 | if ([attributes objectForKey:@"&"]) { 229 | [attrsArray addObject:@"strong"]; 230 | } else if ([attributes objectForKey:@"C"]) { 231 | [attrsArray addObject:@"copy"]; 232 | } else if ([attributes objectForKey:@"W"]) { 233 | [attrsArray addObject:@"weak"]; 234 | } else { 235 | [attrsArray addObject:@"assign"]; 236 | } 237 | if ([attributes objectForKey:@"R"]) {[attrsArray addObject:@"readonly"];} 238 | if ([attributes objectForKey:@"G"]) { 239 | [attrsArray addObject:[NSString stringWithFormat:@"getter=%@", [attributes objectForKey:@"G"]]]; 240 | } 241 | if ([attributes objectForKey:@"S"]) { 242 | [attrsArray addObject:[NSString stringWithFormat:@"setter=%@", [attributes objectForKey:@"G"]]]; 243 | } 244 | 245 | [property appendFormat:@"(%@) %@ %@", 246 | [attrsArray componentsJoinedByString:@", "], 247 | [NSString decodeType:[[attributes objectForKey:@"T"] cStringUsingEncoding:NSUTF8StringEncoding]], 248 | [NSString stringWithCString:property_getName(prop) encoding:NSUTF8StringEncoding]]; 249 | return [property copy]; 250 | } 251 | @end 252 | -------------------------------------------------------------------------------- /OCDeepLearning/GCDLearning.h: -------------------------------------------------------------------------------- 1 | // 2 | // GCDLearning.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2017/7/11. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface GCDLearning : NSObject 12 | 13 | 14 | + (instancetype)sharedInstance; 15 | 16 | - (void)testQueue; 17 | 18 | - (void)testGroup; 19 | - (void)testGroupOfEnterLeaveAndWait; 20 | 21 | - (void)testBarrier; 22 | - (void)testWait; 23 | - (void)testSyncMain; 24 | 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /OCDeepLearning/GCDLearning.m: -------------------------------------------------------------------------------- 1 | // 2 | // GCDLearning.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2017/7/11. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "GCDLearning.h" 10 | 11 | 12 | struct GCDQueue { 13 | // static dispatch_queue_t serialQueue = dispatch_queue_create("com.sohu.www", NULL); 14 | }; 15 | 16 | @implementation GCDLearning 17 | 18 | //单例 19 | // 单例使用dispatch_once的好处是: 20 | // dispatch_once比synchronized要更高效,它没有使用重量级的同步机制。若是那样的话,每次运行代码前都要获取锁,相反此函数采用“原子访问”来查询标记,以判断其对应的代码是否之前执行过。 21 | 22 | + (instancetype)sharedInstance { 23 | static GCDLearning *sharedInstance = nil; 24 | static dispatch_once_t onceToken; 25 | // @synchronized (self) { 26 | // if (!sharedInstance) { 27 | // sharedInstance = [[self alloc] init]; 28 | // } 29 | // } 30 | dispatch_once(&onceToken, ^{ 31 | sharedInstance = [[self alloc] init]; 32 | }); 33 | return sharedInstance; 34 | } 35 | 36 | - (void)testQueue { 37 | 38 | dispatch_queue_t serialQueue = dispatch_queue_create("com.sohu.www", NULL); 39 | //串行并行是针对任务的,对应GCD里的block 40 | //同步异步是针对队列的,对应线程 41 | //异步串行(子线程里同步执行任务) 42 | dispatch_async(serialQueue, ^{ 43 | NSLog(@"异步线程为%@",[NSThread currentThread]); 44 | }); 45 | 46 | //同步串行队列 47 | dispatch_sync(serialQueue, ^{ 48 | NSLog(@"同步串行线程为%@",[NSThread currentThread]); 49 | }); 50 | 51 | // 异步并发队列 52 | dispatch_queue_t concurrentQueue = dispatch_queue_create("test.gcd.async", DISPATCH_QUEUE_CONCURRENT); 53 | dispatch_async(concurrentQueue, ^{ 54 | NSLog(@"当前第一个线程为%@",[NSThread currentThread]); 55 | }); 56 | dispatch_async(concurrentQueue, ^{ 57 | NSLog(@"当前第二个线程为%@",[NSThread currentThread]); 58 | }); 59 | } 60 | 61 | - (void)testGroup { 62 | /* 63 | 打印结果是: 64 | 将任务1和任务3放在group中, 65 | 先执行任务1,3结束后,执行任务2 66 | */ 67 | 68 | dispatch_queue_t globalQueue = dispatch_queue_create("test.gcd.group", DISPATCH_QUEUE_CONCURRENT); 69 | dispatch_group_t group = dispatch_group_create(); 70 | 71 | dispatch_group_async(group, globalQueue, ^{ 72 | NSLog(@"Group第1个任务,当前线程为%@",[NSThread currentThread]); 73 | }); 74 | 75 | dispatch_group_async(group, globalQueue, ^{ 76 | sleep(5); 77 | NSLog(@"Group第3个任务延迟5秒执行,当前线程为%@",[NSThread currentThread]); 78 | }); 79 | 80 | dispatch_group_notify(group, globalQueue, ^{ 81 | dispatch_group_async(group, globalQueue, ^{ 82 | NSLog(@"Group第2个任务,当前线程为%@",[NSThread currentThread]); 83 | }); 84 | }); 85 | } 86 | 87 | - (void)testGroupOfEnterLeaveAndWait { 88 | //log结果: 89 | // 因为等待最长为3秒,所以先执行任务1,后执行组外的任务3,后执行5秒的任务2 90 | // 如果超时时长为大于执行任务的时长,则会执行完1,再执行2,最后执行3 91 | //NOTE: wait传入的是一个dispatch_time的参数,而不要直接传数字 92 | dispatch_group_t group2 = dispatch_group_create(); 93 | dispatch_queue_t globalQueue = dispatch_queue_create("test.gcd.group", DISPATCH_QUEUE_CONCURRENT); 94 | 95 | dispatch_group_enter(group2); 96 | dispatch_group_async(group2, globalQueue, ^{ 97 | NSLog(@"Group2组内的第1个任务,当前线程为%@",[NSThread currentThread]); 98 | }); 99 | 100 | dispatch_group_async(group2, globalQueue, ^{ 101 | sleep(5); 102 | NSLog(@"Group2组内的第2个任务,延迟5秒执行,当前线程为%@",[NSThread currentThread]); 103 | }); 104 | 105 | dispatch_group_leave(group2); 106 | 107 | long a = dispatch_group_wait(group2, dispatch_time(DISPATCH_TIME_NOW, 6.0 * NSEC_PER_SEC)); 108 | NSLog(@"时间%ld",a); 109 | 110 | dispatch_group_async(group2, globalQueue, ^{ 111 | NSLog(@"Group2组外的第三个任务,当前线程为%@",[NSThread currentThread]); 112 | }); 113 | } 114 | 115 | - (void)testBarrier { 116 | 117 | /* 118 | 打印顺序是: 119 | barrier之前的dispatch-1 120 | barrier之前的dispatch-2 121 | dispatch-barrier 122 | barrier之后的dispatch-3 123 | barrier之后的dispatch-4 124 | */ 125 | 126 | dispatch_queue_t concurrentQueue = dispatch_queue_create("test.gcd.barrier", DISPATCH_QUEUE_CONCURRENT); 127 | dispatch_async(concurrentQueue, ^(){ 128 | NSLog(@"barrier之前的dispatch-1"); 129 | }); 130 | dispatch_async(concurrentQueue, ^(){ 131 | NSLog(@"barrier之前的dispatch-2"); 132 | }); 133 | dispatch_barrier_async(concurrentQueue, ^(){ 134 | NSLog(@"dispatch-barrier"); 135 | }); 136 | dispatch_async(concurrentQueue, ^(){ 137 | NSLog(@"barrier之后的dispatch-3"); 138 | }); 139 | dispatch_async(concurrentQueue, ^(){ 140 | NSLog(@"barrier之后的dispatch-4"); 141 | }); 142 | } 143 | 144 | - (void)testWait { 145 | dispatch_queue_t queue = dispatch_queue_create("alibaba-inc.com", NULL); 146 | 147 | dispatch_async(queue, ^{ 148 | // 异步 149 | [NSThread sleepForTimeInterval:2];// 模拟耗时操作 150 | NSLog(@"异步队列---%@",[NSThread currentThread]); // 打印当前线程 151 | }); 152 | 153 | dispatch_sync(queue, ^{ 154 | // 同步 155 | [NSThread sleepForTimeInterval:2]; 156 | // 模拟耗时操作 157 | NSLog(@"3---%@",[NSThread currentThread]); 158 | // 打印当前线程 159 | }); 160 | } 161 | 162 | - (void)testSyncMain { 163 | 164 | NSLog(@"syncMain---begin"); 165 | /* 166 | * 同步主队列会crash 167 | * crash信息:Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0) 168 | */ 169 | 170 | NSLog(@"currentThread---%@",[NSThread currentThread]); 171 | // 打印当前线程NSLog(@"syncMain---begin"); 172 | dispatch_queue_t queue = dispatch_get_main_queue(); 173 | 174 | dispatch_sync(queue, ^{// 追加任务1 175 | for(int i =0; i < 2; ++i) { 176 | [NSThread sleepForTimeInterval:2]; 177 | // 模拟耗时操作 178 | NSLog(@"1---%@",[NSThread currentThread]); 179 | // 打印当前线程 180 | } 181 | }); 182 | NSLog(@"syncMain---end"); 183 | } 184 | 185 | @end 186 | -------------------------------------------------------------------------------- /OCDeepLearning/Grade+CoreDataClass.h: -------------------------------------------------------------------------------- 1 | // 2 | // Grade+CoreDataClass.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/6/22. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | // 9 | 10 | #import 11 | #import 12 | 13 | @class Student; 14 | 15 | NS_ASSUME_NONNULL_BEGIN 16 | 17 | @interface Grade : NSManagedObject 18 | 19 | @end 20 | 21 | NS_ASSUME_NONNULL_END 22 | 23 | #import "Grade+CoreDataProperties.h" 24 | -------------------------------------------------------------------------------- /OCDeepLearning/Grade+CoreDataClass.m: -------------------------------------------------------------------------------- 1 | // 2 | // Grade+CoreDataClass.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/6/22. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | // 9 | 10 | #import "Grade+CoreDataClass.h" 11 | 12 | @implementation Grade 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /OCDeepLearning/Grade+CoreDataProperties.h: -------------------------------------------------------------------------------- 1 | // 2 | // Grade+CoreDataProperties.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/6/22. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | // 9 | 10 | #import "Grade+CoreDataClass.h" 11 | 12 | 13 | NS_ASSUME_NONNULL_BEGIN 14 | 15 | @interface Grade (CoreDataProperties) 16 | 17 | + (NSFetchRequest *)fetchRequest; 18 | 19 | @property (nullable, nonatomic, copy) NSString *gradeName; 20 | @property (nullable, nonatomic, copy) NSString *gradeID; 21 | @property (nullable, nonatomic, retain) Student *studentClass; 22 | 23 | @end 24 | 25 | NS_ASSUME_NONNULL_END 26 | -------------------------------------------------------------------------------- /OCDeepLearning/Grade+CoreDataProperties.m: -------------------------------------------------------------------------------- 1 | // 2 | // Grade+CoreDataProperties.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/6/22. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | // 9 | 10 | #import "Grade+CoreDataProperties.h" 11 | 12 | @implementation Grade (CoreDataProperties) 13 | 14 | + (NSFetchRequest *)fetchRequest { 15 | return [[NSFetchRequest alloc] initWithEntityName:@"Grade"]; 16 | } 17 | 18 | @dynamic gradeName; 19 | @dynamic gradeID; 20 | @dynamic studentClass; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /OCDeepLearning/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /OCDeepLearning/LearnDatasourceClass.h: -------------------------------------------------------------------------------- 1 | // 2 | // LearnDatasourceClass.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/8/17. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface LearnDatasourceClass : NSObject 12 | 13 | @property(nonatomic, copy) NSString *KVOString; 14 | 15 | + (instancetype)sharedInstance; 16 | 17 | - (void)postNotify; 18 | - (void)addObserveNotify; 19 | - (void)learnKVO; 20 | 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /OCDeepLearning/LearnDatasourceClass.m: -------------------------------------------------------------------------------- 1 | // 2 | // LearnDatasourceClass.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/8/17. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "LearnDatasourceClass.h" 10 | 11 | static NSString *const kFirstNotificationName = @"firstNotificationName"; 12 | static NSString *const kSecondNotificationName = @"secondNotificationName"; 13 | static NSString *const kThirdNotificationName = @"thirdNotificationName"; 14 | 15 | @interface LearnDatasourceClass() 16 | 17 | @property(nonatomic, strong) NSMutableArray *allNotifyArray; // 获取所有的通知 18 | 19 | 20 | @end 21 | 22 | @implementation LearnDatasourceClass 23 | 24 | /* 25 | 26 | 1. 通知默认是同步的 27 | 2. 如果通知的线程是异步的,即post和接收的都是,可以使用 28 | addObserverForName:<#(nullable NSNotificationName)#> object:<#(nullable id)#> queue:<#(nullable NSOperationQueue *)#> usingBlock:<#^(NSNotification * _Nonnull note)block#> 29 | 方法 30 | 3. 如果通知的name填写为nil,则会接收所有的通知、(所以可以利用trick,获取所有的通知) 31 | */ 32 | 33 | + (instancetype)sharedInstance { 34 | static LearnDatasourceClass *sharedInstance = nil; 35 | static dispatch_once_t onceToken; 36 | dispatch_once(&onceToken, ^{ 37 | sharedInstance = [[self alloc] init]; 38 | }); 39 | return sharedInstance; 40 | } 41 | 42 | #pragma mark - 通知 43 | - (void)postNotify { 44 | [self addObserveNotify]; 45 | 46 | NSString *firstString = @"这是第1个通知"; 47 | NSString *secondString = @"这是第2个通知"; 48 | NSString *thirdString = @"这是第3个通知"; 49 | 50 | [[NSNotificationCenter defaultCenter] postNotificationName:kFirstNotificationName object:firstString]; 51 | [[NSNotificationCenter defaultCenter] postNotificationName:kSecondNotificationName object:secondString]; 52 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 53 | [[NSNotificationCenter defaultCenter] postNotificationName:kThirdNotificationName object:thirdString]; 54 | NSLog(@"发送通知的线程是%@", [NSThread currentThread]); 55 | }); 56 | 57 | // // 第一种方式执行通知 58 | // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(firstNotification:) name:kFirstNotificationName object:nil]; 59 | // 60 | // // 第二种方式执行通知 61 | // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(secondNotification:) name:nil object:nil]; 62 | // 63 | // // 第3种方式执行通知(第三个是子线程发送的通知,如果想在主线程中收到信息,则应该指定具体的队列 64 | // [[NSNotificationCenter defaultCenter] addObserverForName:kThirdNotificationName object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) { 65 | // NSLog(@"接收通知的线程是%@", [NSThread currentThread]); 66 | // NSLog(@"通知的信息是%@",note); 67 | // }]; 68 | 69 | // [[NSNotificationCenter defaultCenter] addObserverForName:kThirdNotificationName object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) { 70 | // NSLog(@"接收通知的线程是%@", [NSThread currentThread]); 71 | // NSLog(@"通知的信息是%@",note); 72 | // }]; 73 | } 74 | 75 | - (void)addObserveNotify { 76 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(firstNotification:) name:kFirstNotificationName object:nil]; 77 | 78 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(secondNotification:) name:kSecondNotificationName object:nil]; 79 | 80 | [[NSNotificationCenter defaultCenter] addObserverForName: kThirdNotificationName object:nil queue:NSOperationQueue.mainQueue usingBlock:^(NSNotification * _Nonnull note) { 81 | NSLog(@"queue == mainQueue,此时的通知的信息%@,当前线程是%@",note.userInfo, [NSThread currentThread]); 82 | }]; 83 | 84 | [[NSNotificationCenter defaultCenter] addObserverForName:kThirdNotificationName object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) { 85 | NSLog(@"queue == nil, 此时的通知的信息%@,当前线程是%@",note.userInfo, [NSThread currentThread]); 86 | }]; 87 | 88 | [[NSNotificationCenter defaultCenter] addObserverForName:kThirdNotificationName object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) { 89 | NSLog(@"通知的信息%@",note.userInfo); 90 | }]; 91 | } 92 | 93 | - (void)firstNotification:(NSNotification *)notify { 94 | NSLog(@"第1个通知的通知详情%@",notify); 95 | } 96 | 97 | - (void)secondNotification:(NSNotification *)notify { 98 | 99 | [self.allNotifyArray addObject:notify.name]; 100 | NSLog(@"第2个通知的通知详情%@",notify); 101 | } 102 | 103 | - (void)thirdNotification:(NSNotification *)notify { 104 | NSLog(@"第3个通知的通知详情%@",notify); 105 | } 106 | 107 | 108 | #pragma mark - KVO 109 | - (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context { 110 | 111 | } 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | #pragma mark - lazy load 122 | - (NSMutableArray *)allNotifyArray { 123 | if (!_allNotifyArray) { 124 | _allNotifyArray = [NSMutableArray array]; 125 | } 126 | return _allNotifyArray; 127 | } 128 | 129 | 130 | - (void)learnKVO { 131 | self.KVOString = @"old"; 132 | [self.KVOString addObserver:self forKeyPath:@"KVOString" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil]; 133 | self.KVOString = @"new"; 134 | 135 | } 136 | 137 | - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { 138 | if ([keyPath isEqualToString:@"KVOString"]) { 139 | NSLog(@"KVO的值是%@",change); 140 | } 141 | } 142 | 143 | - (void)willChangeValueForKey:(NSString *)key { 144 | if ([key isEqualToString:@"KVOString"]) { 145 | NSLog(@"key%@",key); 146 | } 147 | } 148 | 149 | - (void)didChangeValueForKey:(NSString *)key { 150 | if ([key isEqualToString:@"KVOString"]) { 151 | NSLog(@"key%@",key); 152 | } 153 | } 154 | 155 | - (void)dealloc { 156 | //移除通知 157 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 158 | [self.KVOString removeObserver:self forKeyPath:@"KVOString"]; 159 | } 160 | 161 | @end 162 | -------------------------------------------------------------------------------- /OCDeepLearning/LearnInitializeBaseClass.h: -------------------------------------------------------------------------------- 1 | // 2 | // LearnInitializeBaseClass.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/8/16. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface LearnInitializeBaseClass : NSObject 12 | 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /OCDeepLearning/LearnInitializeBaseClass.m: -------------------------------------------------------------------------------- 1 | // 2 | // LearnInitializeBaseClass.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/8/16. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "LearnInitializeBaseClass.h" 10 | 11 | 12 | 13 | @implementation LearnInitializeBaseClass 14 | 15 | //+ (void)initialize { 16 | // NSLog(@"调用initialize,当前类的名字为%@",self); 17 | //} 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /OCDeepLearning/LearnInitializeChildClass.h: -------------------------------------------------------------------------------- 1 | // 2 | // LearnInitializeChildClass.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/8/16. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "LearnInitializeBaseClass.h" 10 | #import "LearnInitializeFatherClass.h" 11 | 12 | 13 | @interface LearnInitializeChildClass : LearnInitializeFatherClass 14 | 15 | + (instancetype)sharedInstance; 16 | 17 | - (void)test; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /OCDeepLearning/LearnInitializeChildClass.m: -------------------------------------------------------------------------------- 1 | // 2 | // LearnInitializeChildClass.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/8/16. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "LearnInitializeChildClass.h" 10 | 11 | 12 | static NSInteger kSomeInteger = 4; 13 | static NSArray *kSomeArray; 14 | 15 | //static NSArray *kConstArray = [NSArray array]; 16 | // NOTE: 17 | // 报错Initializer element is not a compile-time constant 18 | // 初始化的值,不是一个编译时常量 19 | // 如果需要初始化全局状态,可以外部声明,在initialize里初始化 20 | // NOTE: 21 | static NSString* const kSomeString = @"someString";// 这个没问题,是因为直接用字面量给kSomeString赋值,内存在苍凉去 22 | 23 | 24 | @implementation LearnInitializeChildClass 25 | 26 | // 关于initialize 27 | /* 28 | * 1. 只要继承链上,有一个class实现了initilize,该class的子类都会也同样会调用initilize,(父类不会) 29 | 比如: 30 | LearnInitializeBaseClass ————》 LearnInitializeFatherClass ————》LearnInitializeChildClass 31 | LearnInitializeFatherClass实现了initilize方法,其子类LearnInitializeChildClass也会调用,但是父类LearnInitializeBaseClass就不会实现 32 | */ 33 | 34 | + (void)initialize { 35 | 36 | NSLog(@"调用initialize,当前类的名字为%@",self); 37 | if (self == [LearnInitializeChildClass class]) { 38 | kSomeArray = [NSArray arrayWithObject:@"1"]; 39 | } 40 | } 41 | 42 | + (instancetype)sharedInstance { 43 | static LearnInitializeChildClass *sharedInstance = nil; 44 | static dispatch_once_t onceToken; 45 | dispatch_once(&onceToken, ^{ 46 | sharedInstance = [[self alloc] init]; 47 | }); 48 | return sharedInstance; 49 | } 50 | 51 | - (void)test { 52 | NSLog(@"输出数组对象为%@",kSomeArray); 53 | NSLog(@"输出整形为%ld",(long)kSomeInteger); 54 | } 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /OCDeepLearning/LearnInitializeFatherClass.h: -------------------------------------------------------------------------------- 1 | // 2 | // LearnInitializeFatherClass.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/8/16. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "LearnInitializeBaseClass.h" 10 | 11 | @interface LearnInitializeFatherClass : LearnInitializeBaseClass 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /OCDeepLearning/LearnInitializeFatherClass.m: -------------------------------------------------------------------------------- 1 | // 2 | // LearnInitializeFatherClass.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/8/16. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "LearnInitializeFatherClass.h" 10 | 11 | @implementation LearnInitializeFatherClass 12 | 13 | + (void)initialize { 14 | NSLog(@"调用initialize,当前类的名字为%@",self); 15 | sleep(10); 16 | } 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /OCDeepLearning/LearnSelfAndSuper.h: -------------------------------------------------------------------------------- 1 | // 2 | // LearnSelfAndSuper.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2018/8/20. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface LearnSelfAndSuper : NSObject 12 | 13 | @end 14 | 15 | @interface LearnFather : NSObject 16 | 17 | @end 18 | 19 | @interface LearnChild: LearnFather 20 | - (void)test; 21 | @end 22 | 23 | -------------------------------------------------------------------------------- /OCDeepLearning/LearnSelfAndSuper.m: -------------------------------------------------------------------------------- 1 | // 2 | // LearnSelfAndSuper.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2018/8/20. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "LearnSelfAndSuper.h" 10 | #import 11 | 12 | @implementation LearnSelfAndSuper 13 | 14 | @end 15 | 16 | @implementation LearnChild 17 | 18 | 19 | - (instancetype)init { 20 | self = [super init]; 21 | NSLog(@"LearnChild 当前类是 == %@, 调用self的class方法,返回值是%@",[self class], [self class]); 22 | NSLog(@"LearnChild 调用super的class方法,返回值是%@",[super class]); 23 | return self; 24 | } 25 | 26 | - (void)test { 27 | NSLog(@"哈哈哈的测试方法"); 28 | } 29 | 30 | @end 31 | 32 | @implementation LearnFather 33 | 34 | - (instancetype)init { 35 | self = [super init]; 36 | NSLog(@"当前类是 == %@, 调用self的class方法,返回值是%@",[self class], [self class]); 37 | NSLog(@"调用super的class方法,返回值是%@",[super class]); 38 | /* 39 | self和super底层实现原理: 40 | 41 | 当使用 self 调用方法时,会从当前类的方法列表中开始找,如果没有,就从父类中再找;而当使用 super 时,则从父类的方法列表中开始找,然后调用父类的这个方法。 42 | 当使用 self 调用时,会使用 objc_msgSend 函数: id objc_msgSend(id theReceiver, SEL theSelector, ...)。第 一个参数是消息接收者,第二个参数是调用的具体类方法的 selector,后面是 selector 方法的可变参数。以 [self setName:] 为例,编译器会替换成调用 objc_msgSend 的函数调用,其中 theReceiver 是 self,theSelector 是 @selector(setName:),这个 selector 是从当前 self 的 class 的方法列表开始找的 setName,当找到后把对应的 selector 传递过去。 43 | 44 | 当使用 super 调用时,会使用 objc_msgSendSuper 函数:id objc_msgSendSuper(struct objc_super *super, SEL op, ...)第一个参数是个objc_super的结构体,第二个参数还是类似上面的类方法的selector, 45 | 46 | 47 | struct objc_super { 48 | id receiver; 49 | Class superClass; 50 | }; 51 | 52 | 当编译器遇到 [super setName:] 时,开始做这几个事: 53 | 54 | 1)构 建 objc_super 的结构体,此时这个结构体的第一个成员变量 receiver 就是 子类,和 self 相同。而第二个成员变量 superClass 就是指父类 55 | 调用 objc_msgSendSuper 的方法,将这个结构体和 setName 的 self 传递过去。 56 | 57 | 2)函数里面在做的事情类似这样:从 objc_super 结构体指向的 superClass 的方法列表开始找 setName 的 selector,找到后再以 objc_super->receiver 去调用这个 selector 58 | 59 | */ 60 | NSLog(@"%@--------",object_getClass(self)); 61 | NSLog(@"%@--------",object_getClass(self.superclass)); 62 | 63 | NSLog(@"打印self的值是%@",self); 64 | NSLog(@"调用self.superclass方法,返回值是%@",self.superclass); 65 | 66 | 67 | 68 | return self; 69 | } 70 | 71 | @end 72 | 73 | -------------------------------------------------------------------------------- /OCDeepLearning/LearnUIWebView.h: -------------------------------------------------------------------------------- 1 | // 2 | // LearnUIWebView.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/8/20. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface LearnUIWebView : UIWebView 12 | + (instancetype)sharedInstance; 13 | - (void)ui_openURLString:(NSString *)URLString; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /OCDeepLearning/LearnUIWebView.m: -------------------------------------------------------------------------------- 1 | // 2 | // LearnUIWebView.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/8/20. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "LearnUIWebView.h" 10 | 11 | @implementation LearnUIWebView 12 | 13 | + (instancetype)sharedInstance { 14 | static LearnUIWebView *sharedInstance = nil; 15 | static dispatch_once_t onceToken; 16 | dispatch_once(&onceToken, ^{ 17 | sharedInstance = [[self alloc] init]; 18 | }); 19 | return sharedInstance; 20 | } 21 | 22 | - (void)ui_openURLString:(NSString *)URLString{ 23 | NSURL *URL = [NSURL URLWithString:URLString]; 24 | NSURLRequest *request = [NSURLRequest requestWithURL:URL]; 25 | [self loadRequest:request]; 26 | } 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /OCDeepLearning/LearnWKWebView.h: -------------------------------------------------------------------------------- 1 | // 2 | // LearnWKWebView.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/8/20. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface LearnWKWebView : WKWebView 13 | + (instancetype)sharedInstance; 14 | 15 | 16 | 17 | - (void)wk_openURLString:(NSString *)URLString; 18 | 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /OCDeepLearning/LearnWKWebView.m: -------------------------------------------------------------------------------- 1 | // 2 | // LearnWKWebView.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/8/20. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "LearnWKWebView.h" 10 | 11 | @implementation LearnWKWebView 12 | 13 | + (instancetype)sharedInstance { 14 | static LearnWKWebView *sharedInstance = nil; 15 | static dispatch_once_t onceToken; 16 | dispatch_once(&onceToken, ^{ 17 | sharedInstance = [[self alloc] init]; 18 | }); 19 | return sharedInstance; 20 | } 21 | 22 | - (void)wk_openURLString:(NSString *)URLString { 23 | NSURL *URL = [NSURL URLWithString:URLString]; 24 | NSURLRequest *request = [NSURLRequest requestWithURL:URL]; 25 | [self loadRequest:request]; 26 | } 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /OCDeepLearning/LearnWebViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // LearnWebViewController.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/8/20. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface LearnWebViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /OCDeepLearning/LearnWebViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // LearnWebViewController.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/8/20. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "LearnWebViewController.h" 10 | 11 | @interface LearnWebViewController () 12 | 13 | @end 14 | 15 | @implementation LearnWebViewController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | // Do any additional setup after loading the view. 20 | } 21 | 22 | - (void)didReceiveMemoryWarning { 23 | [super didReceiveMemoryWarning]; 24 | // Dispose of any resources that can be recreated. 25 | } 26 | 27 | /* 28 | #pragma mark - Navigation 29 | 30 | // In a storyboard-based application, you will often want to do a little preparation before navigation 31 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 32 | // Get the new view controller using [segue destinationViewController]. 33 | // Pass the selected object to the new view controller. 34 | } 35 | */ 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /OCDeepLearning/MainViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // MainViewController.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/6/15. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MainViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /OCDeepLearning/MainViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // MainViewController.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/6/15. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "MainViewController.h" 10 | #import "OCBaseTableViewController.h" 11 | 12 | @interface MainViewController () 13 | 14 | @end 15 | 16 | @implementation MainViewController 17 | 18 | - (void)viewDidLoad { 19 | [super viewDidLoad]; 20 | // Do any additional setup after loading the view. 21 | 22 | // OCBaseTableViewController *baseTableVC = [[OCBaseTableViewController alloc] init]; 23 | // 24 | // [self addChildViewController:baseTableVC]; 25 | // baseTableVC.tableView.frame = CGRectMake(0, 100, 300, 300); 26 | // [self.view addSubview:baseTableVC.tableView]; 27 | 28 | UIViewController *secondVc = [[UIViewController alloc] init]; 29 | secondVc.view.backgroundColor = [UIColor orangeColor]; 30 | secondVc.view.frame = CGRectMake(0, 410, 300, 300); 31 | [self.view addSubview:secondVc.view]; 32 | 33 | // NSArray *a = [NSArray arrayWithObjects:@0,@1, nil]; 34 | // 35 | // NSNumber *num = [a objectAtIndex:3]; 36 | 37 | } 38 | 39 | - (void)didReceiveMemoryWarning { 40 | [super didReceiveMemoryWarning]; 41 | // Dispose of any resources that can be recreated. 42 | 43 | 44 | } 45 | 46 | - (void)doesNotRecognizeSelector:(SEL)aSelector { 47 | NSLog(@"崩溃的方法是%c",__func__); 48 | 49 | NSLog(@"%@",aSelector); 50 | 51 | } 52 | /* 53 | #pragma mark - Navigation 54 | 55 | // In a storyboard-based application, you will often want to do a little preparation before navigation 56 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 57 | // Get the new view controller using [segue destinationViewController]. 58 | // Pass the selected object to the new view controller. 59 | } 60 | */ 61 | 62 | @end 63 | -------------------------------------------------------------------------------- /OCDeepLearning/NSObject+Extension.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+Extension.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2017/7/25. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSObject (Extension) 12 | 13 | /** 14 | 获取当前对象的引用计数retainCount 15 | 16 | @param obj 当前对象obj 17 | @return retainCount 18 | */ 19 | + (NSInteger)logRetainCount:(id) obj; 20 | 21 | 22 | /** 23 | 不要分类的同名方法取代类里的方法 24 | 25 | @param seletor 方法名 26 | */ 27 | + (void)useClassMethodInsteadOfCayegoryMethod: (SEL)seletor; 28 | @end 29 | -------------------------------------------------------------------------------- /OCDeepLearning/NSObject+Extension.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+Extension.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2017/7/25. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "NSObject+Extension.h" 10 | #import 11 | 12 | @implementation NSObject (Extension) 13 | 14 | + (NSInteger)logRetainCount:(id)obj { 15 | uintptr_t _objc_rootRetainCount(id obj); 16 | NSLog(@"当前对象为:%@\n,其引用计数的retainCount为%lu",obj,_objc_rootRetainCount(obj)); 17 | unsigned long retainCount = _objc_rootRetainCount(obj); 18 | return retainCount; 19 | } 20 | 21 | + (void)useClassMethodInsteadOfCayegoryMethod: (SEL)seletor { 22 | 23 | if (self) { 24 | unsigned int methodCount; 25 | Method *methodList = class_copyMethodList([self class], &methodCount); 26 | IMP lastImp = NULL; 27 | SEL lastSel = NULL; 28 | for (NSInteger i = 0; i < methodCount; i++) { 29 | Method method = methodList[i]; 30 | NSString *methodName = [NSString stringWithCString:sel_getName(method_getName(method)) 31 | encoding:NSUTF8StringEncoding]; 32 | NSString *selectorName = NSStringFromSelector(seletor); 33 | if ([selectorName isEqualToString:methodName]) { 34 | lastImp = method_getImplementation(method); 35 | lastSel = method_getName(method); 36 | } 37 | } 38 | typedef void (*fn)(id,SEL); 39 | 40 | if (lastImp != NULL) { 41 | fn f = (fn)lastImp; 42 | f(self,lastSel); 43 | } 44 | free(methodList); 45 | } 46 | } 47 | 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /OCDeepLearning/NSObject+MakeModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+MakeModel.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2017/7/13. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSObject (MakeModel) 12 | 13 | + (instancetype)modelWithDict:(NSDictionary *)dict; 14 | + (instancetype)modelWithDict:(NSDictionary *)dict updateDict:(NSDictionary *)updateDict; 15 | @end 16 | -------------------------------------------------------------------------------- /OCDeepLearning/NSObject+MakeModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+MakeModel.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2017/7/13. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "NSObject+MakeModel.h" 10 | #import 11 | 12 | @implementation NSObject (MakeModel) 13 | 14 | + (instancetype)modelWithDict:(NSDictionary *)dict updateDict:(NSDictionary *)updateDict { 15 | id model = [[self alloc] init]; 16 | unsigned int count = 0; 17 | Ivar *ivars = class_copyIvarList(self, &count); 18 | for (int i = 0; i < count; i++) { 19 | NSString *ivarName = [NSString stringWithUTF8String:ivar_getName(ivars[i])]; 20 | ivarName = [ivarName substringFromIndex:1]; 21 | id value = dict[ivarName]; 22 | if (value == nil) { 23 | if (updateDict) { 24 | NSString *keyName = updateDict[ivarName]; 25 | value = dict[keyName]; 26 | } 27 | [model setValue:value forKey:ivarName]; 28 | } 29 | } 30 | return model; 31 | } 32 | 33 | + (instancetype)modelWithDict:(NSDictionary *)dict { 34 | return [self modelWithDict:dict updateDict:nil]; 35 | } 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /OCDeepLearning/NSObject+PrivateMethod.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+PrivateMethod.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2018/9/27. 6 | // Copyright © 2018 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface NSObject (PrivateMethod) 14 | 15 | - (void)excutePrivateMethodWithSelectorName:(NSString *)selectorName; 16 | 17 | + (void)excutePrivateMethodWithInstanceSelectorName:(NSString *)aSelectorName ForClass:(NSString *)className; 18 | 19 | + (void)excutePrivateMethodWithInstanceSelector:(SEL)aSelector ForClass:(NSString *)className; 20 | @end 21 | 22 | NS_ASSUME_NONNULL_END 23 | -------------------------------------------------------------------------------- /OCDeepLearning/NSObject+PrivateMethod.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+PrivateMethod.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2018/9/27. 6 | // Copyright © 2018 walker彬. All rights reserved. 7 | // 8 | 9 | #import "NSObject+PrivateMethod.h" 10 | 11 | 12 | // TODO: - 1. 调用私有的类方法 13 | 14 | @implementation NSObject (PrivateMethod) 15 | 16 | /** 17 | 对象方法 18 | 入参方法名,可以调用本类的私有方法 19 | 20 | @param selectorName 方法名的字符串 21 | */ 22 | - (void)excutePrivateMethodWithSelectorName:(NSString *)selectorName { 23 | SEL privateSelector = NSSelectorFromString(selectorName); 24 | 25 | NSMethodSignature *signature = [self methodSignatureForSelector:privateSelector]; 26 | 27 | NSInvocation *invovation = [NSInvocation invocationWithMethodSignature:signature]; 28 | [invovation setTarget:self]; 29 | [invovation setSelector:privateSelector]; 30 | [invovation invoke]; 31 | } 32 | 33 | 34 | /** 35 | 调用某个类的实例方法 36 | 37 | @param aSelectorName 实例方法名 38 | @param className 类名 39 | */ 40 | + (void)excutePrivateMethodWithInstanceSelectorName:(NSString *)aSelectorName ForClass:(NSString *)className { 41 | Class TargetClass = NSClassFromString(className); 42 | id aClass = [[TargetClass alloc] init]; 43 | if (!aClass) { return; } 44 | 45 | SEL privateSelector = NSSelectorFromString(aSelectorName); 46 | NSMethodSignature *signature = [aClass methodSignatureForSelector:privateSelector]; 47 | 48 | NSInvocation *invovation = [NSInvocation invocationWithMethodSignature:signature]; 49 | [invovation setTarget:aClass]; 50 | [invovation setSelector:privateSelector]; 51 | [invovation invoke]; 52 | } 53 | 54 | + (void)excutePrivateMethodWithInstanceSelector:(SEL)aSelector ForClass:(NSString *)className { 55 | Class TargetClass = NSClassFromString(className); 56 | id aClass = [[TargetClass alloc] init]; 57 | if (!aClass) { return; } 58 | 59 | NSMethodSignature *signature = [aClass methodSignatureForSelector:aSelector]; 60 | 61 | NSInvocation *invovation = [NSInvocation invocationWithMethodSignature:signature]; 62 | [invovation setTarget:aClass]; 63 | [invovation setSelector:aSelector]; 64 | [invovation invoke]; 65 | } 66 | 67 | @end 68 | -------------------------------------------------------------------------------- /OCDeepLearning/NSObject+Runtime.h: -------------------------------------------------------------------------------- 1 | //// 2 | //// NSObject+Runtime.h 3 | //// OCDeepLearning 4 | //// 5 | //// Created by walker彬 on 2017/7/7. 6 | //// Copyright © 2017年 walker彬. All rights reserved. 7 | //// 8 | // 9 | //#import 10 | // 11 | //@interface NSObject (Runtime) 12 | // 13 | //+ (void)load; 14 | // 15 | //@end 16 | -------------------------------------------------------------------------------- /OCDeepLearning/NSObject+Runtime.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+Runtime.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2017/7/7. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "NSObject+Runtime.h" 10 | #import 11 | #import "ViewController.h" 12 | 13 | @implementation NSObject (Runtime) 14 | 15 | + (void)load { 16 | 17 | // [[self class] exchangeInstanceMethod:@selector(viewDidAppear:) SwizzledMethod:@selector(xxx_viewWillAppear:)]; 18 | [self exchangeViewDidLoad]; 19 | } 20 | 21 | 22 | - (void)exchangeViewDidLoad { 23 | // Method m1 = class_getInstanceMethod([ViewController class], @selector(viewDidAppear:)); 24 | // Method m2 = class_getInstanceMethod([ViewController class], @selector(gb_viewDidAppear:)); 25 | // 26 | //// IMP p1 = method_getImplementation(m1); 27 | //// IMP p2 = method_getImplementation(m2); 28 | //// NSLog(@"Imp分别是%p,/n %p",p1,p2); 29 | // ///p1和m1对应的是两个地址 30 | // 31 | // NSLog(@"method分别是%p,/n %p",m1,m2); 32 | // 33 | // method_exchangeImplementations(m1, m2); 34 | 35 | Method m3 = class_getInstanceMethod([ViewController class], @selector(viewDidLoad)); 36 | Method m4 = class_getInstanceMethod([ViewController class], @selector(gb_viewDidLoad)); 37 | 38 | // IMP p3 = method_getImplementation(m3); 39 | // IMP p4 = method_getImplementation(m4); 40 | // NSLog(@"Imp分别是%p,/n %p",p1,p2); 41 | ///p1和m1对应的是两个地址 42 | 43 | // NSLog(@"method分别是%p,/n %p",m3,m4); 44 | 45 | method_exchangeImplementations(m3, m4); 46 | } 47 | 48 | //- (void)gb_viewDidAppear:(BOOL)animated { 49 | // [self gb_viewDidAppear:YES]; 50 | // NSLog(@"方法交换成功"); 51 | //} 52 | 53 | 54 | - (void)gb_viewDidLoad { 55 | [self gb_viewDidLoad]; 56 | NSLog(@"类的名字是%@",[self class]); 57 | } 58 | 59 | 60 | #pragma mark - Method Swizzling 61 | // 交换方法 62 | + (void)exchangeInstanceMethod:(SEL)originalSelector SwizzledMethod:(SEL)swizzledSelector { 63 | static dispatch_once_t onceToken; 64 | dispatch_once(&onceToken, ^{ 65 | Class class = [self class]; 66 | 67 | Method originalMethod = class_getInstanceMethod(class, originalSelector); 68 | Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector); 69 | ///判断是否添加成功 70 | //成功则拦截,失败则交换 71 | BOOL didAddMethod = 72 | class_addMethod(class, 73 | originalSelector, 74 | method_getImplementation(swizzledMethod), 75 | method_getTypeEncoding(swizzledMethod)); 76 | 77 | if (didAddMethod) { 78 | class_replaceMethod(class, 79 | swizzledSelector, 80 | method_getImplementation(originalMethod), 81 | method_getTypeEncoding(originalMethod)); 82 | } else { 83 | method_exchangeImplementations(originalMethod, swizzledMethod); 84 | } 85 | }); 86 | } 87 | 88 | // MARK: 实现方法交换和拦截 89 | + (void)exchangeInstanceMethod:(SEL)originalSelector SwizzledMethod:(SEL)swizzledSelector InClass: (Class)class { 90 | static dispatch_once_t onceToken; 91 | dispatch_once(&onceToken, ^{ 92 | Method originalMethod = class_getInstanceMethod(class, originalSelector); 93 | Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector); 94 | ///判断是否添加成功 95 | //成功则拦截,失败则交换 96 | BOOL didAddMethod = 97 | class_addMethod(class, 98 | originalSelector, 99 | method_getImplementation(swizzledMethod), 100 | method_getTypeEncoding(swizzledMethod)); 101 | if (didAddMethod) { 102 | class_replaceMethod(class, 103 | swizzledSelector, 104 | method_getImplementation(originalMethod), 105 | method_getTypeEncoding(originalMethod)); 106 | } else { 107 | method_exchangeImplementations(originalMethod, swizzledMethod); 108 | } 109 | }); 110 | } 111 | 112 | 113 | 114 | // MARK: swizzledSelector 115 | - (void)xxx_viewWillAppear:(BOOL)animated { 116 | [self xxx_viewWillAppear:animated]; 117 | NSLog(@"viewWillAppear: %@", self); 118 | } 119 | @end 120 | -------------------------------------------------------------------------------- /OCDeepLearning/NSObject+a.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+a.h 3 | // OCDeepLearning 4 | // 5 | // Created by 郭彬 on 2020/3/24. 6 | // Copyright © 2020 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | #import 13 | 14 | NS_ASSUME_NONNULL_BEGIN 15 | 16 | @interface NSObject () 17 | 18 | @end 19 | 20 | NS_ASSUME_NONNULL_END 21 | -------------------------------------------------------------------------------- /OCDeepLearning/New Group/CTMediator.h: -------------------------------------------------------------------------------- 1 | // 2 | // CTMediator.h 3 | // CTMediator 4 | // 5 | // Created by casa on 16/3/13. 6 | // Copyright © 2016年 casa. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface CTMediator : NSObject 12 | 13 | + (instancetype)sharedInstance; 14 | 15 | // 远程App调用入口 16 | - (id)performActionWithUrl:(NSURL *)url completion:(void(^)(NSDictionary *info))completion; 17 | // 本地组件调用入口 18 | - (id)performTarget:(NSString *)targetName action:(NSString *)actionName params:(NSDictionary *)params shouldCacheTarget:(BOOL)shouldCacheTarget; 19 | - (void)releaseCachedTargetWithTargetName:(NSString *)targetName; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /OCDeepLearning/New Group/CTMediator.m: -------------------------------------------------------------------------------- 1 | // 2 | // CTMediator.m 3 | // CTMediator 4 | // 5 | // Created by casa on 16/3/13. 6 | // Copyright © 2016年 casa. All rights reserved. 7 | // 8 | 9 | #import "CTMediator.h" 10 | #import 11 | 12 | @interface CTMediator () 13 | 14 | @property (nonatomic, strong) NSMutableDictionary *cachedTarget; 15 | 16 | @end 17 | 18 | @implementation CTMediator 19 | 20 | #pragma mark - public methods 21 | + (instancetype)sharedInstance 22 | { 23 | static CTMediator *mediator; 24 | static dispatch_once_t onceToken; 25 | dispatch_once(&onceToken, ^{ 26 | mediator = [[CTMediator alloc] init]; 27 | }); 28 | return mediator; 29 | } 30 | 31 | /* 32 | scheme://[target]/[action]?[params] 33 | 34 | url sample: 35 | aaa://targetA/actionB?id=1234 36 | */ 37 | 38 | - (id)performActionWithUrl:(NSURL *)url completion:(void (^)(NSDictionary *))completion 39 | { 40 | NSMutableDictionary *params = [[NSMutableDictionary alloc] init]; 41 | NSString *urlString = [url query]; 42 | for (NSString *param in [urlString componentsSeparatedByString:@"&"]) { 43 | NSArray *elts = [param componentsSeparatedByString:@"="]; 44 | if([elts count] < 2) continue; 45 | [params setObject:[elts lastObject] forKey:[elts firstObject]]; 46 | } 47 | 48 | // 这里这么写主要是出于安全考虑,防止黑客通过远程方式调用本地模块。这里的做法足以应对绝大多数场景,如果要求更加严苛,也可以做更加复杂的安全逻辑。 49 | NSString *actionName = [url.path stringByReplacingOccurrencesOfString:@"/" withString:@""]; 50 | if ([actionName hasPrefix:@"native"]) { 51 | return @(NO); 52 | } 53 | 54 | // 这个demo针对URL的路由处理非常简单,就只是取对应的target名字和method名字,但这已经足以应对绝大部份需求。如果需要拓展,可以在这个方法调用之前加入完整的路由逻辑 55 | id result = [self performTarget:url.host action:actionName params:params shouldCacheTarget:NO]; 56 | if (completion) { 57 | if (result) { 58 | completion(@{@"result":result}); 59 | } else { 60 | completion(nil); 61 | } 62 | } 63 | return result; 64 | } 65 | 66 | - (id)performTarget:(NSString *)targetName action:(NSString *)actionName params:(NSDictionary *)params shouldCacheTarget:(BOOL)shouldCacheTarget 67 | { 68 | 69 | NSString *targetClassString = [NSString stringWithFormat:@"%@", targetName]; 70 | NSString *actionString = [NSString stringWithFormat:@"%@:", actionName]; 71 | Class targetClass; 72 | 73 | NSObject *target = self.cachedTarget[targetClassString]; 74 | if (target == nil) { 75 | targetClass = NSClassFromString(targetClassString); 76 | target = [[targetClass alloc] init]; 77 | } 78 | 79 | SEL action = NSSelectorFromString(actionString); 80 | 81 | if (target == nil) { 82 | // 这里是处理无响应请求的地方之一,这个demo做得比较简单,如果没有可以响应的target,就直接return了。实际开发过程中是可以事先给一个固定的target专门用于在这个时候顶上,然后处理这种请求的 83 | [self NoTargetActionResponseWithTargetString:targetClassString selectorString:actionString originParams:params]; 84 | return nil; 85 | } 86 | 87 | if (shouldCacheTarget) { 88 | self.cachedTarget[targetClassString] = target; 89 | } 90 | 91 | if ([target respondsToSelector:action]) { 92 | return [self safePerformAction:action target:target params:params]; 93 | } else { 94 | // 有可能target是Swift对象 95 | actionString = [NSString stringWithFormat:@"Action_%@WithParams:", actionName]; 96 | action = NSSelectorFromString(actionString); 97 | if ([target respondsToSelector:action]) { 98 | return [self safePerformAction:action target:target params:params]; 99 | } else { 100 | // 这里是处理无响应请求的地方,如果无响应,则尝试调用对应target的notFound方法统一处理 101 | SEL action = NSSelectorFromString(@"notFound:"); 102 | if ([target respondsToSelector:action]) { 103 | return [self safePerformAction:action target:target params:params]; 104 | } else { 105 | // 这里也是处理无响应请求的地方,在notFound都没有的时候,这个demo是直接return了。实际开发过程中,可以用前面提到的固定的target顶上的。 106 | [self NoTargetActionResponseWithTargetString:targetClassString selectorString:actionString originParams:params]; 107 | [self.cachedTarget removeObjectForKey:targetClassString]; 108 | return nil; 109 | } 110 | } 111 | } 112 | } 113 | 114 | - (void)releaseCachedTargetWithTargetName:(NSString *)targetName 115 | { 116 | NSString *targetClassString = [NSString stringWithFormat:@"Target_%@", targetName]; 117 | [self.cachedTarget removeObjectForKey:targetClassString]; 118 | } 119 | 120 | #pragma mark - private methods 121 | - (void)NoTargetActionResponseWithTargetString:(NSString *)targetString selectorString:(NSString *)selectorString originParams:(NSDictionary *)originParams 122 | { 123 | SEL action = NSSelectorFromString(@"Action_response:"); 124 | NSObject *target = [[NSClassFromString(@"Target_NoTargetAction") alloc] init]; 125 | 126 | NSMutableDictionary *params = [[NSMutableDictionary alloc] init]; 127 | params[@"originParams"] = originParams; 128 | params[@"targetString"] = targetString; 129 | params[@"selectorString"] = selectorString; 130 | 131 | [self safePerformAction:action target:target params:params]; 132 | } 133 | 134 | - (id)safePerformAction:(SEL)action target:(NSObject *)target params:(NSDictionary *)params 135 | { 136 | NSMethodSignature* methodSig = [target methodSignatureForSelector:action]; 137 | if(methodSig == nil) { 138 | return nil; 139 | } 140 | const char* retType = [methodSig methodReturnType]; 141 | 142 | if (strcmp(retType, @encode(void)) == 0) { 143 | NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig]; 144 | [invocation setArgument:¶ms atIndex:2]; 145 | [invocation setSelector:action]; 146 | [invocation setTarget:target]; 147 | [invocation invoke]; 148 | return nil; 149 | } 150 | 151 | if (strcmp(retType, @encode(NSInteger)) == 0) { 152 | NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig]; 153 | [invocation setArgument:¶ms atIndex:2]; 154 | [invocation setSelector:action]; 155 | [invocation setTarget:target]; 156 | [invocation invoke]; 157 | NSInteger result = 0; 158 | [invocation getReturnValue:&result]; 159 | return @(result); 160 | } 161 | 162 | if (strcmp(retType, @encode(BOOL)) == 0) { 163 | NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig]; 164 | [invocation setArgument:¶ms atIndex:2]; 165 | [invocation setSelector:action]; 166 | [invocation setTarget:target]; 167 | [invocation invoke]; 168 | BOOL result = 0; 169 | [invocation getReturnValue:&result]; 170 | return @(result); 171 | } 172 | 173 | if (strcmp(retType, @encode(CGFloat)) == 0) { 174 | NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig]; 175 | [invocation setArgument:¶ms atIndex:2]; 176 | [invocation setSelector:action]; 177 | [invocation setTarget:target]; 178 | [invocation invoke]; 179 | CGFloat result = 0; 180 | [invocation getReturnValue:&result]; 181 | return @(result); 182 | } 183 | 184 | if (strcmp(retType, @encode(NSUInteger)) == 0) { 185 | NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig]; 186 | [invocation setArgument:¶ms atIndex:2]; 187 | [invocation setSelector:action]; 188 | [invocation setTarget:target]; 189 | [invocation invoke]; 190 | NSUInteger result = 0; 191 | [invocation getReturnValue:&result]; 192 | return @(result); 193 | } 194 | 195 | #pragma clang diagnostic push 196 | #pragma clang diagnostic ignored "-Warc-performSelector-leaks" 197 | return [target performSelector:action withObject:params]; 198 | #pragma clang diagnostic pop 199 | } 200 | 201 | #pragma mark - getters and setters 202 | - (NSMutableDictionary *)cachedTarget 203 | { 204 | if (_cachedTarget == nil) { 205 | _cachedTarget = [[NSMutableDictionary alloc] init]; 206 | } 207 | return _cachedTarget; 208 | } 209 | 210 | @end 211 | -------------------------------------------------------------------------------- /OCDeepLearning/OCAutoReleasePool.h: -------------------------------------------------------------------------------- 1 | // 2 | // OCAutoReleasePool.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2017/7/7. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface OCAutoReleasePool : NSObject 13 | 14 | - (void)createNumbersOfObjects; 15 | - (void)createNumbersOfObjectsByautoReleasePool; 16 | - (void)monitorAsyncAutoReleasePool; 17 | - (void)testTimerInAsync; 18 | @end 19 | 20 | -------------------------------------------------------------------------------- /OCDeepLearning/OCAutoReleasePool.m: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // OCAutoReleasePool.m 4 | // OCDeepLearning 5 | // 6 | // Created by walker彬 on 2017/7/7. 7 | // Copyright © 2017年 walker彬. All rights reserved. 8 | // 9 | 10 | #import "OCAutoReleasePool.h" 11 | #import 12 | 13 | @implementation OCAutoReleasePool 14 | 15 | /** 16 | 为了对比 使用自动释放池对循环创建对象的影响 17 | */ 18 | - (void)createNumbersOfObjects { //未使用自动释放池,创建循环变量 19 | CFAbsoluteTime start = CFAbsoluteTimeGetCurrent(); 20 | 21 | for (int i = 0; i <= 100000; i++) { 22 | NSArray *array = [NSArray arrayWithObjects:@"1",@"2", nil]; 23 | NSLog(@"%@",array); 24 | } 25 | 26 | CFAbsoluteTime end = CFAbsoluteTimeGetCurrent(); 27 | NSLog(@"没有使用自动释放的耗时%f", end - start); 28 | 29 | 30 | } 31 | 32 | - (void)createNumbersOfObjectsByautoReleasePool { 33 | 34 | CFAbsoluteTime start = CFAbsoluteTimeGetCurrent(); 35 | @autoreleasepool { 36 | for (int i = 0; i <= 100000; i++) { 37 | NSArray *array = [NSArray arrayWithObjects:@"1",@"2", nil]; 38 | NSLog(@"%@",array); 39 | } 40 | } 41 | CFAbsoluteTime end = CFAbsoluteTimeGetCurrent(); 42 | NSLog(@"使用自动释放的耗时%f", end - start); 43 | 44 | } 45 | 46 | // TODO: - 待完成 47 | // MARK: 检测异步线程的NSAutoReleasePool 48 | /** 49 | 自动释放池依赖NSRunloop,但子线程的RunLoop默认不开启 50 | AIM: 检测子线程中引用自动释放池是否有影响 51 | Result: 52 | */ 53 | - (void)monitorAsyncAutoReleasePool { 54 | dispatch_queue_t queue = dispatch_queue_create("top.betteris.www", NULL); 55 | //异步线程全局队列 56 | 57 | dispatch_async(queue, ^{ 58 | NSMutableArray *array = [NSMutableArray array]; 59 | @autoreleasepool { 60 | [array addObject:@"111"]; 61 | } 62 | NSLog(@"%@",array); 63 | }); 64 | 65 | dispatch_async(dispatch_get_main_queue(), ^{ 66 | NSLog(@"当前线程为%@",[NSThread currentThread]); 67 | [NSTimer scheduledTimerWithTimeInterval:2 repeats:YES block:^(NSTimer * _Nonnull timer) { 68 | NSLog(@"次队列为异步主线程"); 69 | }]; 70 | }); 71 | } 72 | 73 | /** 74 | 子线程的runloop默认不开启,而NSTimer事件必须加入NSRunLoop中才可以运行 75 | 因此需要手动开启runloop,并把NSTimer添加进去才可以 76 | */ 77 | - (void)testTimerInAsync { 78 | dispatch_queue_t queue = dispatch_queue_create("top.betteris.www", NULL); 79 | //异步线程全局队列 80 | dispatch_async(queue, ^{ 81 | NSRunLoop *runloop = [NSRunLoop currentRunLoop]; 82 | NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) { 83 | NSLog(@"%@----子线程时间源事件成功开启----",[self class]); 84 | }]; 85 | [runloop addTimer:timer forMode:NSRunLoopCommonModes]; 86 | [runloop run]; 87 | NSMutableArray *array = [NSMutableArray array]; 88 | @autoreleasepool { 89 | [array addObject:@"111"]; 90 | } 91 | NSLog(@"%@",array); 92 | }); 93 | } 94 | 95 | @end 96 | -------------------------------------------------------------------------------- /OCDeepLearning/OCAutorelease.h: -------------------------------------------------------------------------------- 1 | // 2 | // OCAutorelease.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2017/7/24. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface OCAutorelease : NSObject 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /OCDeepLearning/OCAutorelease.m: -------------------------------------------------------------------------------- 1 | // 2 | // OCAutorelease.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2017/7/24. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "OCAutorelease.h" 10 | 11 | @implementation OCAutorelease 12 | 13 | - (void) testAutoRelease { 14 | // id oc = [[NSObject alloc] init]; 15 | // 16 | // id __strong oc2 = [[NSObject alloc] init]; 17 | // { 18 | // id oc3 = [[NSObject alloc] init]; 19 | // } 20 | // @autoreleasepool { 21 | // id obj = [[NSObject alloc] init]; 22 | // } 23 | // id __strong bbb = @"111"; 24 | // id __autorelease cc = @"11"; 25 | 26 | 27 | // NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 28 | // 29 | // id obj = [[NSObject alloc] init]; 30 | // [obj autorelease]; 31 | // 32 | // [pool drain]; 33 | 34 | 35 | ///autorelease到底做了什么 36 | /* 37 | //自动释放池的原理: 38 | 调用autorelease实际是把autorelease加入到自动释放池中 39 | 40 | - (id)autorelease { 41 | [NSAutoreleasePool addObject:self]; 42 | } 43 | 44 | + (void)addObject: (id) obj { 45 | NSAutoreleasePool *pool = 取得正在使用的NSAutoreleasePool对象; 46 | if (pool != nil) { 47 | [pool addObject: obj]; 48 | } else { 49 | 不存在pool,无法调用autorelease 50 | } 51 | } 52 | 调用autorelease,对象会被追加到自动释放池NSAutoreleasePool中的数组中,当自动释放池的pool执行[pool drain]方法时,会释放掉自动释放池中的数组,代码操作如下 53 | - (void)drain { 54 | [self dealloc]; 55 | } 56 | 57 | - (void)dealloc { 58 | [self emptyPool]; 59 | [array release]; 60 | } 61 | - (void)emptyPool { 62 | for (id obj in array) { 63 | [obj release]; 64 | } 65 | } 66 | */ 67 | 68 | 69 | 70 | } 71 | // MARK: 引用计数器的原理 72 | /* 73 | 通过散列表来表示引用计数器表简直为内存地址,对应的value是引用计数 74 | */ 75 | 76 | // MARK: 类方法的引用计数 77 | @end 78 | -------------------------------------------------------------------------------- /OCDeepLearning/OCBaseCellModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // OCBaseCellModel.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/6/15. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface OCBaseCellModel : NSObject 12 | 13 | @property(nonatomic, copy) NSString *btnName; 14 | @property(nonatomic, copy) NSString *labelName; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /OCDeepLearning/OCBaseCellModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // OCBaseCellModel.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/6/15. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "OCBaseCellModel.h" 10 | 11 | @implementation OCBaseCellModel 12 | 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /OCDeepLearning/OCBaseManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // OCBaseManager.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/6/28. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface OCBaseManager : NSObject 12 | 13 | + (instancetype)sharedInstance; 14 | 15 | - (void)insertContentInSourceDict:(NSArray *)insertArray keyName:(NSString *)keyName; 16 | - (NSArray *)getArrayFromDictOfKey:(NSString *)keyString; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /OCDeepLearning/OCBaseManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // OCBaseManager.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/6/28. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | /* 10 | 此类作为所有功能类数据源的描述,英语管理数据源 11 | 12 | */ 13 | #import "OCBaseManager.h" 14 | 15 | @interface OCBaseManager () 16 | @property(nonatomic, strong) NSMutableDictionary *sourceDict; 17 | 18 | @end 19 | 20 | @implementation OCBaseManager 21 | 22 | + (instancetype)sharedInstance { 23 | static OCBaseManager *sharedInstance = nil; 24 | static dispatch_once_t onceToken; 25 | dispatch_once(&onceToken, ^{ 26 | if (!sharedInstance) { 27 | sharedInstance = [[self alloc] init]; 28 | } 29 | }); 30 | return sharedInstance; 31 | } 32 | 33 | 34 | - (void)insertContentInSourceDict:(NSArray *)insertArray keyName:(NSString *)keyName { 35 | [self.sourceDict setObject:insertArray forKey:keyName]; 36 | 37 | } 38 | 39 | - (NSArray *)getArrayFromDictOfKey:(NSString *)keyString { 40 | 41 | NSArray *tmpArray = [self.sourceDict valueForKey:keyString]; 42 | return tmpArray; 43 | } 44 | 45 | 46 | 47 | @end 48 | -------------------------------------------------------------------------------- /OCDeepLearning/OCBaseTableViewCell+ConfigModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // OCBaseTableViewCell+ConfigModel.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/6/15. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "OCBaseTableViewCell.h" 10 | #import "OCBaseCellModel.h" 11 | 12 | @interface OCBaseTableViewCell (ConfigModel) 13 | 14 | 15 | - (void)configureDataForCell:(OCBaseCellModel *)model; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /OCDeepLearning/OCBaseTableViewCell+ConfigModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // OCBaseTableViewCell+ConfigModel.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/6/15. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "OCBaseTableViewCell+ConfigModel.h" 10 | 11 | @implementation OCBaseTableViewCell (ConfigModel) 12 | 13 | 14 | - (void)configureDataForCell:(OCBaseCellModel *)model { 15 | self.customLabel.text = model.labelName; 16 | self.customBtn.titleLabel.text = model.btnName; 17 | self.customBtn.backgroundColor = [UIColor orangeColor]; 18 | } 19 | 20 | 21 | @end 22 | 23 | -------------------------------------------------------------------------------- /OCDeepLearning/OCBaseTableViewCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // OCBaseTableViewCell.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/6/15. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface OCBaseTableViewCell : UITableViewCell 12 | @property(nonatomic, strong) UIButton *customBtn; 13 | @property(nonatomic, strong) UILabel *customLabel; 14 | @end 15 | -------------------------------------------------------------------------------- /OCDeepLearning/OCBaseTableViewCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // OCBaseTableViewCell.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/6/15. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "OCBaseTableViewCell.h" 10 | 11 | 12 | @interface OCBaseTableViewCell () 13 | 14 | 15 | @end 16 | 17 | @implementation OCBaseTableViewCell 18 | 19 | 20 | 21 | - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { 22 | 23 | if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) { 24 | [self setupUI]; 25 | } 26 | return self; 27 | } 28 | 29 | 30 | - (void) setupUI { 31 | self.customBtn = [UIButton buttonWithType:UIButtonTypeSystem]; 32 | self.customBtn.frame = CGRectMake(10, 10, 30, 30); 33 | 34 | [self.contentView addSubview:self.customBtn]; 35 | 36 | self.customLabel = [[UILabel alloc] init]; 37 | self.customLabel.frame = CGRectMake(100, 0, 200, 40); 38 | 39 | [self.contentView addSubview:self.customLabel]; 40 | } 41 | 42 | #pragma mark - lazy 43 | 44 | 45 | 46 | - (void)awakeFromNib { 47 | [super awakeFromNib]; 48 | // Initialization code 49 | } 50 | 51 | - (void)setSelected:(BOOL)selected animated:(BOOL)animated { 52 | [super setSelected:selected animated:animated]; 53 | 54 | // Configure the view for the selected state 55 | } 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /OCDeepLearning/OCBaseTableViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // OCBaseTableViewController.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/6/15. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface OCBaseTableViewController : UITableViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /OCDeepLearning/OCBaseTableViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // OCBaseTableViewController.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/6/15. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "OCBaseTableViewController.h" 10 | #import "OCBaseTableViewCell.h" 11 | #import "OCBaseTableViewCell+ConfigModel.h" 12 | #import "OCBaseCellModel.h" 13 | #import "StudentDataManager.h" 14 | 15 | static NSString* const kBaseIdentifier = @"baseIdentifier"; 16 | 17 | @interface OCBaseTableViewController () 18 | @property(nonatomic, strong) NSArray *DBActionArray; 19 | 20 | @end 21 | 22 | @implementation OCBaseTableViewController 23 | 24 | - (void)viewDidLoad { 25 | [super viewDidLoad]; 26 | 27 | // Uncomment the following line to preserve selection between presentations. 28 | // self.clearsSelectionOnViewWillAppear = NO; 29 | 30 | // Uncomment the following line to display an Edit button in the navigation bar for this view controller. 31 | // self.navigationItem.rightBarButtonItem = self.editButtonItem; 32 | 33 | [self.tableView registerClass:[OCBaseTableViewCell class] forCellReuseIdentifier:kBaseIdentifier]; 34 | self.DBActionArray = @[@"增加单条数据",@"增加多条数据",@"删除单条数据",@"删除多条数据",@"更改单条数据",@"更改多条数据",@"查询单条数据",@"查询多条数据"]; 35 | } 36 | 37 | - (void)didReceiveMemoryWarning { 38 | [super didReceiveMemoryWarning]; 39 | // Dispose of any resources that can be recreated. 40 | } 41 | 42 | #pragma mark - Table view data source 43 | 44 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 45 | return 1; 46 | } 47 | 48 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 49 | 50 | // return [[StudentDataManager sharedInstance] fetchMassData]; 51 | return self.DBActionArray.count; 52 | } 53 | 54 | 55 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 56 | OCBaseTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kBaseIdentifier forIndexPath:indexPath]; 57 | 58 | if (!cell) { 59 | cell = [[OCBaseTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kBaseIdentifier]; 60 | } 61 | 62 | 63 | 64 | // Configure the cell... 65 | OCBaseCellModel *baseModel = [[OCBaseCellModel alloc] init]; 66 | baseModel.btnName = @"按钮"; 67 | if (indexPath.row < 8) { 68 | baseModel.labelName = self.DBActionArray[indexPath.row]; 69 | } else { 70 | baseModel.labelName = @"越界"; 71 | } 72 | 73 | [cell configureDataForCell:baseModel]; 74 | 75 | return cell; 76 | } 77 | 78 | 79 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 80 | 81 | if (indexPath.row == 0) { 82 | [[StudentDataManager sharedInstance] saveSingleData]; 83 | } 84 | if (indexPath.row == 1) { 85 | [[StudentDataManager sharedInstance] saveMassData]; 86 | } 87 | if (indexPath.row == 2) { 88 | [[StudentDataManager sharedInstance] deleteSingleData]; 89 | } 90 | if (indexPath.row == 3) { 91 | [[StudentDataManager sharedInstance] deleteMassData]; 92 | } 93 | if (indexPath.row == 4) { 94 | [[StudentDataManager sharedInstance] updateSingleData]; 95 | } 96 | if (indexPath.row == 5) { 97 | [[StudentDataManager sharedInstance] updateMassData]; 98 | } 99 | if (indexPath.row == 6) { 100 | [[StudentDataManager sharedInstance] fetchSingleData]; 101 | } 102 | if (indexPath.row == 7) { 103 | [[StudentDataManager sharedInstance] fetchMassData]; 104 | } 105 | 106 | 107 | } 108 | /* 109 | // Override to support conditional editing of the table view. 110 | - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { 111 | // Return NO if you do not want the specified item to be editable. 112 | return YES; 113 | } 114 | */ 115 | 116 | /* 117 | // Override to support editing the table view. 118 | - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { 119 | if (editingStyle == UITableViewCellEditingStyleDelete) { 120 | // Delete the row from the data source 121 | [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; 122 | } else if (editingStyle == UITableViewCellEditingStyleInsert) { 123 | // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view 124 | } 125 | } 126 | */ 127 | 128 | /* 129 | // Override to support rearranging the table view. 130 | - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath { 131 | } 132 | */ 133 | 134 | /* 135 | // Override to support conditional rearranging of the table view. 136 | - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath { 137 | // Return NO if you do not want the item to be re-orderable. 138 | return YES; 139 | } 140 | */ 141 | 142 | /* 143 | #pragma mark - Navigation 144 | 145 | // In a storyboard-based application, you will often want to do a little preparation before navigation 146 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 147 | // Get the new view controller using [segue destinationViewController]. 148 | // Pass the selected object to the new view controller. 149 | } 150 | */ 151 | 152 | @end 153 | -------------------------------------------------------------------------------- /OCDeepLearning/OCDLLayer.h: -------------------------------------------------------------------------------- 1 | // 2 | // OCDLLayer.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/5/22. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface OCDLLayer : CALayer 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /OCDeepLearning/OCDLLayer.m: -------------------------------------------------------------------------------- 1 | // 2 | // OCDLLayer.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/5/22. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "OCDLLayer.h" 10 | 11 | @implementation OCDLLayer 12 | 13 | - (void)cus { 14 | // self.contents 15 | } 16 | @end 17 | -------------------------------------------------------------------------------- /OCDeepLearning/OCDLView.h: -------------------------------------------------------------------------------- 1 | // 2 | // OCDLView.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/5/22. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface OCDLView : UIView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /OCDeepLearning/OCDLView.m: -------------------------------------------------------------------------------- 1 | // 2 | // OCDLView.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/5/22. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "OCDLView.h" 10 | 11 | @implementation OCDLView 12 | 13 | /* 14 | // Only override drawRect: if you perform custom drawing. 15 | // An empty implementation adversely affects performance during animation. 16 | - (void)drawRect:(CGRect)rect { 17 | // Drawing code 18 | } 19 | */ 20 | 21 | - (void)test { 22 | // UIView *a = [UIView alloc] initWithFrame:cgrect 23 | 24 | } 25 | 26 | 27 | 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /OCDeepLearning/OCDataSourceManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // OCDataSourceManager.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/8/29. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface OCDataSourceManager : NSObject 12 | 13 | + (instancetype)sharedInstance; 14 | 15 | //获取方法调用次数 16 | - (void)writeCallCountOfMethod:(NSString *)methodName; 17 | @end 18 | -------------------------------------------------------------------------------- /OCDeepLearning/OCDataSourceManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // OCDataSourceManager.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/8/29. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "OCDataSourceManager.h" 10 | 11 | 12 | @interface OCDataSourceManager() 13 | @property(nonatomic, copy) NSDictionary *callCountDict; 14 | @end 15 | 16 | 17 | @implementation OCDataSourceManager 18 | 19 | + (instancetype)sharedInstance { 20 | static OCDataSourceManager *sharedInstance = nil; 21 | static dispatch_once_t onceToken; 22 | dispatch_once(&onceToken, ^{ 23 | sharedInstance = [[self alloc] init]; 24 | }); 25 | return sharedInstance; 26 | } 27 | 28 | - (void)writeCallCountOfMethod:(NSString *)methodName{ 29 | NSNumber *callCount = [self.callCountDict valueForKey:methodName]; 30 | NSInteger count = [callCount integerValue]; 31 | count = count + 1; 32 | callCount = [NSNumber numberWithInteger:count]; 33 | [self.callCountDict setValue:callCount forKey:methodName]; 34 | NSLog(@"oc_函数调用次数的字典是%@",self.callCountDict); 35 | } 36 | 37 | - (NSDictionary *)callCountDict { 38 | if (!_callCountDict) { 39 | _callCountDict = [NSDictionary dictionary]; 40 | } 41 | return _callCountDict; 42 | } 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /OCDeepLearning/OCDeepLearning.xcdatamodeld/OCDeepLearningModel.xcdatamodel/contents: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /OCDeepLearning/OCDeepLearningModel.xcdatamodeld/OCDeepLearningModel.xcdatamodel/contents: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /OCDeepLearning/OCFuntionStyleViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // OCFuntionStyleViewController.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/6/27. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "BaseViewController.h" 10 | 11 | @interface OCFuntionStyleViewController : BaseViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /OCDeepLearning/OCFuntionStyleViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // OCFuntionStyleViewController.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/6/27. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | /* 9 | * 定义各种功能,Demo的入口,便于统一管理 10 | */ 11 | 12 | #import "OCFuntionStyleViewController.h" 13 | #import "CTMediator.h" 14 | 15 | 16 | static NSString* const kFuntionStyle = @"funtionStyle"; 17 | 18 | @interface OCFuntionStyleViewController () 19 | @property(nonatomic, strong) UITableView *funtionStyleTableView; 20 | @property(nonatomic, strong) NSArray *funtionStyleArray; 21 | 22 | @end 23 | 24 | @implementation OCFuntionStyleViewController 25 | 26 | - (void)viewDidLoad { 27 | [super viewDidLoad]; 28 | // Do any additional setup after loading the view. 29 | self.funtionStyleArray = @[@"NSUserDefaults方案",@"Plist方案",@"KeyChains方案",@"NSCoder/NSDecoder方案",@"CoreData方案"]; 30 | [self.funtionStyleTableView registerClass:[UITableViewCell class] forCellReuseIdentifier:kFuntionStyle]; 31 | [self.view addSubview:self.funtionStyleTableView]; 32 | 33 | } 34 | 35 | - (void)didReceiveMemoryWarning { 36 | [super didReceiveMemoryWarning]; 37 | // Dispose of any resources that can be recreated. 38 | } 39 | 40 | #pragma mark - lazy 41 | - (UITableView *)funtionStyleTableView { 42 | if (!_funtionStyleTableView) { 43 | _funtionStyleTableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain]; 44 | _funtionStyleTableView.delegate = self; 45 | _funtionStyleTableView.dataSource = self; 46 | } 47 | return _funtionStyleTableView; 48 | } 49 | 50 | #pragma mark - UITableViewDelegate,UITableViewDataSource 51 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 52 | return self.funtionStyleArray.count; 53 | } 54 | 55 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 56 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kFuntionStyle forIndexPath:indexPath]; 57 | if (!cell) { 58 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kFuntionStyle]; 59 | } 60 | cell.textLabel.text = self.funtionStyleArray[indexPath.row]; 61 | return cell; 62 | } 63 | 64 | - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { 65 | UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(20, 0, 100, 30)]; 66 | label.text = @"数据库储存"; 67 | return label; 68 | } 69 | 70 | - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { 71 | return 50; 72 | } 73 | 74 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 75 | if (indexPath.row == 4) { 76 | 77 | // [CTMediator sharedInstance] performTarget:<#(NSString *)#> action:<#(NSString *)#> params:<#(NSDictionary *)#> shouldCacheTarget:<#(BOOL)#> 78 | } 79 | 80 | } 81 | 82 | @end 83 | -------------------------------------------------------------------------------- /OCDeepLearning/OCLearningOOP+GetPrivate.h: -------------------------------------------------------------------------------- 1 | // 2 | // OCLearningOOP+GetPrivate.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2018/9/27. 6 | // Copyright © 2018 walker彬. All rights reserved. 7 | // 8 | 9 | #import "OCLearningOOP.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface OCLearningOOP (GetPrivate) 14 | - (void)privateMethodOfOCLearningOOPByCategory; 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /OCDeepLearning/OCLearningOOP+GetPrivate.m: -------------------------------------------------------------------------------- 1 | // 2 | // OCLearningOOP+GetPrivate.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2018/9/27. 6 | // Copyright © 2018 walker彬. All rights reserved. 7 | // 8 | 9 | #import "OCLearningOOP+GetPrivate.h" 10 | 11 | @implementation OCLearningOOP (GetPrivate) 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /OCDeepLearning/OCLearningOOP.h: -------------------------------------------------------------------------------- 1 | // 2 | // OCLearningOOP.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2018/9/27. 6 | // Copyright © 2018 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface OCLearningOOP : NSObject 15 | 16 | @property(nonatomic, assign) NSInteger father; 17 | 18 | @end 19 | 20 | NS_ASSUME_NONNULL_END 21 | 22 | 23 | @interface OCLearningOOPChild1 : OCLearningOOP 24 | @property(nonatomic, assign) NSInteger child1; 25 | 26 | @end 27 | 28 | @interface OCLearningOOPChild2 : OCLearningOOPChild1 29 | @property(nonatomic, assign) NSInteger child2; 30 | 31 | @end 32 | 33 | @interface OCLearningOOPChild3 : OCLearningOOPChild2 34 | @property(nonatomic, assign) NSInteger child3; 35 | 36 | @end 37 | 38 | @interface OCLearningOOPChild4 : OCLearningOOPChild3 39 | @property(nonatomic, assign) NSInteger child4; 40 | 41 | - (void)testSizeOfIvarsList; 42 | @end 43 | -------------------------------------------------------------------------------- /OCDeepLearning/OCLearningOOP.m: -------------------------------------------------------------------------------- 1 | // 2 | // OCLearningOOP.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2018/9/27. 6 | // Copyright © 2018 walker彬. All rights reserved. 7 | // 8 | 9 | 10 | 11 | 12 | /*AIM: 13 | * 1. 包含实例h方法和类方法 14 | * 2. 包装成协议,方便其他人调用 15 | * 3. 方法带有参数的扩展 16 | */ 17 | 18 | 19 | 20 | #import "OCLearningOOP.h" 21 | #import 22 | #import 23 | 24 | 25 | @interface OCLearningOOP () { 26 | NSString *name; 27 | } 28 | 29 | @property(nonatomic, copy) NSString *secret; 30 | 31 | @end 32 | 33 | @implementation OCLearningOOP 34 | 35 | - (void)privateMethodOfOCLearningOOPByCategory { 36 | NSLog(@"哈哈哈,通过分类,实现私有方法的调用"); 37 | } 38 | 39 | - (void)privateMethod:(NSString *)a { 40 | NSLog(@"哈哈哈,私有的对象方法"); 41 | } 42 | 43 | - (void)privateMethod2:(NSString *)name { 44 | NSLog(@"哈哈哈,私有的对象方法2,\n参数为%@",name); 45 | } 46 | 47 | 48 | + (void)privateClassMethod:(NSString *)a { 49 | NSLog(@"哈哈哈,私有的类方法"); 50 | } 51 | 52 | @end 53 | 54 | 55 | @implementation OCLearningOOPChild1 56 | 57 | @end 58 | 59 | @implementation OCLearningOOPChild2 60 | 61 | @end 62 | 63 | 64 | @implementation OCLearningOOPChild3 65 | 66 | @end 67 | 68 | 69 | @implementation OCLearningOOPChild4 70 | 71 | void logSize() { 72 | 73 | } 74 | 75 | - (void)getPrivateIvarByCategory { 76 | 77 | } 78 | 79 | @end 80 | 81 | 82 | -------------------------------------------------------------------------------- /OCDeepLearning/OCSaveDataTableViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // OCSaveDataTableViewController.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/6/27. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface OCSaveDataTableViewController : UITableViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /OCDeepLearning/OCSaveDataTableViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // OCSaveDataTableViewController.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/6/27. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "OCSaveDataTableViewController.h" 10 | 11 | static NSString* const kOCSaveDataIdentifier = @"OCSaveDataIdentifier"; 12 | 13 | @interface OCSaveDataTableViewController () 14 | @property(nonatomic, strong) NSArray *saveStyleArray; 15 | 16 | @end 17 | 18 | @implementation OCSaveDataTableViewController 19 | 20 | - (void)viewDidLoad { 21 | [super viewDidLoad]; 22 | 23 | [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:kOCSaveDataIdentifier]; 24 | self.saveStyleArray = @[@"NSUserDefaults方式",@"Plist方式",@"NSCoder和NSDecoder方式",@"数据库方式"]; 25 | } 26 | 27 | - (void)didReceiveMemoryWarning { 28 | [super didReceiveMemoryWarning]; 29 | // Dispose of any resources that can be recreated. 30 | } 31 | 32 | #pragma mark - Table view data source 33 | 34 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 35 | return self.saveStyleArray.count; 36 | } 37 | 38 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 39 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kOCSaveDataIdentifier forIndexPath:indexPath]; 40 | if (!cell) { 41 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kOCSaveDataIdentifier]; 42 | cell.textLabel.text = self.saveStyleArray[indexPath.row]; 43 | } 44 | return cell; 45 | } 46 | 47 | @end 48 | -------------------------------------------------------------------------------- /OCDeepLearning/OCSaveManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // OCSaveManager.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/6/28. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface OCSaveManager : NSObject 12 | 13 | + (instancetype)sharedInstance; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /OCDeepLearning/OCSaveManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // OCSaveManager.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/6/28. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "OCSaveManager.h" 10 | typedef NS_ENUM(NSInteger, OCSaveStyle) { 11 | OCSaveStyleUserDefault = 0, 12 | OCSaveStylePlist, 13 | OCSaveStyleCoder, 14 | OCSaveStyleKeychain, 15 | OCSaveStyleCoreData 16 | }; 17 | 18 | @interface OCSaveManager () 19 | @property(nonatomic, assign) OCSaveStyle saveStyle; 20 | 21 | @end 22 | 23 | 24 | @implementation OCSaveManager 25 | 26 | 27 | + (instancetype)sharedInstance { 28 | static OCSaveManager *sharedInstance = nil; 29 | static dispatch_once_t onceToken; 30 | dispatch_once(&onceToken, ^{ 31 | sharedInstance = [[self alloc] init]; 32 | }); 33 | 34 | return sharedInstance; 35 | } 36 | 37 | 38 | - (void)saveDataByStyle:(OCSaveStyle)style { 39 | if (style == OCSaveStylePlist) { 40 | //存数据 41 | NSArray *array = @[@"第1个保存数据",@"第2个保存数据",@"第3个保存数据",@"第4个保存数据"]; 42 | NSString *cachePath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject; 43 | NSString *filePathName = [cachePath stringByAppendingPathComponent:@"name.plist"]; 44 | [array writeToFile:filePathName atomically:YES]; 45 | 46 | //取数据 47 | NSString *getCachePath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES).firstObject; 48 | NSString *getFilePathName = [getCachePath stringByAppendingPathComponent:@"name.plist"]; 49 | NSArray *getArray = [NSArray arrayWithContentsOfFile:getFilePathName]; 50 | NSLog(@"Plist取出保存的数据%@",getArray); 51 | 52 | } else if (style == OCSaveStyleUserDefault) { 53 | //存数据 54 | [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"hasValueOfUserDefault"]; 55 | [[NSUserDefaults standardUserDefaults] synchronize]; 56 | 57 | //取数据 58 | BOOL tmpBOOL = [[NSUserDefaults standardUserDefaults] boolForKey:@"hasValueOfUserDefault"]; 59 | NSLog(@"NSUserDefault取出的数据%d",tmpBOOL); 60 | 61 | } else if (style == OCSaveStyleKeychain) { 62 | 63 | } 64 | } 65 | 66 | 67 | 68 | 69 | @end 70 | -------------------------------------------------------------------------------- /OCDeepLearning/OC_AClass.h: -------------------------------------------------------------------------------- 1 | // 2 | // OC_AClass.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2017/7/17. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface OC_AClass : NSObject 12 | 13 | - (void)testName; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /OCDeepLearning/OC_AClass.m: -------------------------------------------------------------------------------- 1 | // 2 | // OC_AClass.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2017/7/17. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "OC_AClass.h" 10 | 11 | @interface OC_AClass () 12 | 13 | @property(nonatomic, strong) NSString *name; 14 | 15 | @end 16 | 17 | @implementation OC_AClass 18 | { 19 | NSString *customName; //成员变量 20 | } 21 | 22 | @synthesize name = customName; 23 | 24 | 25 | - (void)testName { 26 | // _name = @"_Walker"; 27 | customName = @"Walker"; 28 | NSLog(@"%@",self.name); //打印结果为 Walker 29 | 30 | 31 | } 32 | @end 33 | -------------------------------------------------------------------------------- /OCDeepLearning/OC_IMP.h: -------------------------------------------------------------------------------- 1 | // 2 | // OC_IMP.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2017/7/14. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface OC_IMP : NSObject 13 | - (void)testIMP; 14 | @end 15 | -------------------------------------------------------------------------------- /OCDeepLearning/OC_IMP.m: -------------------------------------------------------------------------------- 1 | // 2 | // OC_IMP.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2017/7/14. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "OC_IMP.h" 10 | 11 | 12 | typedef void (^CustomBlock)(NSString *name); 13 | 14 | @interface OC_IMP () 15 | 16 | @property(nonatomic, weak) CustomBlock block; 17 | 18 | @end 19 | 20 | @implementation OC_IMP 21 | 22 | - (void)testIMP { 23 | [self addMethodByIMP]; 24 | } 25 | 26 | //定义一个block 27 | //手动添加方法 28 | - (void)addMethodByIMP { 29 | CustomBlock block = ^(NSString *name){ 30 | NSLog(@"执行block"); 31 | }; 32 | 33 | IMP impBlock = imp_implementationWithBlock(block); 34 | Method m = class_getInstanceMethod(self.class, @selector(testIMP)); 35 | method_setImplementation(m, impBlock); 36 | const char * types = method_getTypeEncoding(m); //因为方法类型相同(都是无参数无返回值类型,所以方法类型相同,如果知道的话,可以直接制定type为v16@0:8) 37 | sel_registerName("newSel"); //注册newSel 38 | BOOL isAdded = class_addMethod([self class], @selector(newSel), impBlock, types); 39 | if (isAdded == YES) { 40 | NSLog(@"当前类为%@:手动添加IMP成功",[self class]); 41 | [self performSelector:@selector(newSel)]; 42 | } 43 | } 44 | 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /OCDeepLearning/OC_Method.h: -------------------------------------------------------------------------------- 1 | // 2 | // OC_Method.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2017/7/14. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface OC_Method : NSObject 13 | 14 | - (void)testMethod; 15 | @end 16 | -------------------------------------------------------------------------------- /OCDeepLearning/OC_Method.m: -------------------------------------------------------------------------------- 1 | // 2 | // OC_Method.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2017/7/14. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "OC_Method.h" 10 | 11 | @implementation OC_Method 12 | 13 | - (void)testMethod { 14 | //次类比较直观参考OC_IMP即可 15 | NSLog(@"%@---次类比较直观参考OC_IMP即可",[self class]); 16 | } 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /OCDeepLearning/OC_Method.temp_caseinsensitive_rename.m: -------------------------------------------------------------------------------- 1 | // 2 | // OC_method.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2017/7/14. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "OC_method.h" 10 | 11 | @implementation OC_Method 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /OCDeepLearning/OC_SEL.h: -------------------------------------------------------------------------------- 1 | // 2 | // OC_SEL.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2017/7/14. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface OC_SEL : NSObject 13 | 14 | - (void)testSEL; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /OCDeepLearning/OC_SEL.m: -------------------------------------------------------------------------------- 1 | // 2 | // SEL.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2017/7/14. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "OC_SEL.h" 10 | 11 | 12 | @implementation OC_SEL 13 | 14 | - (void)testSEL { 15 | SEL SEL1Name = sel_getUid("SEL1"); //获取SEL的名字 16 | NSLog(@"当前类为%@,%s",[self class],SEL1Name); 17 | 18 | // SEL SEL1Name = NSSelectorFromString(@"SEL1"); 和上述方法结果相同 19 | 20 | //SEL是存在系统的某处,所以即使不是当前类的方法,也可以判断是否存在 21 | SEL viewDidLoad = sel_getUid("viewDidLoad"); 22 | BOOL isMapped = sel_isMapped(viewDidLoad); 23 | NSLog(@"%i",isMapped); 24 | } 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /OCDeepLearning/Person+ForwardMessage.h: -------------------------------------------------------------------------------- 1 | // 2 | // Person+ForwardMessage.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2017/7/13. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "Person.h" 10 | 11 | @interface Person (ForwardMessage) 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /OCDeepLearning/Person+ForwardMessage.m: -------------------------------------------------------------------------------- 1 | // 2 | // Person+ForwardMessage.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2017/7/13. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "Person+ForwardMessage.h" 10 | #import 11 | #import "Bird.h" 12 | 13 | 14 | @implementation Person (ForwardMessage) 15 | 16 | 17 | // MARK: 实例方法的消息转发 18 | /** 19 | 消息转发 20 | */ 21 | //// MARK: 实例方法的转发流程 22 | //// STEP 1: 23 | //// 在没有找到方法时,会先调用此方法,可用于动态添加方法 24 | //// 返回 YES 表示相应 selector 的实现已经被找到并添加到了类中,否则返回 NO 25 | + (BOOL)resolveInstanceMethod:(SEL)sel { 26 | return YES; 27 | } 28 | 29 | //如果调用fly方法,则将方法对象变化为bird,执行[bird fly] 30 | - (id)forwardingTargetForSelector:(SEL)aSelector { 31 | Bird *bird =[[Bird alloc] init]; 32 | if (aSelector == @selector(fly)) { 33 | return bird; 34 | } 35 | return nil; 36 | } 37 | 38 | - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector { 39 | return [NSMethodSignature signatureWithObjCTypes:"v@:"]; 40 | } 41 | 42 | - (void)forwardInvocation:(NSInvocation *)anInvocation { 43 | // 我们还可以改变方法选择器 44 | [anInvocation setSelector:@selector(live)]; 45 | // 改变方法选择器后,还需要指定是哪个对象的方法 46 | [anInvocation invokeWithTarget:self]; 47 | } 48 | 49 | - (void)live { 50 | NSLog(@"Person 没有实现 -die 方法,并且成功的转成了 -live 方法"); 51 | } 52 | 53 | - (void)doesNotRecognizeSelector:(SEL)aSelector { 54 | NSLog(@"无法处理消息:%@", NSStringFromSelector(aSelector)); 55 | } 56 | 57 | // MARK: 类方法的消息转发 58 | + (BOOL)resolveClassMethod:(SEL)sel { 59 | return NO; 60 | } 61 | 62 | + (id)forwardingTargetForSelector:(SEL)aSelector { 63 | return nil; 64 | } 65 | 66 | + (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector { 67 | return [NSMethodSignature signatureWithObjCTypes:"v@:"]; 68 | } 69 | 70 | + (void)forwardInvocation:(NSInvocation *)anInvocation { 71 | [anInvocation setSelector:@selector(classLive)]; 72 | [anInvocation invokeWithTarget:self]; 73 | } 74 | 75 | + (void)classLive { 76 | NSLog(@"Person 没有实现 +classDie 方法,并且成功的转成了 +classLive 方法"); 77 | } 78 | 79 | + (void)doesNotRecognizeSelector:(SEL)aSelector { 80 | NSLog(@"无法处理消息:%@", NSStringFromSelector(aSelector)); 81 | } 82 | 83 | 84 | @end 85 | -------------------------------------------------------------------------------- /OCDeepLearning/Person.h: -------------------------------------------------------------------------------- 1 | // 2 | // Person.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2017/7/13. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface Person : NSObject 12 | 13 | - (void)run; 14 | - (void)fly; 15 | - (void)die; 16 | 17 | + (void)classDie; 18 | 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /OCDeepLearning/Person.m: -------------------------------------------------------------------------------- 1 | // 2 | // Person.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2017/7/13. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "Person.h" 10 | 11 | @implementation Person 12 | 13 | - (void)run { 14 | NSLog(@"%@----调用Run方法----",[self class]); 15 | } 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /OCDeepLearning/REDEMEProtocol.h: -------------------------------------------------------------------------------- 1 | // 2 | // REDEMEProtocol.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2018/7/29. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @protocol REDEMEProtocol 13 | 14 | @optional 15 | - (void)fetchData:(NSString *)fetcherName didReceiveData:(NSData *)data; 16 | - (void)fetchData:(NSString *)fetcherName didFailWithError:(NSError *)error; 17 | //- (void)fetchData:(NSString *)fetcherName didReceiveDataSuccess:(NSData *)data; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /OCDeepLearning/ReadMeNSObjcet.h: -------------------------------------------------------------------------------- 1 | // 2 | // ReadMeNSObjcet.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2018/7/29. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ReadMeNSObjcet : NSObject 12 | 13 | + (void)learnIDTypeInCollection; 14 | @end 15 | -------------------------------------------------------------------------------- /OCDeepLearning/ReadMeNSObjcet.m: -------------------------------------------------------------------------------- 1 | // 2 | // ReadMeNSObjcet.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2018/7/29. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "ReadMeNSObjcet.h" 10 | 11 | 12 | @interface ReadMeNSObjcet() 13 | 14 | 15 | 16 | @end 17 | 18 | @implementation ReadMeNSObjcet 19 | 20 | 21 | 22 | //OC中,集合类中的元素,遍历取值,其元素都是id类型,而非强类型 23 | /* 24 | 1. 数组的元素可以为多种对象类型 25 | */ 26 | + (void)learnIDTypeInCollection { 27 | //数组 28 | NSDictionary *learnDict = @{@"key": @"value"}; 29 | NSArray *learnArray = [NSArray arrayWithObjects:@"11", @2, learnDict, nil]; 30 | for (id obj in learnArray) { 31 | if ([obj isKindOfClass:[NSString class]]) { 32 | NSLog(@"是NSString类型,值为%@",obj); 33 | } else if ([obj isKindOfClass:[NSNumber class]]) { 34 | NSLog(@"是NSNumber类型,值为%@",obj); 35 | } else if ([obj isKindOfClass:[NSDictionary class]]) { 36 | NSLog(@"是NSDictionary类型,值为%@",obj); 37 | } 38 | 39 | } 40 | 41 | // NSExceptionName 42 | // [NSException exceptionWithName:<#(nonnull NSExceptionName)#> reason:<#(nullable NSString *)#> userInfo:<#(nullable NSDictionary *)#> 43 | 44 | } 45 | 46 | 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /OCDeepLearning/SecondTestViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SecondTestViewController.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/6/26. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "BaseViewController.h" 10 | 11 | @interface SecondTestViewController : BaseViewController 12 | - (void)changeBackgroundColor:(NSInteger)a; 13 | @end 14 | -------------------------------------------------------------------------------- /OCDeepLearning/SecondTestViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // SecondTestViewController.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/6/26. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "SecondTestViewController.h" 10 | 11 | @interface SecondTestViewController () 12 | 13 | @end 14 | 15 | @implementation SecondTestViewController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | // Do any additional setup after loading the view. 20 | } 21 | 22 | - (void)didReceiveMemoryWarning { 23 | [super didReceiveMemoryWarning]; 24 | // Dispose of any resources that can be recreated. 25 | } 26 | 27 | - (void)changeBackgroundColor:(NSInteger)a { 28 | self.view.backgroundColor = [UIColor redColor]; 29 | int num = arc4random() % 255; 30 | 31 | [NSTimer scheduledTimerWithTimeInterval:3 repeats:YES block:^(NSTimer * _Nonnull timer) { 32 | self.view.backgroundColor = [UIColor colorWithRed:num green:num blue:num alpha:1]; 33 | }]; 34 | } 35 | /* 36 | #pragma mark - Navigation 37 | 38 | // In a storyboard-based application, you will often want to do a little preparation before navigation 39 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 40 | // Get the new view controller using [segue destinationViewController]. 41 | // Pass the selected object to the new view controller. 42 | } 43 | */ 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /OCDeepLearning/Student+CoreDataClass.h: -------------------------------------------------------------------------------- 1 | // 2 | // Student+CoreDataClass.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/6/22. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | // 9 | 10 | #import 11 | #import 12 | 13 | @class Course, Grade; 14 | 15 | NS_ASSUME_NONNULL_BEGIN 16 | 17 | @interface Student : NSManagedObject 18 | 19 | @end 20 | 21 | NS_ASSUME_NONNULL_END 22 | 23 | #import "Student+CoreDataProperties.h" 24 | -------------------------------------------------------------------------------- /OCDeepLearning/Student+CoreDataClass.m: -------------------------------------------------------------------------------- 1 | // 2 | // Student+CoreDataClass.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/6/22. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | // 9 | 10 | #import "Student+CoreDataClass.h" 11 | 12 | @implementation Student 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /OCDeepLearning/Student+CoreDataProperties.h: -------------------------------------------------------------------------------- 1 | // 2 | // Student+CoreDataProperties.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/6/22. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | // 9 | 10 | #import "Student+CoreDataClass.h" 11 | 12 | 13 | NS_ASSUME_NONNULL_BEGIN 14 | 15 | @interface Student (CoreDataProperties) 16 | 17 | + (NSFetchRequest *)fetchRequest; 18 | 19 | @property (nullable, nonatomic, copy) NSString *name; 20 | @property (nonatomic) int16_t age; 21 | @property (nonatomic) BOOL gender; 22 | @property (nonatomic) int16_t score; 23 | @property (nullable, nonatomic, retain) Grade *gradeStudent; 24 | @property (nullable, nonatomic, retain) Course *courseStudent; 25 | 26 | @end 27 | 28 | NS_ASSUME_NONNULL_END 29 | -------------------------------------------------------------------------------- /OCDeepLearning/Student+CoreDataProperties.m: -------------------------------------------------------------------------------- 1 | // 2 | // Student+CoreDataProperties.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/6/22. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | // 9 | 10 | #import "Student+CoreDataProperties.h" 11 | 12 | @implementation Student (CoreDataProperties) 13 | 14 | + (NSFetchRequest *)fetchRequest { 15 | return [[NSFetchRequest alloc] initWithEntityName:@"Student"]; 16 | } 17 | 18 | @dynamic name; 19 | @dynamic age; 20 | @dynamic gender; 21 | @dynamic score; 22 | @dynamic gradeStudent; 23 | @dynamic courseStudent; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /OCDeepLearning/StudentDataManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // StudentDataManager.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/6/21. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface StudentDataManager : NSObject 12 | + (instancetype)sharedInstance; 13 | 14 | //数据库操作的增删改查——(CRUD) 15 | - (void)saveSingleData; 16 | - (void)saveMassData; 17 | 18 | - (void)deleteSingleData; 19 | - (void)deleteMassData; 20 | 21 | - (void)updateSingleData; 22 | - (void)updateMassData; 23 | 24 | - (void)fetchSingleData; 25 | - (NSInteger)fetchMassData; 26 | 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /OCDeepLearning/StudentDataManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // StudentDataManager.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/6/21. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "StudentDataManager.h" 10 | #import "Student+CoreDataClass.h" 11 | #import "Grade+CoreDataClass.h" 12 | #import "Course+CoreDataClass.h" 13 | 14 | #import 15 | #import 16 | 17 | static StudentDataManager *sharedInstance = nil; 18 | 19 | @interface StudentDataManager () 20 | 21 | 22 | @property ( strong , nonatomic) NSManagedObjectContext *coreDataContext; 23 | @property ( strong , nonatomic) NSManagedObjectModel *coreDataModel; 24 | @property ( strong , nonatomic) NSPersistentStoreCoordinator *coreDataPersistent; 25 | 26 | @end 27 | 28 | 29 | @implementation StudentDataManager 30 | 31 | + (instancetype)sharedInstance { 32 | // static StudentDataManager *sharedInstance = nil; 33 | static dispatch_once_t onceToken; 34 | dispatch_once(&onceToken, ^{ 35 | if (!sharedInstance) { 36 | sharedInstance = [[StudentDataManager alloc] init]; 37 | } 38 | }); 39 | 40 | return sharedInstance; 41 | } 42 | 43 | //+(id) allocWithZone:(struct _NSZone *)zone 44 | //{ 45 | // return sharedInstance; 46 | //} 47 | // 48 | //-(id) copyWithZone:(struct _NSZone *)zone 49 | //{ 50 | // return sharedInstance; 51 | //} 52 | 53 | 54 | #pragma mark - 增加数据 55 | - (void)saveSingleData { 56 | Student *student = [NSEntityDescription insertNewObjectForEntityForName:@"Student" inManagedObjectContext:self.coreDataContext]; 57 | student.name = @"张三"; 58 | student.gender = YES; 59 | student.age = 11; 60 | student.score = 100; 61 | 62 | NSError *error; 63 | [self.coreDataContext save:&error]; 64 | if (![self.coreDataContext save:&error]) { 65 | NSLog(@"不能保存,原因是%@",error.localizedDescription); 66 | } 67 | } 68 | 69 | - (void)saveMassData { 70 | for (int i = 0;i < 100; i++) { 71 | Student *student = [NSEntityDescription insertNewObjectForEntityForName:@"Student" inManagedObjectContext:self.coreDataContext]; 72 | student.name = [NSString stringWithFormat:@"student-%d", i];; 73 | student.age = i; 74 | student.score = i; 75 | } 76 | NSError *error; 77 | [self.coreDataContext save:&error]; 78 | if (![self.coreDataContext save:&error]) { 79 | NSLog(@"不能保存,原因是%@",error.localizedDescription); 80 | } 81 | } 82 | 83 | #pragma mark - 删除数据 84 | - (void)deleteSingleData { 85 | 86 | // for (Student *student in students) { 87 | // [self.coreDataContext deleteObject:student]; 88 | // } 89 | // [self.coreDataContext save:nil]; // 最后不要忘了调用 save 使操作生效。 90 | } 91 | 92 | - (void)deleteMassData { 93 | NSFetchRequest *deleteFetch = [Student fetchRequest]; 94 | 95 | deleteFetch.predicate = [NSPredicate predicateWithFormat:@"age >= %@", @(50)]; 96 | 97 | NSBatchDeleteRequest *deleteRequest = [[NSBatchDeleteRequest alloc] initWithFetchRequest:deleteFetch]; 98 | deleteRequest.resultType = NSBatchDeleteResultTypeObjectIDs; 99 | 100 | NSBatchDeleteResult *deleteResult = [self.coreDataContext executeRequest:deleteRequest error:nil]; 101 | NSArray *deletedObjectIDs = deleteResult.result; 102 | 103 | NSDictionary *deletedDict = @{NSDeletedObjectsKey : deletedObjectIDs}; 104 | [NSManagedObjectContext mergeChangesFromRemoteContextSave:deletedDict intoContexts:@[self.coreDataContext]]; 105 | 106 | } 107 | 108 | #pragma mark - 更改数据 109 | - (void)updateSingleData { 110 | 111 | } 112 | 113 | - (void)updateMassData { 114 | 115 | // 根据 entityName 创建 116 | NSBatchUpdateRequest *updateRequest = [[NSBatchUpdateRequest alloc] initWithEntityName:@"Student"]; 117 | updateRequest.predicate = [NSPredicate predicateWithFormat:@"age == %@", @(20)]; 118 | updateRequest.propertiesToUpdate = @{@"name" : @"newName"}; 119 | updateRequest.resultType = NSUpdatedObjectIDsResultType; 120 | NSError *error; 121 | NSBatchUpdateResult *updateResult = [self.coreDataContext executeRequest:updateRequest error:&error]; 122 | NSArray *updatedObjectIDs = updateResult.result; 123 | NSLog(@"更改之后的结果为%@",updatedObjectIDs); 124 | 125 | NSDictionary *updatedDict = @{NSUpdatedObjectsKey : updatedObjectIDs}; 126 | [NSManagedObjectContext mergeChangesFromRemoteContextSave:updatedDict intoContexts:@[self.coreDataContext]]; 127 | } 128 | 129 | #pragma mark - 查询数据 130 | - (void)fetchSingleData { 131 | NSFetchRequest *fetchRequest = [Student fetchRequest]; 132 | fetchRequest.predicate = [NSPredicate predicateWithFormat:@"age > %@", @(90)]; 133 | fetchRequest.fetchLimit = 8; 134 | NSArray*sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"age" ascending:YES]]; 135 | fetchRequest.sortDescriptors = sortDescriptors; 136 | NSArray *students = [self.coreDataContext executeFetchRequest:fetchRequest error:nil]; 137 | NSLog(@"查询的结果是%@",students); 138 | } 139 | 140 | - (NSInteger )fetchMassData { 141 | NSFetchRequest *fetchRequest = [Student fetchRequest]; 142 | 143 | fetchRequest.predicate = [NSPredicate predicateWithFormat:@"age > %@", @(90)]; 144 | // fetchRequest.fetchLimit = 8; 145 | 146 | NSArray*sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"age" ascending:YES]]; 147 | fetchRequest.sortDescriptors = sortDescriptors; 148 | NSArray *students = [self.coreDataContext executeFetchRequest:fetchRequest error:nil]; 149 | NSLog(@"查询的结果是%@",students); 150 | 151 | return [students count]; 152 | 153 | } 154 | 155 | #pragma mark - lazy 156 | - (NSManagedObjectModel *)coreDataModel { 157 | if (!_coreDataModel) { 158 | _coreDataModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:[[NSBundle mainBundle] URLForResource:@"OCDeepLearning" withExtension:@"momd"]]; 159 | } 160 | return _coreDataModel; 161 | } 162 | 163 | - (NSPersistentStoreCoordinator *)coreDataPersistent { 164 | if (!_coreDataPersistent) { 165 | _coreDataPersistent = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self coreDataModel]]; 166 | NSString * path = [NSSearchPathForDirectoriesInDomains(NSDocumentationDirectory, NSUserDomainMask, YES) lastObject]; 167 | NSURL * pathURL = [NSURL fileURLWithPath:[path stringByAppendingString:@"OCDeepLearning.sqlite" ]]; 168 | NSLog(@"路径%@",pathURL); 169 | NSError * error = nil; 170 | 171 | NSDictionary *optionsDict = [NSDictionary dictionary]; 172 | [optionsDict setValue:[NSNumber numberWithBool:YES] forKey:NSMigratePersistentStoresAutomaticallyOption]; 173 | [optionsDict setValue:[NSNumber numberWithBool:YES] forKey:NSInferMappingModelAutomaticallyOption]; 174 | 175 | NSPersistentStore *store = [_coreDataPersistent addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:pathURL options:optionsDict error:&error]; 176 | if (!store) { 177 | [NSException raise:@"add database error" format:@"%@" ,[error localizedDescription]]; 178 | } 179 | } 180 | return _coreDataPersistent ; 181 | } 182 | 183 | - (NSManagedObjectContext *)coreDataContext { 184 | if(!_coreDataContext) 185 | { 186 | _coreDataContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; 187 | [_coreDataContext setPersistentStoreCoordinator:[self coreDataPersistent]]; 188 | } 189 | return _coreDataContext; 190 | } 191 | 192 | #pragma mark - 关联属性 193 | - (void)addCoursePropertyForStudent { 194 | Student *student = [NSEntityDescription insertNewObjectForEntityForName:@"Student" inManagedObjectContext:self.coreDataContext]; 195 | Grade *grade = [[Grade alloc] initWithContext:self.coreDataContext]; 196 | grade.gradeName = @"初一"; 197 | grade.gradeID = @"7"; 198 | student.gradeStudent = grade; 199 | [self.coreDataContext save:nil]; 200 | } 201 | 202 | 203 | @end 204 | -------------------------------------------------------------------------------- /OCDeepLearning/TestViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TestViewController.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/6/5. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TestViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /OCDeepLearning/TestViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // TestViewController.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/6/5. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "TestViewController.h" 10 | #import "NSObject+Runtime.h" 11 | @interface TestViewController () 12 | @property(nonatomic, strong) UIButton *exitButton; // 测试退出命令 13 | @property(nonatomic, strong) UIButton *addressButton; // 测试不同类型的内存地址 14 | 15 | @property(nonatomic, strong) UIView *blueView; 16 | @end 17 | 18 | @implementation TestViewController 19 | 20 | - (void)viewDidLoad { 21 | [super viewDidLoad]; 22 | // Do any additional setup after loading the view. 23 | 24 | [self setupUI]; 25 | } 26 | 27 | - (void)didReceiveMemoryWarning { 28 | [super didReceiveMemoryWarning]; 29 | // Dispose of any resources that can be recreated. 30 | } 31 | 32 | - (void)setupUI { 33 | self.view.backgroundColor = [UIColor whiteColor]; 34 | [self.view addSubview:self.exitButton]; 35 | [self.view addSubview:self.addressButton]; 36 | [self.view addSubview:self.blueView]; 37 | } 38 | 39 | #pragma mark - lazy 40 | 41 | - (UIButton *)exitButton { 42 | if (!_exitButton) { 43 | _exitButton = [UIButton buttonWithType:UIButtonTypeCustom]; 44 | _exitButton.frame = CGRectMake(100, 100, 50, 50); 45 | _exitButton.backgroundColor = [UIColor blueColor]; 46 | _exitButton.titleLabel.text = @"点击退出"; 47 | [_exitButton addTarget:self action:@selector(testExitCommand:) forControlEvents:UIControlEventTouchUpInside]; 48 | } 49 | return _exitButton; 50 | } 51 | 52 | - (UIButton *)addressButton { 53 | if (!_addressButton) { 54 | _addressButton = [UIButton buttonWithType:UIButtonTypeCustom]; 55 | _addressButton.frame = CGRectMake(100, 200, 50, 50); 56 | _addressButton.backgroundColor = [UIColor orangeColor]; 57 | _addressButton.titleLabel.text = @"获取内存地址"; 58 | [_addressButton addTarget:self action:@selector(alertMemberPointer) forControlEvents:UIControlEventTouchUpInside]; 59 | } 60 | return _addressButton; 61 | } 62 | 63 | - (UIView *)blueView { 64 | if (!_blueView) { 65 | _blueView = [[UIView alloc] initWithFrame:CGRectMake(0, 400, 300, 300)]; 66 | _blueView.backgroundColor = [UIColor blueColor]; 67 | } 68 | return _blueView; 69 | } 70 | 71 | #pragma mark - private method 72 | 73 | - (void)testExitCommand:(UIButton *)sender { 74 | 75 | // NSTimeInterval currentDate = [NSDate timeIntervalSinceReferenceDate]; 76 | // NSArray *a = [NSArray array]; 77 | // @try { 78 | // 79 | // } 80 | // @catch { 81 | // sender.backgroundColor = [UIColor redColor]; 82 | // } 83 | // 84 | // @finally { 85 | // } 86 | // exit(0); 87 | [self testAsyncDelayScheduledAction]; 88 | } 89 | 90 | - (void) alertMemberPointer { 91 | NSNumber *testNumber = @1; 92 | NSInteger testInt = 1; 93 | NSArray *testNumArr = @[@1,@2]; 94 | NSArray *testStringArr = @[@"a",@"b"]; 95 | 96 | // [self excuteTimeRecycleAction]; 97 | } 98 | 99 | - (void)testAsyncDelayScheduledAction { 100 | dispatch_queue_t queue = dispatch_queue_create("test.delayperformSelctor", NULL); 101 | 102 | dispatch_async(queue, ^{ 103 | // [self performSelector:@selector(changeBackgroundColor) withObject:nil afterDelay:2]; 104 | [self performSelector:@selector(changeBackgroundColor) withObject:nil afterDelay:2 inModes:@[NSRunLoopCommonModes]]; 105 | 106 | }); 107 | } 108 | 109 | - (void)excuteTimeRecycleAction { 110 | 111 | // NSTimer *timer1 = [NSTimer timerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) { 112 | // NSLog(@"主线程里打印timer"); 113 | // }]; 114 | //// [timer1 fire]; 115 | // [[NSRunLoop currentRunLoop] addTimer:timer1 forMode:NSDefaultRunLoopMode]; 116 | 117 | [NSTimer scheduledTimerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) { 118 | NSLog(@"主线程里打印timer"); 119 | }]; 120 | 121 | dispatch_queue_t queue = dispatch_queue_create("test.delayperformSelctor2", NULL); 122 | 123 | dispatch_async(queue, ^{ 124 | 125 | NSLog(@"nsrunloop的相关信息%@",[NSRunLoop currentRunLoop]); 126 | 127 | // NSTimer *timer2 = [NSTimer timerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) { 128 | // NSLog(@"当前线程是%@打印timer",[NSThread currentThread]); 129 | // }]; 130 | // [[NSRunLoop currentRunLoop] addTimer:timer2 forMode:NSRunLoopCommonModes]; 131 | [NSTimer scheduledTimerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) { 132 | // NSLog(@"当前线程是%@打印timer",[NSThread currentThread]); 133 | NSLog(@"NSRunloop的相关信息%@",[NSRunLoop currentRunLoop]); 134 | }]; 135 | 136 | [NSTimer scheduledTimerWithTimeInterval:2 repeats:NO block:^(NSTimer * _Nonnull timer) { 137 | NSLog(@"repeats==NO的NSRunloop的相关信息%@",[NSRunLoop currentRunLoop]); 138 | }]; 139 | 140 | NSLog(@"nsrunloop的相关信息%@",[NSRunLoop currentRunLoop]); 141 | [[NSRunLoop currentRunLoop] run]; 142 | }); 143 | } 144 | 145 | - (void)changeBackgroundColor { 146 | self.view.backgroundColor = [UIColor redColor]; 147 | } 148 | 149 | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 150 | NSSet *set1 = [event touchesForView:self.view]; 151 | NSSet *set2 = [event touchesForView:self.exitButton]; 152 | NSSet *set3 = [event touchesForView:self.addressButton]; 153 | NSSet *set4 = [event touchesForView:self.blueView]; 154 | NSSet *windowSet = [event touchesForWindow:[UIApplication sharedApplication].keyWindow]; 155 | } 156 | 157 | @end 158 | -------------------------------------------------------------------------------- /OCDeepLearning/ThirdViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ThirdViewController.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/6/26. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "BaseViewController.h" 10 | 11 | @interface ThirdViewController : BaseViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /OCDeepLearning/ThirdViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ThirdViewController.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2018/6/26. 6 | // Copyright © 2018年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "ThirdViewController.h" 10 | #import "SecondTestViewController.h" 11 | #import "CTMediator.h" 12 | 13 | static NSString* const kCustomIdentifier = @"customIdentifier"; 14 | 15 | @interface ThirdViewController () 16 | 17 | @property(nonatomic, strong) UITableView *customTableView; 18 | 19 | @end 20 | 21 | @implementation ThirdViewController 22 | 23 | - (void)viewDidLoad { 24 | [super viewDidLoad]; 25 | // Do any additional setup after loading the view. 26 | 27 | [self.view addSubview:self.customTableView]; 28 | } 29 | 30 | - (void)didReceiveMemoryWarning { 31 | [super didReceiveMemoryWarning]; 32 | // Dispose of any resources that can be recreated. 33 | } 34 | 35 | /* 36 | #pragma mark - Navigation 37 | 38 | // In a storyboard-based application, you will often want to do a little preparation before navigation 39 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 40 | // Get the new view controller using [segue destinationViewController]. 41 | // Pass the selected object to the new view controller. 42 | } 43 | */ 44 | 45 | #pragma mark - lazy 46 | - (UITableView *)customTableView { 47 | if (!_customTableView) { 48 | _customTableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain]; 49 | _customTableView.delegate = self; 50 | _customTableView.dataSource = self; 51 | 52 | [self.customTableView registerClass:[UITableViewCell class] forCellReuseIdentifier:kCustomIdentifier]; 53 | 54 | } 55 | return _customTableView; 56 | } 57 | 58 | #pragma mark - UITableViewDelegate,UITableViewDataSource 59 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 60 | return 1; 61 | } 62 | 63 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 64 | return 10; 65 | } 66 | 67 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 68 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kCustomIdentifier forIndexPath:indexPath]; 69 | if (!cell) { 70 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kCustomIdentifier]; 71 | } 72 | 73 | cell.textLabel.text = [NSString stringWithFormat:@"第%ld个cell",indexPath.row]; 74 | 75 | return cell; 76 | } 77 | 78 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 79 | if (indexPath.row == 0) { 80 | [[CTMediator sharedInstance] performTarget:@"SecondTestViewController" action:@"changeBackgroundColor" params:nil shouldCacheTarget:NO]; 81 | } 82 | } 83 | 84 | 85 | - (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context { 86 | 87 | } 88 | 89 | - (void)dealloc { 90 | 91 | } 92 | 93 | @end 94 | -------------------------------------------------------------------------------- /OCDeepLearning/UserModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // UserModel.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2017/7/13. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UserModel : NSObject 12 | 13 | @property (nonatomic, strong) NSString *location; 14 | 15 | @property (nonatomic, assign) NSNumber *public_gists; 16 | 17 | @property (nonatomic, strong) NSString *url; 18 | 19 | @property (nonatomic, strong) NSString *following_url; 20 | 21 | @property (nonatomic, strong) NSString *events_url; 22 | 23 | @property (nonatomic, strong) NSString *received_events_url; 24 | 25 | @property (nonatomic, strong) NSString *company; 26 | 27 | @property (nonatomic, strong) NSString *updated_at; 28 | 29 | @property (nonatomic, strong) NSString *avatar_url; 30 | 31 | @property (nonatomic, strong) NSString *name; 32 | 33 | @property (nonatomic, strong) NSString *type; 34 | 35 | @property (nonatomic, strong) NSString *subscriptions_url; 36 | 37 | @property (nonatomic, strong) NSString *gists_url; 38 | 39 | @property (nonatomic, assign) NSNumber *ID; 40 | 41 | @property (nonatomic, strong) NSString *starred_url; 42 | 43 | @property (nonatomic, strong) NSString *organizations_url; 44 | 45 | @property (nonatomic, strong) NSString *repos_url; 46 | 47 | @property (nonatomic, assign) BOOL site_admin; 48 | 49 | @property (nonatomic, strong) NSString *email; 50 | 51 | @property (nonatomic, strong) NSString *login; 52 | 53 | @property (nonatomic, strong) NSString *blog; 54 | 55 | @property (nonatomic, assign) NSNumber *public_repos; 56 | 57 | @property (nonatomic, assign) NSNumber *followers; 58 | 59 | @property (nonatomic, assign) NSNumber *following; 60 | 61 | @property (nonatomic, strong) NSString *created_at; 62 | 63 | @property (nonatomic, strong) NSString *gravatar_id; 64 | 65 | @property (nonatomic, strong) NSString *followers_url; 66 | 67 | @property (nonatomic, strong) NSString *html_url; 68 | 69 | @end 70 | -------------------------------------------------------------------------------- /OCDeepLearning/UserModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // UserModel.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2017/7/13. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "UserModel.h" 10 | 11 | @implementation UserModel 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /OCDeepLearning/ViewController+SwizzlingMethod.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController+SwizzlingMethod.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2017/7/12. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | 11 | @interface ViewController (SwizzlingMethod) 12 | 13 | + (void)load; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /OCDeepLearning/ViewController+SwizzlingMethod.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController+SwizzlingMethod.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2017/7/12. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import "ViewController+SwizzlingMethod.h" 10 | #import 11 | 12 | @implementation ViewController (SwizzlingMethod) 13 | 14 | 15 | + (void)load { 16 | // Method m1 = class_getInstanceMethod([ViewController class], @selector(viewDidAppear:)); 17 | // Method m2 = class_getInstanceMethod([ViewController class], @selector(gb_viewDidAppear:)); 18 | // 19 | //// IMP p1 = method_getImplementation(m1); 20 | //// IMP p2 = method_getImplementation(m2); 21 | //// NSLog(@"Imp分别是%p,/n %p",p1,p2); 22 | // ///p1和m1对应的是两个地址 23 | // 24 | // NSLog(@"method分别是%p,/n %p",m1,m2); 25 | // 26 | // method_exchangeImplementations(m1, m2); 27 | 28 | Method m3 = class_getInstanceMethod([ViewController class], @selector(viewDidLoad)); 29 | Method m4 = class_getInstanceMethod([ViewController class], @selector(gb_viewDidLoad)); 30 | 31 | // IMP p3 = method_getImplementation(m3); 32 | // IMP p4 = method_getImplementation(m4); 33 | // NSLog(@"Imp分别是%p,/n %p",p1,p2); 34 | ///p1和m1对应的是两个地址 35 | 36 | // NSLog(@"method分别是%p,/n %p",m3,m4); 37 | NSLog(@"method分别是%p,/n %p",m3,m4); 38 | 39 | method_exchangeImplementations(m3, m4); 40 | } 41 | 42 | //- (void)gb_viewDidAppear:(BOOL)animated { 43 | // [self gb_viewDidAppear:YES]; 44 | // NSLog(@"方法交换成功"); 45 | //} 46 | 47 | 48 | - (void)gb_viewDidLoad { 49 | [self gb_viewDidLoad]; 50 | NSLog(@"类的名字是%@",[self class]); 51 | } 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /OCDeepLearning/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2017/7/7. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /OCDeepLearning/appletrace.h: -------------------------------------------------------------------------------- 1 | // 2 | // appletrace.h 3 | // appletrace 4 | // 5 | // Created by everettjf on 2017/9/12. 6 | // Copyright © 2017年 everettjf. All rights reserved. 7 | // 8 | 9 | 10 | #import 11 | 12 | FOUNDATION_EXPORT void APTBeginSection(const char* name); 13 | FOUNDATION_EXPORT void APTEndSection(const char* name); 14 | 15 | 16 | // Objective C class method 17 | #define APTBegin APTBeginSection([NSString stringWithFormat:@"[%@]%@",self,NSStringFromSelector(_cmd)].UTF8String) 18 | #define APTEnd APTEndSection([NSString stringWithFormat:@"[%@]%@",self,NSStringFromSelector(_cmd)].UTF8String) 19 | -------------------------------------------------------------------------------- /OCDeepLearning/appletrace.mm: -------------------------------------------------------------------------------- 1 | // 2 | // appletrace.m 3 | // appletrace 4 | // 5 | // Created by everettjf on 2017/9/12. 6 | // Copyright © 2017年 everettjf. All rights reserved. 7 | // 8 | 9 | 10 | #import "appletrace.h" 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | namespace appletrace { 23 | class Logger{ 24 | private: 25 | // int block_size = 64 * 1024 * 1024; // 64MB 26 | int block_size = 16 * 1024 * 1024; // 16MB 27 | // int block_size = 1 * 1024 * 1024; // 1MB 28 | // int block_size = 1 * 1024; // 1KB 29 | 30 | int fd_ = 0; 31 | char * file_start_ = NULL; 32 | char * file_cur_ = NULL; 33 | size_t cur_size_ = 0; 34 | public: 35 | Logger(){} 36 | ~Logger(){} 37 | 38 | bool Open(const char * log_path){ 39 | Close(); 40 | 41 | remove(log_path); 42 | fd_ = ::open(log_path, O_CREAT|O_RDWR,(mode_t)0600); 43 | if(fd_ == -1){ 44 | NSLog(@"open file failed"); 45 | return false; 46 | } 47 | off_t cur_off = ::lseek(fd_, block_size - 1, SEEK_SET); 48 | ssize_t wrote_bytes = ::write(fd_,"",1); 49 | if(wrote_bytes != 1){ 50 | NSLog(@"wrote error"); 51 | Close(); 52 | return false; 53 | } 54 | ::lseek(fd_, 0, SEEK_SET); 55 | 56 | file_start_ = (char*)::mmap(NULL,block_size,PROT_READ|PROT_WRITE,MAP_SHARED,fd_,0); 57 | if(file_start_ == MAP_FAILED){ 58 | NSLog(@"map failed"); 59 | Close(); 60 | return false; 61 | } 62 | file_cur_ = file_start_; 63 | return true; 64 | } 65 | void Close(){ 66 | if(file_start_){ 67 | ::munmap(file_start_, block_size); 68 | } 69 | if(fd_){ 70 | ::close(fd_); 71 | } 72 | fd_ = 0; 73 | file_start_ = NULL; 74 | file_cur_ = NULL; 75 | cur_size_ = 0; 76 | } 77 | bool AddLine(const char * line){ 78 | if(!file_cur_) 79 | return false; 80 | 81 | size_t len = strlen(line); 82 | if(cur_size_ + len + 1> block_size){ 83 | NSLog(@"file full"); 84 | return false; 85 | } 86 | 87 | memcpy(file_cur_, line, len); 88 | file_cur_ += len; 89 | memcpy(file_cur_, (const char *)"\n",1); 90 | file_cur_ += 1; 91 | 92 | cur_size_ += len + 1; 93 | return true; 94 | } 95 | }; 96 | 97 | 98 | class LoggerManager{ 99 | private: 100 | static int file_counter; 101 | Logger log_; 102 | public: 103 | std::string GetFilePath(){ 104 | NSString * tmp_dir = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES)[0]; 105 | tmp_dir = [tmp_dir stringByAppendingPathComponent:@"appletracedata"]; 106 | 107 | NSString * log_name; 108 | if(file_counter == 0){ 109 | [[NSFileManager defaultManager] removeItemAtPath:tmp_dir error:nil]; 110 | [[NSFileManager defaultManager] createDirectoryAtPath:tmp_dir withIntermediateDirectories:YES attributes:nil error:nil]; 111 | 112 | log_name = @"trace.appletrace"; 113 | }else{ 114 | log_name = [NSString stringWithFormat:@"trace_%@.appletrace",@(file_counter)]; 115 | } 116 | NSString * log_path = [tmp_dir stringByAppendingPathComponent:log_name]; 117 | NSLog(@"log path = %@",log_path); 118 | return std::string(log_path.UTF8String); 119 | } 120 | bool Open(){ 121 | std::string path = GetFilePath(); 122 | if(!log_.Open(path.c_str())){ 123 | return false; 124 | } 125 | ++file_counter; 126 | return true; 127 | } 128 | void AddLine(const char *line){ 129 | if(log_.AddLine(line)) 130 | return; 131 | 132 | NSLog(@"will map a new file"); 133 | // map a new file 134 | if(!Open()) 135 | return; 136 | 137 | if(!log_.AddLine(line)){ 138 | // error 139 | NSLog(@"still error add line"); 140 | } 141 | } 142 | }; 143 | int LoggerManager::file_counter = 0; 144 | 145 | class Trace{ 146 | private: 147 | LoggerManager log_; 148 | dispatch_queue_t queue_; 149 | uint64_t begin_; 150 | mach_timebase_info_data_t timeinfo_; 151 | public: 152 | bool Open(){ 153 | static dispatch_once_t onceToken; 154 | dispatch_once(&onceToken, ^{ 155 | log_.Open(); 156 | 157 | queue_ = dispatch_queue_create("appletrace.queue", DISPATCH_QUEUE_SERIAL); 158 | mach_timebase_info(&timeinfo_); 159 | begin_ = mach_absolute_time() * timeinfo_.numer / timeinfo_.denom; 160 | 161 | }); 162 | return true; 163 | } 164 | 165 | void WriteSection(const char *name,const char *ph){ 166 | pthread_t thread = pthread_self(); 167 | __uint64_t thread_id=0; 168 | pthread_threadid_np(thread,&thread_id); 169 | uint64_t time = mach_absolute_time() * timeinfo_.numer / timeinfo_.denom; 170 | uint64_t elapsed = time - begin_; 171 | 172 | NSString *str = [NSString stringWithFormat:@"{\"name\":\"%s\",\"cat\":\"catname\",\"ph\":\"%s\",\"pid\":666,\"tid\":%llu,\"ts\":%llu}", 173 | name,ph,thread_id,elapsed 174 | ]; 175 | dispatch_async(queue_, ^{ 176 | log_.AddLine(str.UTF8String); 177 | }); 178 | } 179 | }; 180 | 181 | class TraceManager{ 182 | private: 183 | Trace t_; 184 | public: 185 | static TraceManager & Instance(){ 186 | static TraceManager o; 187 | return o; 188 | } 189 | 190 | TraceManager(){ 191 | if(!t_.Open()){ 192 | NSLog(@"error open trace file"); 193 | } 194 | } 195 | 196 | void BeginSection(const char* name){ 197 | t_.WriteSection(name, "B"); 198 | } 199 | 200 | void EndSection(const char* name){ 201 | t_.WriteSection(name, "E"); 202 | } 203 | }; 204 | } 205 | 206 | void APTBeginSection(const char* name){ 207 | appletrace::TraceManager::Instance().BeginSection(name); 208 | } 209 | 210 | void APTEndSection(const char* name){ 211 | appletrace::TraceManager::Instance().EndSection(name); 212 | } 213 | 214 | -------------------------------------------------------------------------------- /OCDeepLearning/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // OCDeepLearning 4 | // 5 | // Created by walker彬 on 2017/7/7. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /OCDeepLearningTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /OCDeepLearningTests/OCDeepLearningTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // OCDeepLearningTests.m 3 | // OCDeepLearningTests 4 | // 5 | // Created by walker彬 on 2017/7/7. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface OCDeepLearningTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation OCDeepLearningTests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | // Put setup code here. This method is called before the invocation of each test method in the class. 20 | } 21 | 22 | - (void)tearDown { 23 | // Put teardown code here. This method is called after the invocation of each test method in the class. 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample { 28 | // This is an example of a functional test case. 29 | // Use XCTAssert and related functions to verify your tests produce the correct results. 30 | } 31 | 32 | - (void)testPerformanceExample { 33 | // This is an example of a performance test case. 34 | [self measureBlock:^{ 35 | // Put the code you want to measure the time of here. 36 | }]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /OCDeepLearningUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /OCDeepLearningUITests/OCDeepLearningUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // OCDeepLearningUITests.m 3 | // OCDeepLearningUITests 4 | // 5 | // Created by walker彬 on 2017/7/7. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface OCDeepLearningUITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation OCDeepLearningUITests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | 22 | // In UI tests it is usually best to stop immediately when a failure occurs. 23 | self.continueAfterFailure = NO; 24 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 25 | [[[XCUIApplication alloc] init] launch]; 26 | 27 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 28 | } 29 | 30 | - (void)tearDown { 31 | // Put teardown code here. This method is called after the invocation of each test method in the class. 32 | [super tearDown]; 33 | } 34 | 35 | - (void)testExample { 36 | // Use recording to get started writing UI tests. 37 | // Use XCTAssert and related functions to verify your tests produce the correct results. 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /OCLearningNote.md: -------------------------------------------------------------------------------- 1 | # OC学习Note 2 | > 记录学习的一些trick,开发的tips及其偏片段的一些知识点。 3 | 4 | * Mac OS 上打开通用的Router 5 | ``` 6 | x-help-action://openPrefPane?bundleId=com.apple.preference.security&anchorId=General 7 | ``` 8 | 所以MacOS的路由,本身也是通过URL来处理的。 9 | 10 | * Fix: 11 | 调用**objc_msgSend()**时,方法报错: 12 | ```objc_msgSend(): Too many arguments to function call ,expected 0,have2;``` 13 | 报错原因:Xcode对objc_msgSend()有严格的类型检查 14 | 修改办法: 15 | 在build settings中,将 16 | `Build Setting--> Apple LLVM - Preprocessing--> Enable Strict Checking of objc_msgSend Calls 改为 NO` 17 | > **NOTE:**在Xcode10中,为 18 | `Build Setting--> Apple Clang - Preprocessing--> Enable Strict Checking of objc_msgSend Calls 改为 NO` 19 | 20 | * Xcode10中,将build settings 中的Apple LLVM改为Apple Clang; 21 | 22 | 23 | -------------------------------------------------------------------------------- /PrefixHeader.pch: -------------------------------------------------------------------------------- 1 | // 2 | // PrefixHeader.pch 3 | // OCDeepLearning 4 | // 5 | // Created by walker on 2017/10/16. 6 | // Copyright © 2017年 walker彬. All rights reserved. 7 | // 8 | 9 | #ifndef PrefixHeader_pch 10 | #define PrefixHeader_pch 11 | 12 | // Include any system framework and library headers here that should be included in all compilation units. 13 | // You will also need to set the Prefix Header build setting of one or more of your targets to reference this file. 14 | 15 | // Objective C class method 16 | #define APTBegin APTBeginSection([NSString stringWithFormat:@"[%@]%@",self,NSStringFromSelector(_cmd)].UTF8String) 17 | #define APTEnd APTEndSection([NSString stringWithFormat:@"[%@]%@",self,NSStringFromSelector(_cmd)].UTF8String) 18 | 19 | #endif /* PrefixHeader_pch */ 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OCDeepLearning 2 | ## OC的高级用法和学习 3 | 4 | ### 文章主要包含以下部分: 5 | 6 | * OC的黑魔法 7 | * 底层的方法 8 | * IMP,SEL,Method的本质 9 | * 添加IMP实现方法调用(OC_IMP.h类) 10 | * 内存管理 11 | * 自动释放池 12 | * ARC和MRC 13 | * 多线程 14 | * GCD的基础用法 15 | * Queue 16 | * dispatch_create 17 | * 系统队列 18 | * Main Dispatch Queue/Global Dispatch Queue 19 | * GCD的高级用法 20 | * `Dispatch Group` 21 | * notify 22 | * wait 23 | * `dispatch_barrier_aync` 24 | * `dispatch_set-target-queue` 25 | * `dispatch_after` 26 | * `dispatch_apply` 27 | * `dispatch_suspend/resume` 28 | * `dispatch_once` 29 | 30 | 31 | ### ARC 32 | * 内部循环使用自动释放池 33 | 34 | ### NSRunloop 35 | * 子线程的NSTimer和NSRunLoop 36 | 37 | ``` 38 | 子线程有RunLoop,但默认不开启, 39 | 而NSTimer事件依赖NSRunLoop, 40 | 只有手动开启子线程的NSRunLoop, 41 | 并将NSTimer添加进去才可以运行。 42 | ``` 43 | ### [category的高级使用](https://github.com/walkertop/OCDeepLearning/blob/master/category的高级使用.md) 44 | 45 | ### Runtime 46 | * [消息转发代码实现](https://github.com/walkertop/OCDeepLearning/blob/master/消息转发流程.md) 47 | * `load` 和 `initialize`方法初探 48 | * `swizzling method`系列 49 | * `SEL`,`IMP`,`Method`的区别 50 | [SEL&IMP&Method区别](https://github.com/walkertop/OCDeepLearning/blob/master/SEL-IMP-Method解析.md) 51 | 52 | ## 文末 53 | 主要是针对各种魔法提供代码的用例以及高级技巧的使用介绍。 54 | 基于底层的实现原理,会选择性提供优质的博客以论证。 55 | 56 | 57 | -------------------------------------------------------------------------------- /SEL-IMP-Method解析.md: -------------------------------------------------------------------------------- 1 | ### SEL,Method,IMP 2 | #### SEL 3 | * SEL方法选择器,表示一个selector的指针 4 | * 无论什么类里,只要方法名相同,SEL就相同。项目里的所有SEL都保存在一个NSSet集合里(NSSet集合里的元素不能重复),所以查找对应方法,只要找到对应的SEL就可以了。 5 | * SEL实际是根据方法名hash化了的字符串 6 | 7 | 8 | ``` 9 | SEL sel_registerName(const char *str)//向runtime system注册一个方法名。如果方法名已经注册,则放回已经注册的SEL 10 | SEL sel_getUid(const char *str)//同上 11 | @selector(<#selector#>)//oc编译器提供的 12 | SEL NSSelectorFromString(NSString *aSelectorName)//OC字符串转化 13 | SEL method_getName ( Method m );//根据Method结构体获取 14 | 等等 15 | ``` 16 | 17 | SEL的操作函数 18 | 19 | ``` 20 | // 比较两个选择器 21 | BOOL sel_isEqual ( SEL lhs, SEL rhs ); 22 | //判断方法名是否映射到某个函数实现上 23 | BOOL sel_isMapped(SEL sel); 24 | ``` 25 | 26 | 27 | ##### 出现个BUG: 28 | 既然SEL是方法的唯一标识,那不同的类调用名字相同的方法怎么办呢? 29 | 30 | 那就让下一个重要任务出场吧。 31 | #### IMP 32 | 定义:函数指针,指向方法实现的首地址。 33 | 代码定义如下: 34 | 35 | ``` 36 | typedef id (*IMP)(id, SEL, ...); 37 | ``` 38 | 其参数包含id,SEL,后面试实际的参数列表。 39 | 那么,XX调用了XXX方法,其参数为XX都确定下来了。 40 | 41 | ##### IMP的高级作用 42 | 既然上述元素都确定下来了,那么就可以直接绕过Runtime的消息传递机制,直接执行IMP指向的函数了。省去了一些列的查找,直接向对象发送消息,效率会高一些。 43 | 44 | ``` 45 | IMP imp_implementationWithBlock(id block)//根据代码块获取IMP,其实就是代码块与IMP关联 46 | IMP method_getImplementation(Method m) //根据Method获取IMP 47 | [[objc Class] instanceMethodForSelector:SEL]//根据OC方式获取IMP 48 | ``` 49 | 50 | 51 | 当我们获取一个方法的IMP时候可以直接调用IMP 52 | 53 | ``` 54 | IMP imp = method_getImplementation(Method m); 55 | id objc = imp(id,SEL,argument);//objc用来保存方法的返回值,id表示调用这个方法的对象,SEL是Method的选择器,argument是方法的参数。 56 | ``` 57 | 58 | 59 | #### Method 60 | 61 | Method定义如下:它主要是用语描述类里面的方法 62 | 63 | ``` 64 | typedef struct objc_method *Method; 65 | ``` 66 | objc_method结构体定义如下 67 | 68 | ``` 69 | struct objc_method { 70 | SEL method_name OBJC2_UNAVAILABLE;//方法名 71 | char *method_types OBJC2_UNAVAILABLE;//参数返回值字符串描述 72 | IMP method_imp OBJC2_UNAVAILABLE;//方法的实现 73 | } 74 | ``` 75 | 76 | 从上述代码可以看出,Method是一个结构体,包含了SEL和IMP成员变量。 77 | 实际上,相当于在SEL和IMP之间做了一个映射,有了Method,SEL就可以找到对应的IMP,从而调用方法。 78 | 79 | 80 | ##### Method操作函数如下: 81 | 82 | ``` 83 | 方法操作主要有以下函数: 84 | // 添加方法 85 | BOOL class_addMethod ( Class cls, SEL name, IMP imp, const char *types ); 86 | 87 | // 获取实例方法 88 | Method class_getInstanceMethod ( Class cls, SEL name ); 89 | 90 | // 获取类方法 91 | Method class_getClassMethod ( Class cls, SEL name ); 92 | 93 | // 获取所有方法的数组 94 | Method * class_copyMethodList ( Class cls, unsigned int *outCount ); 95 | 96 | // 替代方法的实现 97 | IMP class_replaceMethod ( Class cls, SEL name, IMP imp, const char *types ); 98 | 99 | // 返回方法的具体实现 100 | IMP class_getMethodImplementation ( Class cls, SEL name ); 101 | IMP class_getMethodImplementation_stret ( Class cls, SEL name ); 102 | 103 | // 类实例是否响应指定的selector 104 | BOOL class_respondsToSelector ( Class cls, SEL sel ); 105 | ``` 106 | 107 | 此处具体实现比较简单,可以通过手动操作IMP来完成方法的调用。 108 | 109 | 实例代码: 110 | 111 | 112 | ``` 113 | #import "OC_IMP.h" 114 | 115 | 116 | typedef void (^CustomBlock)(NSString *name); 117 | 118 | @interface OC_IMP () 119 | 120 | @property(nonatomic, weak) CustomBlock block; 121 | 122 | @end 123 | 124 | @implementation OC_IMP 125 | 126 | - (void)testIMP { 127 | [self addMethodByIMP]; 128 | } 129 | 130 | //定义一个block 131 | //手动添加方法 132 | - (void)addMethodByIMP { 133 | CustomBlock block = ^(NSString *name){ 134 | NSLog(@"执行block"); 135 | }; 136 | 137 | IMP impBlock = imp_implementationWithBlock(block); 138 | Method m = class_getInstanceMethod(self.class, @selector(testIMP)); 139 | method_setImplementation(m, impBlock); 140 | const char * types = method_getTypeEncoding(m); //因为方法类型相同(都是无参数无返回值类型,所以方法类型相同,如果知道的话,可以直接制定type为v16@0:8) 141 | sel_registerName("newSel"); //注册newSel 142 | BOOL isAdded = class_addMethod([self class], @selector(newSel), impBlock, types); 143 | if (isAdded == YES) { 144 | NSLog(@"添加成功"); 145 | [self performSelector:@selector(newSel)]; 146 | } 147 | } 148 | 149 | @end 150 | ``` 151 | 152 | 153 | ``` 154 | OC_IMP *oc_imp = [[OC_IMP alloc] init]; 155 | [oc_imp testIMP]; 156 | ``` 157 | 158 | 调用执行结果 159 | 160 | ``` 161 | 2017-07-14 20:14:26.359 OCDeepLearning[5654:530015] 添加成功 162 | 2017-07-14 20:14:26.359 OCDeepLearning[5654:530015] 执行block 163 | ``` 164 | 165 | 166 | 补充: 167 | 1. 在swift里可以使用#selector(XXX)来获取对应的SEL,但这并非指swift的方法调用是通过selector来实现的,能调用仅仅是因为swift和OC的混编; 168 | 2. 每个方法名有对应的唯一seletor,其SEL相同,但对应的IMP函数指针不同。 169 | 170 | -------------------------------------------------------------------------------- /appletrace.framework/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .idea/ 3 | .vscode/ 4 | cmake-build-debug/ 5 | CMakeLists.txt 6 | 7 | # Prerequisites 8 | *.d 9 | 10 | # Object files 11 | *.o 12 | *.ko 13 | *.obj 14 | *.elf 15 | 16 | # Linker output 17 | *.ilk 18 | *.map 19 | *.exp 20 | 21 | # Precompiled Headers 22 | *.gch 23 | *.pch 24 | 25 | # Libraries 26 | *.lib 27 | *.a 28 | *.la 29 | *.lo 30 | 31 | # Shared objects (inc. Windows DLLs) 32 | *.dll 33 | *.so 34 | *.so.* 35 | *.dylib 36 | 37 | # Executables 38 | *.exe 39 | *.out 40 | *.app 41 | *.i*86 42 | *.x86_64 43 | *.hex 44 | 45 | # Debug files 46 | *.dSYM/ 47 | *.su 48 | *.idb 49 | *.pdb 50 | 51 | # Kernel Module Compile Results 52 | *.mod* 53 | *.cmd 54 | .tmp_versions/ 55 | modules.order 56 | Module.symvers 57 | Mkfile.old 58 | dkms.conf 59 | -------------------------------------------------------------------------------- /appletrace.framework/Info.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walkertop/OCDeepLearning/1f0b34032d8500a11789c1b8ee9e93e4039e3943/appletrace.framework/Info.plist -------------------------------------------------------------------------------- /appletrace.framework/appletrace: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walkertop/OCDeepLearning/1f0b34032d8500a11789c1b8ee9e93e4039e3943/appletrace.framework/appletrace -------------------------------------------------------------------------------- /category的高级使用.md: -------------------------------------------------------------------------------- 1 | # category的高级使用 2 | 3 | 4 | [TOC] 5 | > Category是在`Objective-C 2.0`时提供的新的语言特性,其原因简单,不管类设计的多么完美,总有无法预测的状况,Category就是作为一种方式来扩展类的。 6 | 7 | 关于基础部分,网上很多相关文档可供查阅,此文不赘述。 8 | 作者只做分类的底层及高级用法作使用说明。 9 | 10 | ### 1. 分类为什么会覆盖掉类的同名方法,对应的类方法是不存在了么? 11 | 12 | ``` 13 | 1. category的方法没有“完全替换掉”原来类已经有的方法,也就是说如果category和原来类都有methodA,那么category附加完成之后,类的方法列表里会有两个methodA 14 | 2. category的方法被放到了新方法列表的前面,而原来类的方法被放到了新方法列表的后面,这也就是我们平常所说的category的方法会“覆盖”掉原来类的同名方法,这是因为运行时在查找方法的时候是顺着方法列表的顺序查找的,它只要一找到对应名字的方法,就会罢休^_^,殊不知后面可能还有一样名字的方法。 15 | ``` 16 | ### 2. 怎么解除分类对类方法的覆盖? 17 | 18 | ``` 19 | /* 20 | 怎么调用到原来类中被category覆盖掉的方法? 21 | 对于这个问题,我们已经知道category其实并不是完全替换掉原来类的同名方法,只是category在方法列表的前面而已,所以我们只要顺着方法列表找到最后一个对应名字的方法,就可以调用原来类的方法: 22 | */ 23 | + (void)useClassMethodInsteadCayegoryMethod: (SEL)seletor { 24 | 25 | if (self) { 26 | unsigned int methodCount; 27 | Method *methodList = class_copyMethodList([self class], &methodCount); 28 | IMP lastImp = NULL; 29 | SEL lastSel = NULL; 30 | for (NSInteger i = 0; i < methodCount; i++) { 31 | Method method = methodList[i]; 32 | NSString *methodName = [NSString stringWithCString:sel_getName(method_getName(method)) 33 | encoding:NSUTF8StringEncoding]; 34 | NSString *selectorName = NSStringFromSelector(seletor); 35 | if ([selectorName isEqualToString:methodName]) { 36 | lastImp = method_getImplementation(method); 37 | lastSel = method_getName(method); 38 | } 39 | } 40 | typedef void (*fn)(id,SEL); 41 | 42 | if (lastImp != NULL) { 43 | fn f = (fn)lastImp; 44 | f(self,lastSel); 45 | } 46 | free(methodList); 47 | } 48 | } 49 | ``` 50 | 51 | ### 3.category怎么关联对象的? 52 | ``` 53 | #import 54 | #import "LearnCategoryClass.h" 55 | 56 | @interface LearnCategoryClass (Addition) 57 | 58 | @property(nonatomic, strong) NSString *newName; 59 | 60 | ``` 61 | ------- 62 | 63 | ``` 64 | 65 | #import "LearnCategoryClass+Addition.h" 66 | #import 67 | 68 | @implementation LearnCategoryClass (Addition) 69 | 70 | - (void)testCategory { 71 | NSLog(@"分类里是%@,方法名是%s",[self class], __PRETTY_FUNCTION__); 72 | } 73 | 74 | //运行时动态添加set和get方法(Xcode9 更新了提醒功能,超级牛逼。比如此处在分类里声明了属性,但不添加set/get方法会warnning,这里说下,厉害了我的苹果) 75 | - (void)setNewName:(NSString *)newName 76 | { 77 | objc_setAssociatedObject(self, 78 | "newName", 79 | newName, 80 | OBJC_ASSOCIATION_COPY); 81 | } 82 | 83 | - (NSString*)newName 84 | { 85 | NSString *nameObject = objc_getAssociatedObject(self, "newName"); 86 | return nameObject; 87 | } 88 | @end 89 | ``` 90 | 91 | 92 | ### 4.多个category,哪个方法优先执行? 93 | 好吧,这其实不是一个问题,是一串问题。 94 | 可以分为: 95 | > 1. category里的方法是什么时候注册到Class的`method_list`的,在`+load`阶段么? 96 | 2. 如果有多个category,怎么办? 97 | 98 | 我们知道,在类class和category中都可以有`+load`方法,那么有两个问题: 99 | > 1. 在class的`+load`方法调用的时候,我们可以调用category中声明的方法么? 100 | 2. 这么多个`+load`方法,调用顺序是咋样的呢? 101 | 102 | -------- 103 | 104 | >答案是 105 | 1. 可以调用,而且附加category到类的工作会先于`+load`方法的执行; 106 | 2. `+load`的执行顺序是先class,后category,而category的`+load`执行顺序是根据编译顺序决定的。 107 | 108 | 可以这么理解方法的调用。 109 | 有一个类似有压栈入栈的栈结构,先把class里的methodA添加到methodList中,然后添加分类中的方法,编译器会从上到下找分类,先找到的分类就先放入methodList中,后找到的就后放入。 110 | 所以最终形成了一个Class里的方法在最底层,最后编译的分类在最上层的栈结构。 111 | 而方法的调用是从上到下执行的,冉调用对应的方法,就会从methodList里找对应的SEL,找到就停止,所以Class和前面便轻易的分类虽然都在methodList里,但因为找到了就不会继续查找。 112 | 以上就是方法掉用顺序的原理。 113 | 当然,编译顺序可以在 `Build Phases`里的`Compile Source`里修改。 114 | 115 | ## 奇葩问答: 116 | 117 | * 如果在分类里声明了,但不实现,`method_list`里不会有,当然也不会调用分类方法。但若是实现了,即使不在.h文件声明,也会调用分类的方法; 118 | * 如果分类里是`- (void)testCategory`,而Class里是`- (int)testCategory`;返回值不同,也会覆盖,因为虽然返回值不同,但OC里,这两者依然是一个方法。 119 | * 对于多个分类,方法的调用是执行最后编译的分类方法; 120 | 121 | 122 | ------- 123 | ## 文末 124 | 关于category及其OC的深入研究,请转移到[Github—>OCDeepLearning](https://github.com/walkertop/OCDeepLearning) 125 | 欢迎star和issues参与讨论。 126 | 127 | 128 | 129 | 之于category的更底层实现,可以参照:[参考文章](https://tech.meituan.com/DiveIntoCategory.html) 130 | 131 | 132 | 133 | 134 | -------------------------------------------------------------------------------- /消息转发流程.md: -------------------------------------------------------------------------------- 1 | ## OC的消息转发流程 2 | 3 | 至于OC中Runtime详细的消息转发流程,网上文章很多,次文主要通过代码来讲述整个消息转发的流程,文字描述精干,不求细。具体原理可以查阅资料,作者建议《Effective Ovjective-C 2.0》的12章,祝你看了有奇效。 4 | 5 | 先配个图 6 | ![消息调用](http://oiu13lwmh.bkt.clouddn.com/%E6%B6%88%E6%81%AF%E5%8F%91%E9%80%81.png) 7 | 8 | ![消息转发](http://oiu13lwmh.bkt.clouddn.com/%E6%B6%88%E6%81%AF%E8%BD%AC%E5%8F%91.png) 9 | 主要分为: 10 | -------- 11 | 12 | ### 代码解释方法就是消息转发 13 | ### 方法的交换 14 | ### 动态加载方法 15 | 16 | Animal类: 17 | 18 | ``` 19 | /** 20 | 手动添加swim方法,在resolveInstanceMethod里,添加swim 21 | */ 22 | void swim(id self,SEL _cmd) { 23 | NSLog(@"消息转发时增加了swim方法"); 24 | } 25 | + (BOOL)resolveInstanceMethod:(SEL)sel { 26 | if (sel == NSSelectorFromString(@"swim")) { 27 | class_addMethod(self, @selector(swim), swim, "v@:@"); 28 | return YES; 29 | } 30 | return [super resolveInstanceMethod:sel]; 31 | } 32 | 33 | ``` 34 | ### 消息转发 35 | 36 | `Person`和`Bird`类 37 | ##### 实现需求: 38 | * Person调用了fly方法时,转发给了Bird的实例变量,交给bird实现 39 | * 调用了die实例方法时,动态转发到live实例方法 40 | * 调用ClassDie方法时,转发给ClassLive方法 41 | 42 | ``` 43 | // MARK: 实例方法的消息转发 44 | /** 45 | 消息转发 46 | */ 47 | //// MARK: 实例方法的转发流程 48 | //// STEP 1: 49 | //// 在没有找到方法时,会先调用此方法,可用于动态添加方法 50 | //// 返回 YES 表示相应 selector 的实现已经被找到并添加到了类中,否则返回 NO 51 | + (BOOL)resolveInstanceMethod:(SEL)sel { 52 | return YES; 53 | } 54 | 55 | //如果调用fly方法,则将方法对象变化为bird,执行[bird fly] 56 | - (id)forwardingTargetForSelector:(SEL)aSelector { 57 | Bird *bird =[[Bird alloc] init]; 58 | if (aSelector == @selector(fly)) { 59 | return bird; 60 | } 61 | return nil; 62 | } 63 | 64 | - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector { 65 | return [NSMethodSignature signatureWithObjCTypes:"v@:"]; 66 | } 67 | 68 | - (void)forwardInvocation:(NSInvocation *)anInvocation { 69 | // 我们还可以改变方法选择器 70 | [anInvocation setSelector:@selector(live)]; 71 | // 改变方法选择器后,还需要指定是哪个对象的方法 72 | [anInvocation invokeWithTarget:self]; 73 | } 74 | 75 | - (void)live { 76 | NSLog(@"Person 没有实现 -die 方法,并且成功的转成了 -live 方法"); 77 | } 78 | 79 | - (void)doesNotRecognizeSelector:(SEL)aSelector { 80 | NSLog(@"无法处理消息:%@", NSStringFromSelector(aSelector)); 81 | } 82 | 83 | // MARK: 类方法的消息转发 84 | + (BOOL)resolveClassMethod:(SEL)sel { 85 | return NO; 86 | } 87 | 88 | + (id)forwardingTargetForSelector:(SEL)aSelector { 89 | return nil; 90 | } 91 | 92 | + (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector { 93 | return [NSMethodSignature signatureWithObjCTypes:"v@:"]; 94 | } 95 | 96 | + (void)forwardInvocation:(NSInvocation *)anInvocation { 97 | [anInvocation setSelector:@selector(classLive)]; 98 | [anInvocation invokeWithTarget:self]; 99 | } 100 | 101 | + (void)classLive { 102 | NSLog(@"Person 没有实现 +classDie 方法,并且成功的转成了 +classLive 方法"); 103 | } 104 | 105 | + (void)doesNotRecognizeSelector:(SEL)aSelector { 106 | NSLog(@"无法处理消息:%@", NSStringFromSelector(aSelector)); 107 | } 108 | ``` 109 | ### 动态属性关联(TODO) 110 | 111 | ``` 112 | - (void)setName:(NSString *)name { 113 | // 把属性关联给对象 114 | objc_setAssociatedObject(self, "name", name, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 115 | } 116 | 117 | - (NSString *)name { 118 | // 取出属性 119 | return objc_getAssociatedObject(self, "name"); 120 | } 121 | ``` 122 | 123 | ### 字典转模型 124 | [参考链接](http://www.jianshu.com/p/c96c48adb07b) 125 | ``` 126 | + (instancetype)modelWithDict:(NSDictionary *)dict updateDict:(NSDictionary *)updateDict { 127 | id model = [[self alloc] init]; 128 | // 遍历模型中属性 129 | unsigned int count = 0; 130 | Ivar *ivars = class_copyIvarList(self, &count); 131 | for (int i = 0 ; i < count; i++) { 132 | Ivar ivar = ivars[i]; 133 | // 属性名称 134 | NSString *ivarName = [NSString stringWithUTF8String:ivar_getName(ivar)]; 135 | ivarName = [ivarName substringFromIndex:1]; 136 | id value = dict[ivarName]; 137 | // 模型中属性名对应字典中的key 138 | if (value == nil) { 139 | if (updateDict) { 140 | NSString *keyName = updateDict[ivarName]; 141 | value = dict[keyName]; 142 | } 143 | } 144 | [model setValue:value forKeyPath:ivarName]; 145 | } 146 | return model; 147 | } 148 | 149 | + (instancetype)modelWithDict:(NSDictionary *)dict { 150 | return [self modelWithDict:dict updateDict:nil]; 151 | } 152 | ``` 153 | 154 | 155 | ## 归档接档(TODO:) 156 | 157 | 158 | --------------------------------------------------------------------------------