0

I've been working on this problem for a while and can't seem to find the solution. In my app, I uniquely identify contacts from ABAddressBook by their creation date, as no two contacts can be created at the same time. In my app, the creation date is stored in a string called uid, as you can see below. I am checking to see if two contacts are the same, and I do this by performing the following conditional statement:

NSString *uid = @"some string";

if([(__bridge_transfer NSString *)ABRecordCopyValue(currentPersonRef, kABPersonCreationDateProperty) isEqualToString:uid]) {

    //Do some code
}

However, when I run this code, I get the following error:

[__NSDate isEqualToString:]: unrecognized selector sent to instance 0x8c7c770

I'm pretty sure the problem is that ABRecordCopyValue() is returning an NSDate object that is not being casted to NSString by (__bridge_transfer NSString *), so when I compare it to uid using isEqualToString, it crashes. The thing is, I thought that by casting it to an NSString object, isEqualToString: would work. My question is:

Why is the (__bridge_transfer NSString *) not casting the NSDate object?


EDIT:

The answers provided have been useful, but they do not completely address my problem (well actually they do, but I have a follow-up question). In another part of my code, I run this:

NSString *uid = (__bridge_transfer NSString *)ABRecordCopyValue(currentPerson, kABPersonCreationDateProperty);

And if I NSLog uid I get this:

2012-10-28 21:55:29 +0000

So how would I compare uid in the above conditional statement if isEqualToString: doesn't work?

Community
  • 1
  • 1
pasawaya
  • 11,515
  • 7
  • 53
  • 92
  • You're asking for kABPersonCreationDateProperty which will always return a CFDateRef no matter how you typecast it. If you need it as a NSString you need to convert it first and then run `isEqualToString` on it. – Rog Oct 29 '12 at 02:33

2 Answers2

5

A cast never changes the class or type of an object. It just tells the compiler, that you are certain about the fact, that this object is of another type, than the compiler might assumes.

So if you cast a date object to a string, it will still be a date object.

In OOP you usually needs up-casting: a method wants you to pass in a object, but actually you pass in an object of a subclass. If you then need to access a property or method that is defined by the subclass, you will tell the compiler, that you have an object of the subclass by casting.
A very common example in iOS is tableview:cellForRowAtIndexPath: with subclassed cells.

In cocoa(-touch) you also know casting from toll-free bridging. see this documentation for valid casts.


The answers provided have been useful, but they do not completely address my problem (well actually they do, but I have a follow-up question). In another part of my code, I run this:

NSString *uid = (__bridge_transfer NSString *)ABRecordCopyValue(currentPerson, kABPersonCreationDateProperty);

And if I NSLog uid I get this:

2012-10-28 21:55:29 +0000

You are creating a variable, that you declare to be an NSString, but actually the object you assign to it, is a date object.

NSDate *uidDate = (__bridge_transfer NSDate *)ABRecordCopyValue(currentPerson, kABPersonCreationDateProperty);

NSString *uid = [NSString stringWithFormat:uidDate];
vikingosegundo
  • 52,040
  • 14
  • 137
  • 178
  • Thats true for pointer, but for primitive types like casting an int to a float, the type will be changed for you. – Nathan Day Oct 29 '12 at 02:45
  • So how would I compare the CFDateRef to the NSString (`uid`)? – pasawaya Oct 29 '12 at 02:45
  • actually it would be helpful to know the format go the uid. but you should cast the returned value to a nsdate and compare that. so either you create a nsdate from uid or a nsstring from the returned date. as we dont know that format you need there, it is hard to tell, how this should be done, as it could involve a date formatter. – vikingosegundo Oct 29 '12 at 02:51
0

Well, I don't know the answer to your question, but why don't you just convert the ABRecordCopyValue() to NSString, then do the isStringEqual:?

Like -

NSString *string = [NSString stringWithFormat:@"%@", ABRecordCopyValue(currentPersonRef, kABPersonCreationDateProperty)];
if([string isEqualToString: uid]){
    //do your thing
}
yeesterbunny
  • 1,847
  • 2
  • 13
  • 17
  • I tried that, but now it crashes with an `EXC_BAD_ACCESS` error. – pasawaya Oct 29 '12 at 02:44
  • This is the worst possible way to convert a date object to a string. You are relying on an undocumented, and changeable, implementation of of `NSDate description`. What's worse here is that you don't even have an NSDate. You get a CFDateRef. Either use an NSDateFormatter to convert the date to a string, or convert the string to date. – rmaddy Oct 29 '12 at 03:30
  • Thanks for the insight. I'll keep that in mind. If you want your insight to be seen, you should put it on the accepted answer, since he also used stringWithFormat (but he bridged cast the CFDateRef, which I forgot). – yeesterbunny Oct 29 '12 at 03:46