Count Number of Instances of a Class Swift

count number of instances of a class swift

Inside initializer method you have to add one to your static var with

Car.carPopulation += 1

And you must implement de deinitializer to delete the car entity that is going to disappear

deinit
{
Car.carPopulation -= 1
}

Get number of instances of custom class

No you can not get directly. Whenever you create in instance add it any Array and then access it using that array properties.

Ex :

NSMutableArray *allInstancesArray = [NSMutableArray new];
PaperPack *pack1 = [[PaperPack alloc] init];
pack1.title = @"Title 1";
pack1.author = @"Author";
[allInstancesArray addObject:pack1];

PaperPack *pack2 = [[PaperPack alloc] init];
pack1.title = @"Title 2";
pack1.author = @"Author";
[allInstancesArray addObject:pack2];

Then get count as :

NSLog(@"TOTAL INSTANCES : %d",[allInstancesArray count]);

How to count how many times all classes are called

If you mean visited each view controller, when you say visited each class. Then i'd recommend you do it viewDidAppear.

class YourViewController: UIViewController {

override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)

let key = String(describing: type(of: self))
let count = UserDefaults.standard.value(forKey: key) as? Int ?? 0
UserDefaults.standard.set(value + 1, forKey: key)
}

}

To make it simpler, you could use an extension on UIViewController.

extension UIViewController {

func updateVisitCount() {
let key = String(describing: type(of: self))
let count = UserDefaults.standard.value(forKey: key) as? Int ?? 0
UserDefaults.standard.set(count + 1, forKey: key)
}

}

Or, if you need this for every view controller that you create, then you can create a base view controller which you would use everywhere instead of UIViewController.

class BaseViewController: UIViewController {

override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)

updateVisitCount()
}

}

Count number of objects of class

The obvious solution is to use an array, put all your recipes in an array and return the count of such array on the tableView datasource. Something like

// Declare it on your interface
@property (nonatomic, strong) NSArray *recipes;
...

// On your viewDidLoad
self.recipes = @[recipe1, recipe2]; // and so on
...

// UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.recipes.count;
}

How to count occurrences of an element in a Swift array?

Swift 3 and Swift 2:

You can use a dictionary of type [String: Int] to build up counts for each of the items in your [String]:

let arr = ["FOO", "FOO", "BAR", "FOOBAR"]
var counts: [String: Int] = [:]

for item in arr {
counts[item] = (counts[item] ?? 0) + 1
}

print(counts) // "[BAR: 1, FOOBAR: 1, FOO: 2]"

for (key, value) in counts {
print("\(key) occurs \(value) time(s)")
}

output:

BAR occurs 1 time(s)
FOOBAR occurs 1 time(s)
FOO occurs 2 time(s)

Swift 4:

Swift 4 introduces (SE-0165) the ability to include a default value with a dictionary lookup, and the resulting value can be mutated with operations such as += and -=, so:

counts[item] = (counts[item] ?? 0) + 1

becomes:

counts[item, default: 0] += 1

That makes it easy to do the counting operation in one concise line using forEach:

let arr = ["FOO", "FOO", "BAR", "FOOBAR"]
var counts: [String: Int] = [:]

arr.forEach { counts[$0, default: 0] += 1 }

print(counts) // "["FOOBAR": 1, "FOO": 2, "BAR": 1]"

Swift 4: reduce(into:_:)

Swift 4 introduces a new version of reduce that uses an inout variable to accumulate the results. Using that, the creation of the counts truly becomes a single line:

let arr = ["FOO", "FOO", "BAR", "FOOBAR"]
let counts = arr.reduce(into: [:]) { counts, word in counts[word, default: 0] += 1 }

print(counts) // ["BAR": 1, "FOOBAR": 1, "FOO": 2]

Or using the default parameters:

let counts = arr.reduce(into: [:]) { $0[$1, default: 0] += 1 }

Finally you can make this an extension of Sequence so that it can be called on any Sequence containing Hashable items including Array, ArraySlice, String, and String.SubSequence:

extension Sequence where Element: Hashable {
var histogram: [Element: Int] {
return self.reduce(into: [:]) { counts, elem in counts[elem, default: 0] += 1 }
}
}

This idea was borrowed from this question although I changed it to a computed property. Thanks to @LeoDabus for the suggestion of extending Sequence instead of Array to pick up additional types.

Examples:

print("abacab".histogram)
["a": 3, "b": 2, "c": 1]
print("Hello World!".suffix(6).histogram)
["l": 1, "!": 1, "d": 1, "o": 1, "W": 1, "r": 1]
print([1,2,3,2,1].histogram)
[2: 2, 3: 1, 1: 2]
print([1,2,3,2,1,2,1,3,4,5].prefix(8).histogram)
[1: 3, 2: 3, 3: 2]
print(stride(from: 1, through: 10, by: 2).histogram)
[1: 1, 3: 1, 5: 1, 7: 1, 9: 1]

Get instance count of a specific class in Objective-C/IOS

Per request, I've mocked up a category that will keep count of allocated objects using method swizzling and a singleton. This was a quick mock up, so there are a few issues with it (one being that initializing anything that is contained within the storage class will cause an infinite loop). Mind you, this is for keeping track of many objects and should not be used in a production environment. The best methodology overall is to use the instruments tool.

#import "NSObject+Initializer.h"
#import <objc/runtime.h>

@interface ObjectCounter : NSObject

+ (instancetype)sharedObjectCounter;
@property (strong, nonatomic) NSMutableDictionary *objectCounterDictionary;

@end

@implementation ObjectCounter

+ (instancetype)sharedObjectCounter
{
static ObjectCounter *objectCounter;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
objectCounter = [ObjectCounter new];
objectCounter.objectCounterDictionary = [NSMutableDictionary new];
});
return objectCounter;
}

@end

@implementation NSObject (Initializer)

+ (NSNumber *)initializedCount
{
NSLog(@"Dict: %@", [ObjectCounter sharedObjectCounter].objectCounterDictionary);
return [ObjectCounter sharedObjectCounter].objectCounterDictionary[NSStringFromClass([self class])];
}

+ (id)alloc_swizzled
{
NSLog(@"Swizzled");
NSString *className = NSStringFromClass([self class]);
if (![className isEqualToString:NSStringFromClass([NSMutableDictionary class])] && ![className isEqualToString:NSStringFromClass([ObjectCounter class])]) {
ObjectCounter *counter = [ObjectCounter sharedObjectCounter];
NSMutableDictionary *objectDictionary = counter.objectCounterDictionary;
NSNumber *count = objectDictionary[className];
count = count ? @(count.integerValue + 1) : @0;
objectDictionary[className] = count;
}

return [self alloc_swizzled];
}

+ (void)load
{

static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class class = [self class];

SEL originalSelector = @selector(alloc);
SEL swizzledSelector = @selector(alloc_swizzled);

Method originalMethod = class_getClassMethod(class, originalSelector);
Method swizzledMethod = class_getClassMethod(class, swizzledSelector);

BOOL didAddMethod = class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));

if (didAddMethod) {
class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
} else {
method_exchangeImplementations(originalMethod, swizzledMethod);
}
});
}


Related Topics



Leave a reply



Submit