diff --git a/RuntimeDemo.xcodeproj/project.pbxproj b/RuntimeDemo.xcodeproj/project.pbxproj index d5693c3..b64fed7 100644 --- a/RuntimeDemo.xcodeproj/project.pbxproj +++ b/RuntimeDemo.xcodeproj/project.pbxproj @@ -34,6 +34,9 @@ 69657DE41C44DB520095C032 /* NSObject+Swizzling.m in Sources */ = {isa = PBXBuildFile; fileRef = 69657DE31C44DB520095C032 /* NSObject+Swizzling.m */; }; 69657DE51C44DB520095C032 /* NSObject+Swizzling.m in Sources */ = {isa = PBXBuildFile; fileRef = 69657DE31C44DB520095C032 /* NSObject+Swizzling.m */; }; 69657DE61C44DB520095C032 /* NSObject+Swizzling.m in Sources */ = {isa = PBXBuildFile; fileRef = 69657DE31C44DB520095C032 /* NSObject+Swizzling.m */; }; + 69657E2D1C46402D0095C032 /* UIViewController+Swizzling.m in Sources */ = {isa = PBXBuildFile; fileRef = 69657E2C1C46402D0095C032 /* UIViewController+Swizzling.m */; }; + 69657E2E1C46402D0095C032 /* UIViewController+Swizzling.m in Sources */ = {isa = PBXBuildFile; fileRef = 69657E2C1C46402D0095C032 /* UIViewController+Swizzling.m */; }; + 69657E2F1C46402D0095C032 /* UIViewController+Swizzling.m in Sources */ = {isa = PBXBuildFile; fileRef = 69657E2C1C46402D0095C032 /* UIViewController+Swizzling.m */; }; 697364B11C3A461F003E1FE9 /* HYBMethodExchange.m in Sources */ = {isa = PBXBuildFile; fileRef = 697364B01C3A461F003E1FE9 /* HYBMethodExchange.m */; }; 697364B21C3A461F003E1FE9 /* HYBMethodExchange.m in Sources */ = {isa = PBXBuildFile; fileRef = 697364B01C3A461F003E1FE9 /* HYBMethodExchange.m */; }; 697364B31C3A461F003E1FE9 /* HYBMethodExchange.m in Sources */ = {isa = PBXBuildFile; fileRef = 697364B01C3A461F003E1FE9 /* HYBMethodExchange.m */; }; @@ -106,6 +109,8 @@ 69657DDE1C44D8620095C032 /* NSArray+Swizzling.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSArray+Swizzling.m"; sourceTree = ""; }; 69657DE21C44DB520095C032 /* NSObject+Swizzling.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+Swizzling.h"; sourceTree = ""; }; 69657DE31C44DB520095C032 /* NSObject+Swizzling.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+Swizzling.m"; sourceTree = ""; }; + 69657E2B1C46402D0095C032 /* UIViewController+Swizzling.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIViewController+Swizzling.h"; sourceTree = ""; }; + 69657E2C1C46402D0095C032 /* UIViewController+Swizzling.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIViewController+Swizzling.m"; sourceTree = ""; }; 697364AF1C3A461F003E1FE9 /* HYBMethodExchange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HYBMethodExchange.h; sourceTree = ""; }; 697364B01C3A461F003E1FE9 /* HYBMethodExchange.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HYBMethodExchange.m; sourceTree = ""; }; 6980598B1C30D6070021085B /* HYBTestModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HYBTestModel.h; sourceTree = ""; }; @@ -259,6 +264,8 @@ 69657DDE1C44D8620095C032 /* NSArray+Swizzling.m */, 69657DE21C44DB520095C032 /* NSObject+Swizzling.h */, 69657DE31C44DB520095C032 /* NSObject+Swizzling.m */, + 69657E2B1C46402D0095C032 /* UIViewController+Swizzling.h */, + 69657E2C1C46402D0095C032 /* UIViewController+Swizzling.m */, ); name = MethodExchange; sourceTree = ""; @@ -508,6 +515,7 @@ 69654F931C30214500FFB5AC /* UIControl+HYBBlock.m in Sources */, 69E0205C1C3771AF0034BF32 /* HYBMsgSend.m in Sources */, 691D6FC51C421E68003D41FB /* HYBPropertyLearn.m in Sources */, + 69657E2D1C46402D0095C032 /* UIViewController+Swizzling.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -525,6 +533,7 @@ 691D6FC61C421E68003D41FB /* HYBPropertyLearn.m in Sources */, 698828361C34D476002363D5 /* HYBPig.m in Sources */, 697364B21C3A461F003E1FE9 /* HYBMethodExchange.m in Sources */, + 69657E2E1C46402D0095C032 /* UIViewController+Swizzling.m in Sources */, 698828311C34CBAB002363D5 /* HYBDog.m in Sources */, 6980598E1C30D6070021085B /* HYBTestModel.m in Sources */, 69657DE01C44D8620095C032 /* NSArray+Swizzling.m in Sources */, @@ -546,6 +555,7 @@ 691D6FC71C421E68003D41FB /* HYBPropertyLearn.m in Sources */, 698828371C34D476002363D5 /* HYBPig.m in Sources */, 697364B31C3A461F003E1FE9 /* HYBMethodExchange.m in Sources */, + 69657E2F1C46402D0095C032 /* UIViewController+Swizzling.m in Sources */, 698828321C34CBAB002363D5 /* HYBDog.m in Sources */, 6980598F1C30D6070021085B /* HYBTestModel.m in Sources */, 69657DE11C44D8620095C032 /* NSArray+Swizzling.m in Sources */, diff --git a/RuntimeDemo.xcworkspace/xcuserdata/huangyibiao.xcuserdatad/UserInterfaceState.xcuserstate b/RuntimeDemo.xcworkspace/xcuserdata/huangyibiao.xcuserdatad/UserInterfaceState.xcuserstate index d4e7cb3..f482349 100644 Binary files a/RuntimeDemo.xcworkspace/xcuserdata/huangyibiao.xcuserdatad/UserInterfaceState.xcuserstate and b/RuntimeDemo.xcworkspace/xcuserdata/huangyibiao.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/RuntimeDemo/HDFArchiveModel.m b/RuntimeDemo/HDFArchiveModel.m index 92694dc..00463f9 100644 --- a/RuntimeDemo/HDFArchiveModel.m +++ b/RuntimeDemo/HDFArchiveModel.m @@ -81,6 +81,7 @@ - (instancetype)initWithCoder:(NSCoder *)aDecoder { NSString *firstLetter = [NSString stringWithFormat:@"%c", [setterName characterAtIndex:0]]; setterName = [setterName substringFromIndex:1]; setterName = [NSString stringWithFormat:@"%@%@", firstLetter.uppercaseString, setterName]; + // [setterName stringByReplacingCharactersInRange:NSMakeRange(0, 0) withString:firstLetter.uppercaseString]; } diff --git a/RuntimeDemo/HYBMethodExchange.m b/RuntimeDemo/HYBMethodExchange.m index 42a34bd..6c26070 100644 --- a/RuntimeDemo/HYBMethodExchange.m +++ b/RuntimeDemo/HYBMethodExchange.m @@ -39,6 +39,9 @@ + (void)test { NSString *nilStr = nil; NSArray *array1 = @[@"ara", @"sdf", @"dsfdsf", nilStr]; NSLog(@"array1.count = %lu", array1.count); + + // 测试数组中有数组 + NSArray *array2 = @[@[@"12323", @"nsdf", nilStr], @[@"sdf", @"nilsdf", nilStr, @"sdhfodf"]]; } // C语言版 diff --git a/RuntimeDemo/HYBMsgSend.m b/RuntimeDemo/HYBMsgSend.m index 0c17084..4144733 100644 --- a/RuntimeDemo/HYBMsgSend.m +++ b/RuntimeDemo/HYBMsgSend.m @@ -44,17 +44,20 @@ - (float)returnFloatType { - (CGRect)returnTypeIsStruct { NSLog(@"%s was called", __FUNCTION__); - + return CGRectMake(0, 0, 10, 10); } + (void)test { // 1.创建对象 HYBMsgSend *msg = ((HYBMsgSend * (*)(id, SEL))objc_msgSend)((id)[HYBMsgSend class], @selector(alloc)); + // 2.初始化对象 msg = ((HYBMsgSend * (*)(id, SEL))objc_msgSend)((id)msg, @selector(init)); + // 3.调用无参数无返回值方法 ((void (*)(id, SEL))objc_msgSend)((id)msg, @selector(noArgumentsAndNoReturnValue)); + // 4.调用带一个参数但无返回值的方法 ((void (*)(id, SEL, NSString *))objc_msgSend)((id)msg, @selector(hasArguments:), @"带一个参数,但无返回值"); // 5.调用带返回值,但是不带参数 @@ -62,7 +65,7 @@ + (void)test { NSLog(@"5. 返回值为:%@", retValue); // 6.带参数带返回值 int returnValue = ((int (*)(id, SEL, NSString *, int)) - objc_msgSend)((id)msg, + objc_msgSend)(msg, @selector(hasArguments:andReturnValue:), @"参数1", 2016); diff --git a/RuntimeDemo/HYBPropertyLearn.m b/RuntimeDemo/HYBPropertyLearn.m index a5c0fab..a911822 100644 --- a/RuntimeDemo/HYBPropertyLearn.m +++ b/RuntimeDemo/HYBPropertyLearn.m @@ -14,12 +14,13 @@ @implementation HYBPropertyLearn - (void)getAllProperties { unsigned int outCount = 0; + // Ivar objc_property_t *properties = class_copyPropertyList(self.class, &outCount); for (unsigned int i = 0; i < outCount; ++i) { objc_property_t property = properties[i]; const char *propertyName = property_getName(property); - + const char *propertyAttributes = property_getAttributes(property); NSLog(@"%s %s", propertyName, propertyAttributes); diff --git a/RuntimeDemo/HYBTestModel.m b/RuntimeDemo/HYBTestModel.m index 3286bf7..60f9396 100644 --- a/RuntimeDemo/HYBTestModel.m +++ b/RuntimeDemo/HYBTestModel.m @@ -31,12 +31,13 @@ - (instancetype)initWithDictionary:(NSDictionary *)dictionary { } } } - + return self; } - (NSDictionary *)toDictionary { unsigned int outCount = 0; + objc_property_t *properties = class_copyPropertyList([self class], &outCount); if (outCount != 0) { diff --git a/RuntimeDemo/Info.plist b/RuntimeDemo/Info.plist index 6905cc6..65ca776 100644 --- a/RuntimeDemo/Info.plist +++ b/RuntimeDemo/Info.plist @@ -22,6 +22,11 @@ 1 LSRequiresIPhoneOS + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + UILaunchStoryboardName LaunchScreen UIMainStoryboardFile diff --git a/RuntimeDemo/NSArray+Swizzling.m b/RuntimeDemo/NSArray+Swizzling.m index 2dcba77..0565d66 100644 --- a/RuntimeDemo/NSArray+Swizzling.m +++ b/RuntimeDemo/NSArray+Swizzling.m @@ -12,18 +12,22 @@ @implementation NSArray (Swizzling) -//+ (void)load { -// static dispatch_once_t onceToken; -// dispatch_once(&onceToken, ^{ -// [self swizzleSelector:@selector(lastObject) -// withSwizzledSelector:@selector(hdf_lastObject)]; -// }); -//} ++ (void)load { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + [self swizzleSelector:@selector(lastObject) + withSwizzledSelector:@selector(hdf_lastObject)]; + }); +} - (id)hdf_lastObject { - NSLog(@"%s", __FUNCTION__); + if (self.count == 0) { + NSLog(@"%s 数组为空,直接返回nil", __FUNCTION__); + + return nil; + } - return [self hdf_lastObject]; + return [self hdf_lastObject]; } diff --git a/RuntimeDemo/NSMutableArray+Swizzling.m b/RuntimeDemo/NSMutableArray+Swizzling.m index 98950d6..c806659 100644 --- a/RuntimeDemo/NSMutableArray+Swizzling.m +++ b/RuntimeDemo/NSMutableArray+Swizzling.m @@ -12,46 +12,52 @@ @implementation NSMutableArray (Swizzling) -//+ (void)load { -// static dispatch_once_t onceToken; -// dispatch_once(&onceToken, ^{ -// [self swizzleSelector:@selector(removeObject:) -// withSwizzledSelector:@selector(hdf_safeRemoveObject:)]; -// -// [objc_getClass("__NSArrayM") swizzleSelector:@selector(addObject:) -// withSwizzledSelector:@selector(hdf_safeAddObject:)]; -// [objc_getClass("__NSArrayM") swizzleSelector:@selector(removeObjectAtIndex:) -// withSwizzledSelector:@selector(hdf_safeRemoveObjectAtIndex:)]; -// -// [objc_getClass("__NSArrayM") swizzleSelector:@selector(insertObject:atIndex:) -// withSwizzledSelector:@selector(hdf_insertObject:atIndex:)]; -// -// [objc_getClass("__NSPlaceholderArray") swizzleSelector:@selector(initWithObjects:count:) withSwizzledSelector:@selector(hdf_initWithObjects:count:)]; -// -// [objc_getClass("__NSArrayM") swizzleSelector:@selector(objectAtIndex:) withSwizzledSelector:@selector(hdf_objectAtIndex:)]; -// }); -//} ++ (void)load { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + [self swizzleSelector:@selector(removeObject:) + withSwizzledSelector:@selector(hdf_safeRemoveObject:)]; + + [objc_getClass("__NSArrayM") swizzleSelector:@selector(addObject:) + withSwizzledSelector:@selector(hdf_safeAddObject:)]; + [objc_getClass("__NSArrayM") swizzleSelector:@selector(removeObjectAtIndex:) + withSwizzledSelector:@selector(hdf_safeRemoveObjectAtIndex:)]; + + [objc_getClass("__NSArrayM") swizzleSelector:@selector(insertObject:atIndex:) + withSwizzledSelector:@selector(hdf_insertObject:atIndex:)]; + + [objc_getClass("__NSPlaceholderArray") swizzleSelector:@selector(initWithObjects:count:) withSwizzledSelector:@selector(hdf_initWithObjects:count:)]; + + [objc_getClass("__NSArrayM") swizzleSelector:@selector(objectAtIndex:) withSwizzledSelector:@selector(hdf_objectAtIndex:)]; + }); +} - (instancetype)hdf_initWithObjects:(const id _Nonnull __unsafe_unretained *)objects count:(NSUInteger)cnt { BOOL hasNilObject = NO; for (NSUInteger i = 0; i < cnt; i++) { + if ([objects[i] isKindOfClass:[NSArray class]]) { + NSLog(@"%@", objects[i]); + } if (objects[i] == nil) { + hasNilObject = YES; + NSLog(@"%s object at index %lu is nil, it will be filtered", __FUNCTION__, i); + //#if DEBUG +// // 如果可以对数组中为nil的元素信息打印出来,增加更容易读懂的日志信息,这对于我们改bug就好定位多了 // NSString *errorMsg = [NSString stringWithFormat:@"数组元素不能为nil,其index为: %lu", i]; // NSAssert(objects[i] != nil, errorMsg); //#endif - hasNilObject = YES; - NSLog(@"%s object at index %lu is nil, it will be filtered", __FUNCTION__, i); } } + // 因为有值为nil的元素,那么我们可以过滤掉值为nil的元素 if (hasNilObject) { id __unsafe_unretained newObjects[cnt]; NSUInteger index = 0; for (NSUInteger i = 0; i < cnt; ++i) { if (objects[i] != nil) { - newObjects[index++] = objects[i]; + newObjects[index++] = objects[i]; } } @@ -61,6 +67,7 @@ - (instancetype)hdf_initWithObjects:(const id _Nonnull __unsafe_unretained *)ob return [self hdf_initWithObjects:objects count:cnt]; } + - (void)hdf_safeAddObject:(id)obj { if (obj == nil) { NSLog(@"%s can add nil object into NSMutableArray", __FUNCTION__); diff --git a/RuntimeDemo/NSObject+Swizzling.m b/RuntimeDemo/NSObject+Swizzling.m index 5abdec6..6b59502 100644 --- a/RuntimeDemo/NSObject+Swizzling.m +++ b/RuntimeDemo/NSObject+Swizzling.m @@ -14,13 +14,10 @@ @implementation NSObject (Swizzling) // 全面 + (void)swizzleSelector:(SEL)originalSelector withSwizzledSelector:(SEL)swizzledSelector { Class class = [self class]; - + Method originalMethod = class_getInstanceMethod(class, originalSelector); Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector); -// IMP oIMP = class_getMethodImplementation(class, originalSelector); -// IMP nIMP = class_getMethodImplementation(class, swizzledSelector); -// // 若已经存在,则添加会失败 BOOL didAddMethod = class_addMethod(class, originalSelector, diff --git a/RuntimeDemo/UIViewController+Swizzling.h b/RuntimeDemo/UIViewController+Swizzling.h new file mode 100644 index 0000000..41535b7 --- /dev/null +++ b/RuntimeDemo/UIViewController+Swizzling.h @@ -0,0 +1,13 @@ +// +// UIWebView+Swizzling.h +// RuntimeDemo +// +// Created by huangyibiao on 16/1/13. +// Copyright © 2016年 huangyibiao. All rights reserved. +// + +#import + +@interface UIViewController (Swizzling) + +@end diff --git a/RuntimeDemo/UIViewController+Swizzling.m b/RuntimeDemo/UIViewController+Swizzling.m new file mode 100644 index 0000000..49ed5fa --- /dev/null +++ b/RuntimeDemo/UIViewController+Swizzling.m @@ -0,0 +1,42 @@ +// +// UIWebView+Swizzling.m +// RuntimeDemo +// +// Created by huangyibiao on 16/1/13. +// Copyright © 2016年 huangyibiao. All rights reserved. +// + +#import "UIViewController+Swizzling.h" +#import "NSObject+Swizzling.h" + +@implementation UIViewController (Swizzling) + ++ (void)load { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + [self swizzleSelector:@selector(webView:shouldStartLoadWithRequest:navigationType:) + withSwizzledSelector:@selector(hdf_webView:shouldStartLoadWithRequest:navigationType:)]; + }); +} + +- (BOOL)hdf_webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { + NSString *url = request.URL.absoluteString; + + // 注意containsString是iOS8以后才有,具体要兼容ios6则需要自己写 + // 这里只是为了简便测试 + if ([url containsString:@"userId"] && [url containsString:@"token"]) { + return [self hdf_webView:webView shouldStartLoadWithRequest:request navigationType:navigationType]; + } + + if ([url isEqualToString:@"about:blank"]) { + return [self hdf_webView:webView shouldStartLoadWithRequest:request navigationType:navigationType]; + } + + url = [NSString stringWithFormat:@"%@?userId=123&token=ssdfsfdf", url]; + NSURLRequest *req = [NSURLRequest requestWithURL:[NSURL URLWithString:url]]; + [webView loadRequest:req]; + + return NO; +} + +@end diff --git a/RuntimeDemo/ViewController.m b/RuntimeDemo/ViewController.m index 76578fd..90158e4 100644 --- a/RuntimeDemo/ViewController.m +++ b/RuntimeDemo/ViewController.m @@ -16,8 +16,11 @@ #import "HYBMethodExchange.h" #import "HYBPropertyLearn.h" #import "HYBMethodLearn.h" +#import "UIViewController+Swizzling.h" -@interface ViewController () +@interface ViewController () + +@property (nonatomic, strong) UIWebView *webView; @end @@ -33,12 +36,22 @@ - (void)viewDidLoad { // [HYBMsgSend test]; // [HYBMethodExchange test]; // [HYBPropertyLearn test]; - [HYBMethodLearn test]; +// [HYBMethodLearn test]; + [self testWebview]; +} + +- (void)testWebview { + self.webView = [[UIWebView alloc] initWithFrame:self.view.bounds]; + self.webView.delegate = self; + NSURLRequest *req = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.haodf.com/"]]; + [self.webView loadRequest:req]; } -- (void)didReceiveMemoryWarning { - [super didReceiveMemoryWarning]; - // Dispose of any resources that can be recreated. + +- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { + NSLog(@"url: %@", request.URL.absoluteString); + + return YES; } @end