Cocoa: NSString doet vervelend

Ik probeer te controleren of een NSString gelijk is aan "00" en of het een integer is. De code die ik gebruik is: [code:1:0e8553ba12] for(i=0; i<array_count; i++){ if(!(test_value = [[localArray objectAtIndex:i] intValue]) && [localArray objectAtIndex:i] != @"00"){ NSLog(@"Failed at integercheck, %@ at %i", [localArray objectAtIndex:i], i); return FALSE; } }[/code:1:0e8553ba12] Vreemd, want deze code werkt wel: [code:1:0e8553ba12] NSString * test = @"00"; int test_value; if(test_value = [test intValue] || test == @"00"){ NSLog(@"integer"); }else{ NSLog(@"geen integer"); }[/code:1:0e8553ba12] Alvast bedankt :)

In de code die werkt gebruik je ||, in de code die niet werkt gebruik je &&.

Om beter te debuggen kun je ook het volgende proberen:

[code:1:5a62dc695d]
NSString *testString;
int testValue;

for(i=0; i<array_count; i++)
{
testvalue = [[localArray objectAtIndex:i] intValue];
testString = (NSString *) [localArray objectAtIndex:i];

  if&#40; !testvalue &amp;&amp; &#40;testString != @&quot;00&quot;&#41;&#41;
 &#123; 
     NSLog&#40;@&quot;Failed at integercheck, %@ at %i&quot;, &#91;localArray objectAtIndex&#58;i&#93;, i&#41;; 
     return FALSE; 
  &#125; 

}
[/code:1:5a62dc695d]

je doet dit: [localArray objectAtIndex:i] != @"00" maar het object van de array op indez i moet je eerst definieren als nsstring.

Dus dit zal wel lukken:

[ [localArray objectAtIndex:i] stringValue ] != @“00”

[quote:496beb855e="DeMaccer"]je doet dit: [localArray objectAtIndex:i] != @"00" maar het object van de array op indez i moet je eerst definieren als nsstring.

Dus dit zal wel lukken:

[ [localArray objectAtIndex:i] stringValue ] != @“00”[/quote:496beb855e]

[quote:496beb855e]*** -[NSCFString stringValue]: selector not recognized [self = 0x394540][/quote:496beb855e]
Werkt dus niet

@koen: ik gebruik in 2de stuk || omdat eerst komt als als het true is (dus een integer) en bij de echte code gebruik ik && omdat het daar andersom is

[quote:ddd46dbb95="vikking"][[quote:ddd46dbb95]*** -[NSCFString stringValue]: selector not recognized [self = 0x394540][/quote:ddd46dbb95] Werkt dus niet[/quote:ddd46dbb95] Waarschijnlijk omdat het object al een NSString is, en die kent de functie stringValue niet. Probeer eens de isEqualToString: functie om de twee strings te vergelijken.

Wat gebeurt er als je stap voor stap door de code gaat, wat zijn de waarden voor testValue en testString (zie mijn code voorbeeld)?

Daarnaast dien je in Objective-C objecten nooit tevergelijken met de operators == of !=. Dit omdat deze slechts het adres van het object zal vergelijken en niet de waarde...

Het merendeel van de Foundation classes heeft wel een isEqual of compare implementatie…

[edit]
Wat meer uitwerking
NSString * aString = [NSString stringWithString:@“koe”]; // omslachtig, maar voor de duidelijkheid

if( aString == @“koe” ) { // vergelijkt adressen, niet content
NSLog(@“aString == koe”);
}

if( [aString isEqualToString:@“koe”] ) {
NSLog(@“aString isEqualToString”);
}

if( [aString compare:@“koe”] == NSOrderedSame ) {
NSLog(@“aString compare”);
}

isEqualToString is eigenlijk gewoon geimplementeerd als

  • (BOOL)isEqualToString:(NSString *)other {
    return [self compare:other] == NSOrderedSame;
    }

Je zult zien dat de onderste twee wel werken, en de eerste methode niet.

de reguliere hash methode van NSObject (of geimplementeerd door subclassen) wordt bij isEqual gebruikt. In het geval van NSString zal isEqual ook werken, maar niet altijd een 100% betrouwbare uitkomst geven daar deze gebaseerd is op de hash methode ( -(BOOL)isEqual:(NSObject *)other { return [other hash] == [self hash]; } ) Daar NSString de hash methode implementeert werkt de isEqual methode dus wel, maar niet 100% betrouwbaar, daar hashes niet 100% uniek zijn…

Bij hashes (in de implementatie van NSString) doet de volgorde van de tekens er niet toe
example:
woord: koe
hash: 1054352243
woord: eok
hash: 1054352243

Nog verder uitgewerkt zou je kunnen stellen (for the sake of exercise) dat

myString = [NSString stringWithCString:“koe” encoding:NULL];

if( myString == @“koe” )
door de preprocessor vertaald wordt (@"" is een macro ) naar het volgende
if( myString == [NSString stringWithCString:“koe” encoding:NULL] )

De macro @“koe” returned dus een geheel nieuw object. Door te zeggen dat myString == new object vergelijk je de adressen van de twee objecten, en zul je dus nooit op het gewenste resultaat uitkomen. myString en ook de return value van @“koe” zijn niets meer dan pointers naar een object. In het geval van koe een constant gealloceerd object, maar nogsteeds een object…

@Reflex en Koen: Bedankt voor de uitleg :D, nu werkt het (isEqualToString) Nu nogiets anders: [code:1:796b9f37c0]NSArray * keys = [NSArray arrayWithObjects:@"h", @"m", @"s"];[/code:1:796b9f37c0] zorgt ervoor dat het programma hangt... Zie ik weer iets over het hoofd?

Uit de documentatie ([url=http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/Reference/Reference.html#//apple_ref/occ/clm/NSArray/arrayWithObjects:]link[/url])

[quote:49d1014a26]The argument list is a comma-separated list of objects ending with nil.[/quote:49d1014a26]

het dient dus te zijn:

[code:1:49d1014a26]
NSArray * myArray = [NSArray arrayWithObjects:@"a", @"b", @"c", nil];
[/code:1:49d1014a26]

Whoops, daar heb ik overgelezen, bedankt!

Dan nogiets, in PHP kan je zeer gemakkelijk strings aaneenzetten: [code:1:8c6b1d4350]$string1 = "Hello"; $string2 = " World"; echo $string1 . $string2;[/code:1:8c6b1d4350] Bestaat er iets in die aard voor Cocoa? Het enige dat ik gevonden heb is stringByAppendingString:, maar die is nogal omslachtig als ik iets wil doen als: [code:1:8c6b1d4350][d1s setStringValue:[[[[diffhours stringByAppendingString:@":"] stringByAppendingString:diffminutes] stringByAppendingString:@":"] stringByAppendingString:diffseconds]];[/code:1:8c6b1d4350] Alvast bedankt.

Ik stel toch voor dat je de documentatie gaat lezen van NSString

NSString myString = [NSString stringWithFormat:@"%d:%d:%d", diffhours,diffminutes,diffseconds];

Daarnaast heb je natuurlijk ook de NSDate class voor dit soort grappen…

diffHours is beter dan diffhours als variable name, btw. Ik weet dat het feitelijk niets uitmaakt, maar het komt de leesbaarheid ten goede.

Jah, sry, kben men weg nog een beetje aant zoeke in de handleiding, het is gewoon zoveel :P. Toch bedankt.