diff --git a/MLeaksFinder/MLeakedObjectProxy.h b/MLeaksFinder/MLeakedObjectProxy.h old mode 100644 new mode 100755 diff --git a/MLeaksFinder/MLeakedObjectProxy.m b/MLeaksFinder/MLeakedObjectProxy.m old mode 100644 new mode 100755 diff --git a/MLeaksFinder/MLeaksFinder.h b/MLeaksFinder/MLeaksFinder.h old mode 100644 new mode 100755 index ec4024e..63570fb --- a/MLeaksFinder/MLeaksFinder.h +++ b/MLeaksFinder/MLeaksFinder.h @@ -27,3 +27,6 @@ #elif COCOAPODS #define _INTERNAL_MLF_RC_ENABLED COCOAPODS #endif + +//#define MEMORY_LEAKS_ALL_OBJECT_FINDER_ENABLED //是否开启所有属性的检查 + diff --git a/MLeaksFinder/MLeaksMessenger.h b/MLeaksFinder/MLeaksMessenger.h old mode 100644 new mode 100755 diff --git a/MLeaksFinder/NSArray+MemoryLeak.h b/MLeaksFinder/NSArray+MemoryLeak.h new file mode 100644 index 0000000..4f93080 --- /dev/null +++ b/MLeaksFinder/NSArray+MemoryLeak.h @@ -0,0 +1,15 @@ +// +// NSArray.h +// CTDebug +// +// Created by 王腾达 on 2017/11/6. +// Copyright © 2017年 liuweiso. All rights reserved. +// + +#import + +#ifdef MEMORY_LEAKS_ALL_OBJECT_FINDER_ENABLED +@interface NSArray(MemoryLeak) + +@end +#endif diff --git a/MLeaksFinder/NSArray+MemoryLeak.m b/MLeaksFinder/NSArray+MemoryLeak.m new file mode 100644 index 0000000..eb47147 --- /dev/null +++ b/MLeaksFinder/NSArray+MemoryLeak.m @@ -0,0 +1,34 @@ +// +// NSArray.m +// CTDebug +// +// Created by 王腾达 on 2017/11/6. +// Copyright © 2017年 liuweiso. All rights reserved. +// + +#import "NSArray+MemoryLeak.h" +#import "MLeaksFinder.h" + +#ifdef MEMORY_LEAKS_ALL_OBJECT_FINDER_ENABLED +@implementation NSArray(MemoryLeak) + +- (void)willReleaseIvarList +{ + if(!self.count) + { + return; + } + + for(id ob in self) + { + [ob willReleaseIvarList]; + } +} + +- (BOOL)continueCheckObjecClass:(Class)objectClass +{ + return YES; +} + +@end +#endif diff --git a/MLeaksFinder/NSDictionary+MemoryLeak.h b/MLeaksFinder/NSDictionary+MemoryLeak.h new file mode 100644 index 0000000..b220fd4 --- /dev/null +++ b/MLeaksFinder/NSDictionary+MemoryLeak.h @@ -0,0 +1,15 @@ +// +// NSDictionary.h +// CTDebug +// +// Created by 王腾达 on 2017/11/6. +// Copyright © 2017年 liuweiso. All rights reserved. +// + +#import + +#ifdef MEMORY_LEAKS_ALL_OBJECT_FINDER_ENABLED +@interface NSDictionary(MemoryLeak) + +@end +#endif diff --git a/MLeaksFinder/NSDictionary+MemoryLeak.m b/MLeaksFinder/NSDictionary+MemoryLeak.m new file mode 100644 index 0000000..8ef8649 --- /dev/null +++ b/MLeaksFinder/NSDictionary+MemoryLeak.m @@ -0,0 +1,34 @@ +// +// NSDictionary.m +// CTDebug +// +// Created by 王腾达 on 2017/11/6. +// Copyright © 2017年 liuweiso. All rights reserved. +// + +#import "NSDictionary+MemoryLeak.h" +#import "MLeaksFinder.h" + +#ifdef MEMORY_LEAKS_ALL_OBJECT_FINDER_ENABLED +@implementation NSDictionary(MemoryLeak) + +- (void)willReleaseIvarList +{ + if(!self.count) + { + return; + } + + for(id ob in self.allValues) + { + [ob willReleaseIvarList]; + } +} + +- (BOOL)continueCheckObjecClass:(Class)objectClass +{ + return YES; +} + +@end +#endif diff --git a/MLeaksFinder/NSObject+MemoryLeak.h b/MLeaksFinder/NSObject+MemoryLeak.h old mode 100644 new mode 100755 index 09c6047..bfe6fca --- a/MLeaksFinder/NSObject+MemoryLeak.h +++ b/MLeaksFinder/NSObject+MemoryLeak.h @@ -28,4 +28,9 @@ + (void)swizzleSEL:(SEL)originalSEL withSEL:(SEL)swizzledSEL; +#ifdef MEMORY_LEAKS_ALL_OBJECT_FINDER_ENABLED +- (void)willReleaseIvarList; +- (BOOL)continueCheckObjecClass:(Class)objectClass; +#endif + @end diff --git a/MLeaksFinder/NSObject+MemoryLeak.m b/MLeaksFinder/NSObject+MemoryLeak.m old mode 100644 new mode 100755 index 3b656eb..fd9b5f1 --- a/MLeaksFinder/NSObject+MemoryLeak.m +++ b/MLeaksFinder/NSObject+MemoryLeak.m @@ -24,6 +24,10 @@ static const void *const kParentPtrsKey = &kParentPtrsKey; const void *const kLatestSenderKey = &kLatestSenderKey; +#ifdef MEMORY_LEAKS_ALL_OBJECT_FINDER_ENABLED +static const void *const kCheckKey = &kCheckKey; +#endif + @implementation NSObject (MemoryLeak) - (BOOL)willDealloc { @@ -170,4 +174,104 @@ + (void)swizzleSEL:(SEL)originalSEL withSEL:(SEL)swizzledSEL { #endif } + +#ifdef MEMORY_LEAKS_ALL_OBJECT_FINDER_ENABLED +- (BOOL)leakChecked +{ + NSNumber *leak = objc_getAssociatedObject(self, kCheckKey); + return [leak boolValue]; +} + +- (void)setLeakChecked:(BOOL)leakChecked +{ + objc_setAssociatedObject(self, kCheckKey, @(leakChecked),OBJC_ASSOCIATION_RETAIN); +} + +- (BOOL)continueCheckObjecClass:(Class)objectClass +{ + if(!objectClass) + { + return NO; + } + + NSBundle *bundle = [NSBundle bundleForClass:objectClass]; + if(bundle != [NSBundle mainBundle]) + { + return NO; + } + + return YES; + +} + +- (void)willReleaseIvarLisWithTargetObjectClass:(id)targetObjectClass +{ + if(!targetObjectClass) + { + return; + } + NSArray *viewStack = [self viewStack]; + NSSet *parentPtrs = [self parentPtrs]; + + unsigned int outCount = 0; + Ivar * ivars = class_copyIvarList(targetObjectClass, &outCount); + NSString *stringType = nil; + for (unsigned int i = 0; i < outCount; i ++) { + Ivar ivar = ivars[i]; + const char * name = ivar_getName(ivar); + const char * type = ivar_getTypeEncoding(ivar); + stringType = [NSString stringWithCString:type encoding:NSUTF8StringEncoding]; + //非NSObject类型不用继续遍历 + if ((!name) || ![stringType hasPrefix:@"@"] || [stringType isEqualToString:@"@"]) { + + continue; + } + + id value = nil; + + @try { + value = [self valueForKey:[NSString stringWithUTF8String:name]]; + } @catch (NSException *exception) { + NSLog(@"class %@ valueForKey:%s throw NSException,",NSStringFromClass([targetObjectClass class]),name); + } + + if(![value continueCheckObjecClass:[value class]]) + { + continue; + } + + NSString *className = NSStringFromClass([value class]); + [value setViewStack:[viewStack arrayByAddingObject:className]]; + [value setParentPtrs:[parentPtrs setByAddingObject:@((uintptr_t)value)]]; + [value willDealloc]; + [value willReleaseIvarList]; + + } + free(ivars); +} + +- (void)willReleaseIvarList +{ + if([self leakChecked]) + { + return; + } + [self setLeakChecked:YES]; + + if(![self continueCheckObjecClass:[self class]]) + { + return; + } + [self willReleaseIvarLisWithTargetObjectClass:[self class]]; + + if(![self continueCheckObjecClass:[self superclass]]) + { + return; + } + [self willReleaseIvarLisWithTargetObjectClass:[self superclass]]; + +} + +#endif + @end diff --git a/MLeaksFinder/NSSet+MemoryLeak.h b/MLeaksFinder/NSSet+MemoryLeak.h new file mode 100644 index 0000000..9087bae --- /dev/null +++ b/MLeaksFinder/NSSet+MemoryLeak.h @@ -0,0 +1,17 @@ +// +// NSSet.h +// CTDebug +// +// Created by 王腾达 on 2017/11/6. +// Copyright © 2017年 liuweiso. All rights reserved. +// + +#import + +#ifdef MEMORY_LEAKS_ALL_OBJECT_FINDER_ENABLED +@interface NSSet(MemoryLeak) + +- (BOOL)continueCheckObjecClass:(Class)objectClass; + +@end +#endif diff --git a/MLeaksFinder/NSSet+MemoryLeak.m b/MLeaksFinder/NSSet+MemoryLeak.m new file mode 100644 index 0000000..ef22503 --- /dev/null +++ b/MLeaksFinder/NSSet+MemoryLeak.m @@ -0,0 +1,36 @@ +// +// NSSet.m +// CTDebug +// +// Created by 王腾达 on 2017/11/6. +// Copyright © 2017年 liuweiso. All rights reserved. +// + +#import "NSSet+MemoryLeak.h" +#import "MLeaksFinder.h" + +#ifdef MEMORY_LEAKS_ALL_OBJECT_FINDER_ENABLED +@implementation NSSet(MemoryLeak) + +- (void)willReleaseIvarList +{ + if(!self.count) + { + return; + } + + id obj; + + NSEnumerator * enumerator = [self objectEnumerator]; + while (obj = [enumerator nextObject]) { + [obj willReleaseIvarList]; + } +} + +- (BOOL)continueCheckObjecClass:(Class)objectClass +{ + return YES; +} + +@end +#endif diff --git a/MLeaksFinder/UIApplication+MemoryLeak.h b/MLeaksFinder/UIApplication+MemoryLeak.h old mode 100644 new mode 100755 diff --git a/MLeaksFinder/UIApplication+MemoryLeak.m b/MLeaksFinder/UIApplication+MemoryLeak.m old mode 100644 new mode 100755 diff --git a/MLeaksFinder/UINavigationController+MemoryLeak.h b/MLeaksFinder/UINavigationController+MemoryLeak.h old mode 100644 new mode 100755 diff --git a/MLeaksFinder/UINavigationController+MemoryLeak.m b/MLeaksFinder/UINavigationController+MemoryLeak.m old mode 100644 new mode 100755 diff --git a/MLeaksFinder/UIPageViewController+MemoryLeak.h b/MLeaksFinder/UIPageViewController+MemoryLeak.h old mode 100644 new mode 100755 diff --git a/MLeaksFinder/UIPageViewController+MemoryLeak.m b/MLeaksFinder/UIPageViewController+MemoryLeak.m old mode 100644 new mode 100755 diff --git a/MLeaksFinder/UISplitViewController+MemoryLeak.h b/MLeaksFinder/UISplitViewController+MemoryLeak.h old mode 100644 new mode 100755 diff --git a/MLeaksFinder/UISplitViewController+MemoryLeak.m b/MLeaksFinder/UISplitViewController+MemoryLeak.m old mode 100644 new mode 100755 diff --git a/MLeaksFinder/UITabBarController+MemoryLeak.h b/MLeaksFinder/UITabBarController+MemoryLeak.h old mode 100644 new mode 100755 diff --git a/MLeaksFinder/UITabBarController+MemoryLeak.m b/MLeaksFinder/UITabBarController+MemoryLeak.m old mode 100644 new mode 100755 diff --git a/MLeaksFinder/UITouch+MemoryLeak.h b/MLeaksFinder/UITouch+MemoryLeak.h old mode 100644 new mode 100755 diff --git a/MLeaksFinder/UITouch+MemoryLeak.m b/MLeaksFinder/UITouch+MemoryLeak.m old mode 100644 new mode 100755 diff --git a/MLeaksFinder/UIView+MemoryLeak.h b/MLeaksFinder/UIView+MemoryLeak.h old mode 100644 new mode 100755 diff --git a/MLeaksFinder/UIView+MemoryLeak.m b/MLeaksFinder/UIView+MemoryLeak.m old mode 100644 new mode 100755 index ec8dc7e..9048810 --- a/MLeaksFinder/UIView+MemoryLeak.m +++ b/MLeaksFinder/UIView+MemoryLeak.m @@ -21,9 +21,9 @@ - (BOOL)willDealloc { if (![super willDealloc]) { return NO; } - + [self willReleaseChildren:self.subviews]; - + return YES; } diff --git a/MLeaksFinder/UIViewController+MemoryLeak.h b/MLeaksFinder/UIViewController+MemoryLeak.h old mode 100644 new mode 100755 diff --git a/MLeaksFinder/UIViewController+MemoryLeak.m b/MLeaksFinder/UIViewController+MemoryLeak.m old mode 100644 new mode 100755 index 5c59bf6..d824eba --- a/MLeaksFinder/UIViewController+MemoryLeak.m +++ b/MLeaksFinder/UIViewController+MemoryLeak.m @@ -68,9 +68,13 @@ - (BOOL)willDealloc { [self willReleaseChild:self.view]; } +#ifdef MEMORY_LEAKS_ALL_OBJECT_FINDER_ENABLED + [self willReleaseIvarList]; +#endif + return YES; } @end - #endif +