Cocoa lernen - Schritt für Schritt
Cocoa lernen - Schritt für Schritt
Ein Array sortieren

Möchte man ein Array sortieren, mit Bubblesort oder einen anderen Sortieralgorithmus, ist es dafür immer zwingen notwendig, verschiedene Objekte innerhalb des Arrays gegeneinander auszutauschen. Für ein NSMutableArray erledigt das die Methode exchangeObjectAtIndex, mit der tatsächlich zwei Objekte an ihren Positionen getauscht werden können.
NSMutableArray *myArray;
myArray = [NSMutableArray arrayWithCapacity:
3];

[myArray addObject:
@"Alpha"];
[myArray addObject:
@"Beta"];
[myArray addObject:
@"Gamma"];

[myArray exchangeObjectAtIndex:
2 withObjectAtIndex:0];

for(int i = 0; i < [myArray count]; i++)
{
    NSLog(
@"Index %d ist %@", i, [myArray objectAtIndex:i]);
}
stacks_image_9FA40917-5CFE-4C53-B8ED-A26E103E0BCF
Möchte man hingegen mit einer Anweisung ein Objekt innerhalb des Arrays ersetzten, geht das mit der Methode replaceObjectAtIndex.
[myArray replaceObjectAtIndex:1 withObject:@"Delta"];
Mit diesen Methode sollte es jetzt kein Problem mehr darstellen, das Array nach belieben zu manipulieren. Möchte man ein NSMutableArray tatsächlich sortieren, muss man sich aber nicht die Mühe machen, das selbst zu programmieren. Die Klasse hat eigene Methode, um ihren Inhalt nahezu automatisch zu sortieren. Die einfachste ist sortUsingSelector
NSMutableArray *myArray;
myArray = [NSMutableArray arrayWithCapacity:
3];

[myArray addObject:
@"Gamma"];
[myArray addObject:
@"Alpha"];
[myArray addObject:
@"Beta"];

[myArray sortUsingSelector:
@selector(compare:)];

for(int i = 0; i < [myArray count]; i++)
{
    NSLog(
@"Index %d ist %@", i, [myArray objectAtIndex:i]);
}
Durch den Aufruf von sortUsingSelector wird ein Array mit Zeichenketten automatisch aufsteigend sortiert, das gleiche gilt für eine Array mit Zahlen vom Typ NSNumber. Auch so ein Array würde aufsteigend sortiert.

Möchte man hingegen das Array ganz anders sortieren, vielleicht wenn Objekte vom Typ Person im Array sind und man nur nach den Nachnamen sortieren möchte, erweisen sich eigene Sortierfunktionen als sinnvoll. Wie in dieser Funktion verglichen wird, ist dann ganz dem Programmierer überlassen, wichtig ist nur, dass die Rückgabewerte einer solchen Funktion einem NSComparisonResult entsprechen.
NSNumber *n1 = [NSNumber numberWithInt:123];
NSNumber *n2 = [NSNumber numberWithInt:
38];
NSNumber *n3 = [NSNumber numberWithInt:
7];
NSNumber *n4 = [NSNumber numberWithInt:
45];
NSNumber *n5 = [NSNumber numberWithInt:
99];
NSNumber *n6 = [NSNumber numberWithInt:
71];

NSMutableArray *myArray;
myArray = [NSMutableArray arrayWithObjects:n1,n2,n3,n4,n5,n6,
nil];

[myArray sortUsingFunction:myCompareFunction context:
NULL];

for(int i = 0; i < [myArray count]; i++)
{
    NSLog(
@"Index %d ist %d",i, [[myArray objectAtIndex:i] intValue] );
}
Die Funktion myCompareFunction, in der jeweils zwei Objekte des Array verglichen werden, könnte für eine Sortierung dieses NSMutableArray so aussehen:
int myCompareFunction(id val1,id val2,void *context)
{
    int nVal1 = [val1 intValue];
    int nVal2 = [val2 intValue];
    if(nVal1 < nVal2)
    {
        return NSOrderedAscending ;
    }
    else if(nVal1 > nVal2)
    {
        return NSOrderedDescending;
    }
    return NSOrderedSame;
}
stacks_image_F46C4CF1-79C9-4D32-9520-BAECA5D0A59E
Diese Funktion sortiert das Array auch aufsteigend, nichts was man nicht auch durch einen sortUsingSelector erreichen könnte. Will man aber die Sortierrichtung umkehren, reicht es, die Rückgabewerte in den beiden Blöcken der if-Struktur zu vertauschen.

Eine etwas elegantere Lösung bietet hingegen der context, der mit in die Funktion übergeben werden kann. Dieser ermöglicht es, von aussen eine Sortierrichtung anzugeben. Im folgenden Beispiel soll der context ein NSString sein.
int myCompareFunction(id val1,id val2,void *context)
{
    int nVal1 = [val1 intValue];
    int nVal2 = [val2 intValue];

    NSString *order = context;

    if([order compare:@"auf"] == NSOrderedSame)
    {
        if(nVal1 < nVal2)
        {
            return NSOrderedAscending;
        }
            else if(nVal1 > nVal2)
        {
            return NSOrderedDescending;
        }
    }
    else
    {
        if(nVal1 < nVal2)
        {
            return NSOrderedDescending;
        }
        else if(nVal1 > nVal2)
        {
            return NSOrderedAscending;
   
    }
    }
    return NSOrderedSame;
}
Der Aufruf einer solchen Sortierfunktion wäre dann wie folgt:
[myArray sortUsingFunction:myCompareFunction context:@"ab"];
Möchte man das Array weiterhin aufsteigend sortieren, ist die richtige Anweisung:
[myArray sortUsingFunction:myCompareFunction context:@"auf"];