Vijay Kumar
Vijay Kumar

Reputation: 124

How to identify custom classes vs Framework Classes in Objective-C

I am working on an Analytics Project by Swizzling UIViewController methods viewDidAppear and viewDidAppear, code snippet as follows,

- (void) swizzledViewDidAppear : (BOOL)animated {
    if ([UA isAppInitialized]) { // Check if Analytics Initialized
        if ([[self class] isSubclassOfClass:[UIViewController class]]) {
            [UA startPage:[NSString stringWithFormat:@"%@",  NSStringFromClass ([self class])]];
        }
    }
    [self swizzledViewDidAppear:animated];
}

- (void) swizzledViewDidDisappear : (BOOL)animated {
    if ([UA isAppInitialized]) { // Check if Analytics Initialized
        if ([[self class] isSubclassOfClass:[UIViewController class]]) {
            [UA endPage:[NSString stringWithFormat:@"%@", NSStringFromClass ([self class])]];
        }
    }
    [self swizzledViewDidDisappear:animated];
}

This is the code snippet where I want to track only the Custom ViewController, ex: MyViewController or FooViewController...etc and not Framework related classes like UICompatibilityInputViewController, UIInputWindowController...etc.

Please let me know how can I achieve this. I tried to check for Subclass but still at one point Framework classes are getting recorded.

Thanks, Vijay

Upvotes: 1

Views: 723

Answers (3)

Daij-Djan
Daij-Djan

Reputation: 50089

you can get a class's NSBundle and check if that bundle is yours.

swift example using an extension:

//code
extension NSObject {
    static var isOurClass: Bool {
        let appBundle = Bundle.main
        let clsBundle = Bundle(for: self.self);
        return clsBundle.bundlePath.hasPrefix(appBundle.bundlePath)
    }
}

//test
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

        print("appdelegate class ours? \(AppDelegate.isOurClass)")
        print("NSString class ours? \(NSString.isOurClass)")
        return true
    }
}

basic objc example:

#import <Foundation/Foundation.h>

@interface T : NSObject
@end

@implementation T
@end

int main(int argc, char *argv[]) {
    @autoreleasepool {
        NSBundle *bundleOfApp = [NSBundle mainBundle];
        NSLog(@"%@", bundleOfApp.bundlePath);

        //ours
        T *t = [T new];
        NSBundle *bundleOfT = [NSBundle bundleForClass:t.class];
        NSLog(@"%@", bundleOfT.bundlePath);

        if([bundleOfT.bundlePath hasPrefix:bundleOfApp.bundlePath]) {
            NSLog(@"ours");
        }

        //theirs

        bundleOfT = [NSBundle bundleForClass:NSString.class];
        NSLog(@"%@", bundleOfT.bundlePath);

        if([bundleOfT.bundlePath hasPrefix:bundleOfApp.bundlePath]) {
        }
        else {
            NSLog(@"theirs");
        }

    }
}

Upvotes: 2

Emel
Emel

Reputation: 208

I was swizzling viewDidLoad, loadView and awakeFromNib for measuring load times and there is some strange behavior I've noticed.

For framework classes like UIInputWindowController, UIKeyboardCandidateGridCollectionViewController : awakeFromNib or loadView doesn't get called. They immediately appear after viewDidLoad has been called.

So the following lines of codes:

- (void)swizzled_awakeFromNib
{
    NSLog(@"*** Awake from nib %@", NSStringFromClass(self.class));

    [self swizzled_awakeFromNib];
}

- (void)swizzled_viewDidLoad
{
    NSLog(@"*** View did load %@", NSStringFromClass(self.class));

    [self swizzled_viewDidLoad];
}

- (void)swizzled_loadView
{
    NSLog(@"*** Load view %@", NSStringFromClass(self.class));

    [self swizzled_loadView];
}

Prints:

*** Awake from nib UINavigationController
*** View did load UINavigationController
*** Load view MyLoginViewController
*** View did load UIInputWindowController
*** View did load UIKeyboardCandidateGridCollectionViewController
*** View did load UIInputWindowController
*** View did load UIApplicationRotationFollowingControllerNoTouches
*** View did load MyLoginViewController

So maybe you can add a property to your category and set it to YES if awakeFromNib and/or loadView has called. Then check that bool in your viewDidLoad method to see if its a framework class.

Upvotes: 0

Pushkraj Lanjekar
Pushkraj Lanjekar

Reputation: 2294

In this case you have make instance of your class like and check it like

MyViewController *myVcntrl = [[MyViewController alloc]init];
    if ([myVcntrl isKindOfClass:[MyViewController class]]) {
NSLog(@"Class is of MyViewController type");
    }
else {
NSLog(@"Not of MyViewController type");
}

Upvotes: 0

Related Questions