This question already has answers here:
Comparing Strings in Cocoa
(5 answers)
Closed 9 years ago.
I am trying to determine if I have a duplicate record in CoreData using MagicalRecord. To do that, I am comparing the updated data with the first existing record:
This is the code I am using to do the search:
// set up predicate to find single appointment
if(selectedApptKey.length > 0) {
NSPredicate *predicate = ([NSPredicate predicateWithFormat:
#"((aApptKey == %#) && (aStartTime == %#) && (aEndTime == %#) && (aServiceTech == %#))",
selectedApptKey, tStartDate, tEndDate, tStaff]);
NSLog(#"\n\nselectedApptKey: %#\ntStartDate: %#\ntEndDate: %#\ntStaff: %#",selectedApptKey, tStartDate, tEndDate, tStaff);
ai = [AppointmentInfo MR_findFirstWithPredicate:predicate inContext:localContext];
if((ai.aApptKey == selectedApptKey) &&
(ai.aStartTime == tStartDate) &&
(ai.aEndTime == tEndDate) &&
(ai.aServiceTech == tStaff)) {
updateFlag = YES;
}
}
This is the predicate data I am using to search for an existing record:
selectedApptKey: RolfMarsh3911
tStartDate: 2013-12-29 20:15:00 +0000
tEndDate: 2013-12-29 22:15:00 +0000
tStaff: Kellie
This is the resulting record as obtained from the above code:
Printing description of ai:
<NSManagedObject: 0xb705430> (entity: AppointmentInfo; id: 0xb7bca00 <x-coredata://649CD00C-3C88-4447-AA2B-60B792E3B25F/AppointmentInfo/p22> ; data: {
aApptKey = RolfMarsh3911;
aEndTime = "2013-12-29 22:15:00 +0000";
aImage = nil;
aNotes = "";
aPosH = 200;
aPosW = 214;
aPosX = 0;
aPosY = 231;
aServiceTech = Kellie;
aServices = "";
aStartTime = "2013-12-29 20:15:00 +0000";
client = nil;
})
As you can see, the record and search data are exact. Qustion is: why is the if statement failing (the updateFlag is not being set to YES)?
You need to use isEqualToString: instead of ==, since you want to compare the actual object values, not the pointers. Assuming these are all strings. If you have some date objects use isEqualToDate:.
== always compares the pointers, which in this case are not equal, since they are pointing to different objects.
Related
Can't seem to figure out how to check a string so that the same two characters in a row are not allowed.
I don't want anyone to be able to submit data with "00".
What about just:
(\d)\1+
The \d matches any digit and the \1+ matches whatever was matched in the first bit when it appears more than one time.
Pertaining to your comments though, it's much easier just to check:
if ([expiryDate rangeOfString:#"00"].location != NSNotFound)
{
//Invalid date
}
or even perhaps more validating:
NSArray *components = [expiryDate componentsSeparatedByString:#"/"];
int month = [components[0] intValue];
int year = [components[1] intValue];
NSAssert(month > 0 && month <= 12, #"Invalid Month");
NSAssert(year >= 13 /*current year*/ /* (optionally) && year < 20 (or some other future year)*/, #"Invalid year");
Wondering if there is a way to shorthand these conditionals. I am working with data packets and the conditionals get a bit unwieldy at times. Here's a basic example:
I write:
if (message->messageType != kMessageTypeCutCardsArray && message->messageType != kMessageTypeQuit) {
MessageInt message;
message.message.messageType = kMessageTypeReceivedData;
NSData *packet = [NSData dataWithBytes:&message length:sizeof(message)];
[_game sendData:packet];
}
I would rather write:
if (message->messageType != (kMessageTypeCutCardsArray || kMessageTypeQuit)) {
MessageInt message;
message.message.messageType = kMessageTypeReceivedData;
NSData *packet = [NSData dataWithBytes:&message length:sizeof(message)];
[_game sendData:packet];
}
As a general matter, no. That's just the way that C (and hence Objective-C) works.
In this specific case, you could use a switch statement:
switch (message->messageType)
{
case kMessageTypeCutCardsArray:
case kMessageTypeQuit:
break;
default:
MessageInt message;
message.message.messageType = kMessageTypeReceivedData;
NSData *packet = [NSData dataWithBytes:&message length:sizeof(message)];
[_game sendData:packet];
break;
}
Whether that syntax is an improvement is up to you.
If you define your enum such that the values have mutually-exclusive bit patterns, like so:
typedef enum : NSUInteger {
kMessageTypeLoveLetter = 1 << 0,
kMessageTypeBirthdayCard = 1 << 1,
kMessageTypeVacationPostcard = 1 << 2,
kMessageTypeCreditApplication = 1 << 3,
kMessageTypeCharitySolicitation = 1 << 4
} MessageType;
You can then test for multiple values at once, using binary OR | and binary AND &:
MessageType msgType = kMessageTypeCreditApplication;
if( !(msgType & (kMessageTypeLoveLetter | kMessageTypeBirthdayCard)) ){
// Nobody loves you.
}
if( (msgType & (kMessageTypeCreditApplication | kMessageTypeCharitySolicitation) ){
// Someone wants your money.
}
This won't work, however, if you use the compiler-generated consecutive values for the enum, because the values will overlap as flags -- e.g., both 2 and 3 have the lowest bit set -- and ORing them together will often end up testing only one of the flags.
You could box the values and use a temporary array. This achieves the goal of removing the duplication in the conditional, but is unlikely to be as optimizable for the compiler.
if (message->messageType != kMessageTypeCutCardsArray &&
message->messageType != kMessageTypeQuit) {
should be equivalent to:
if(![#[#(kMessageTypeCutCardsArray),#(kMessageTypeQuit)]
contains:#(message->messageType)]) {
Guys what am I doing wrong?
if (numberstring.intValue <=15) {
rankLabel.text = #"A1";
}
else if (numberstring.intValue >16 && <=40){
rankLabel.text = #"A2";
}
I get an error on the "<=40" ..
You missed off a variable reference:
if (numberstring.intValue <=15) {
rankLabel.text = #"A1";
} // vv here vv
else if (numberstring.intValue >16 && numberstring.intValue <= 40){
rankLabel.text = #"A2";
}
As an optional extra, it looks like numberstring is an NSString object, which you are repeatedly converting to an integer in order to test various ranges. That operation is quite expensive, so you are better off doing the conversion once:
int value = [numberstring intValue];
if (value <=15) {
rankLabel.text = #"A1";
}
else if (value >16 && value <= 40){
rankLabel.text = #"A2";
}
Also note that the intValue method is not a property so I would avoid using the Objective-C 2.0 dot syntax to access it and use the normal method calling mechanism.
The && operator links two clauses together. However, each clause is independent, so each one has to be syntactically correct on its own if the other was removed. If you apply this rule to your condition, you can see that "<=40" is not syntactically correct on its own. Thus you need to reference the value being compared, as follows:
if (numberstring.intValue > 16 &&
numberstring.intValue <= 40) // this is syntactically correct on its own
the problem is this:
I have 3 Entities: ImgThumb, Img, and BookmarkedItems. They have relationships between them as follows:
ImgThumb <-> Img (1 to 1)
Img <->> BookmarkItems (1 to many)
Now, having an ImgThumb Array I'm trying to make a NSPredicate which filters these ImgThumbs as follows:
I need all ImgThumbs that are not bookmarked.
In order to achieve this I'm trying to build an NSPredicate using SUBQUERY like this:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"0 != SUBQUERY(image, $x, 0 != SUBQUERY($x.bookmarkItems, $y, $y.#count == 0).#count).#count"];
My Request fails with error:
Unable to generate SQL for predicate (0 != SUBQUERY(image, $x, 0 != SUBQUERY($x.bookmarkItems, $y, $y.#count == 0).#count).#count) (problem on RHS)
What am I doing wrong?
You don't need a SUBQUERY. I'm assuming your fetch entity is ImgThumb, in which case your predicate should be:
[NSPredicate predicateWithFormat:#"img.bookmarkItems.#count == 0"];
Let's say that I want to check that one of two terms are effective, how do I express it?
if (value == 1 **--OR--** value == nil) {
do something;
}
||
eg: if (value == 1 || value == nil)