How to initialize an NSArray (and see what generic type is needed)

Hi,

I have started to actually try and understand the way the ios bindings work. I found some ios code that would retrieve all contacts here.

//iOS 9 or later
        NSError* contactError;
        CNContactStore* addressBook = [[CNContactStore alloc]init];
        [addressBook containersMatchingPredicate:[CNContainer predicateForContainersWithIdentifiers: @[addressBook.defaultContainerIdentifier]] error:&contactError];
        NSArray * keysToFetch [email protected][CNContactEmailAddressesKey, CNContactPhoneNumbersKey, CNContactFamilyNameKey, CNContactGivenNameKey, CNContactPostalAddressesKey];
        CNContactFetchRequest * request = [[CNContactFetchRequest alloc]initWithKeysToFetch:keysToFetch];
        BOOL success = [addressBook enumerateContactsWithFetchRequest:request error:&contactError usingBlock:^(CNContact * __nonnull contact, BOOL * __nonnull stop){
            [self parseContactWithContact:contact];
        }];

As you can see in objective c there is an “keysToFetch” array defined. I found out that I can create a CNContactFetchRequest like this:

NSArray<?> keysToFetch = NSArray.alloc().init();
CNContactFetchRequest request = CNContactFetchRequest.alloc().initWithKeysToFetch(keysToFetch);

But what do I put in that array? The initWithKeysToFetch(NSArray<?> keysToFetch) signature doesn’t specify a generic type. I noticed that the keys in my example are all variables of the Contacts.java and they are returned as String. Does that mean I can just insert Strings and use NSArray< String>?

Also, if I start allocating variables like this, do I need to dealloc() them whenever I am done with them? Or is there some kind of garbage collection for variables I allocate and initialize within a method.

A lot of types are “hidden” when working with MOE from what I’ve seen, so you’ll encounter a lot of “?”. A quick way to know what the real type of a variable/return value is is to just add a breakpoint and check in the debugger.

You should declare your array this way :

NSMutableArray<String> keysToFetch = (NSMutableArray<String>) NSMutableArray.alloc().init()

If you use a simple NSArray, you’ll get an UnsupportedOperationException when trying to add() or remove(). you need a Mutable one for this (I imagine that’s what you want to do). I just stumbled upon this issue an hour ago haha.

I don’t know if it’s the best way of doing things but it works. You can’t insert Strings into a NSArray<?>, first because it’s not mutable and because you can’t insert a specific type into a ? type. ? is an upper-bounded wildcard.

As for dealloc(), someone correct me if I’m wrong but from what I’ve read in the NatJ documentation, it’s done automatically by the garbage collector. You don’t have to manually call dealloc() when you alloc :slight_smile:

Thanks for the reply! Will be useful if I need to construct a mutable array.

This situation might not even need a mutable. This array definition looks like an immutable array where the elements are declared on initialization.

Just found a snippet in the samples here

I’ll try something like this when I get home and let you know if this works as I expect it should:
NSArray<?> array = NSArray.arrayWithObjects("CNContactEmailAddressesKey", "CNContactPhoneNumbersKey");

Yes that works if you already know what you’ll be putting inside of it, in this case you can even take a NSArray instead of <?>, as using arrayWithObjects() will return an NSArray with the type of the objects you passed as parameters :slight_smile:

Found this objective C sample:

Also heard that I have to add something to the info.plist to explain why I need contact info: