Can't seem to get sorting to work


#1

I created a new Xcode project and copied the Asset.h, Asset.m, Employee.h, Employee.m, Person.h, Person.m and main.m from the Chapter 20 project and can’t seem to get the sorting to work. Note: The sleep(100) is still in the code. The output I get is the following: The first Employees array should be sorted by value amount but it is not. The source code files are listed below. Any clues?

[ul]
2011-12-29 15:52:03.545 BMITime[260:707] Employees: (
"<Employee 0: $0 in assets>",
"<Employee 1: $153 in assets>",
"<Employee 2: $119 in assets>",
"<Employee 3: $68 in assets>",
"<Employee 4: $0 in assets>",
"<Employee 5: $136 in assets>",
"<Employee 6: $119 in assets>",
"<Employee 7: $34 in assets>",
"<Employee 8: $0 in assets>",
"<Employee 9: $136 in assets>"
)
2011-12-29 15:52:03.547 BMITime[260:707] Giving up ownership of one employee
2011-12-29 15:52:03.548 BMITime[260:707] allAssets: (
"< Laptop 0: $0, assigned to <Employee 3: $68 in assets> >",
"< Laptop 1: $17, assigned to <Employee 6: $119 in assets> >",
"< Laptop 2: $34, assigned to <Employee 7: $34 in assets> >",
"< Laptop 3: $51, assigned to <Employee 5: $136 in assets> >",
"< Laptop 4: $68, assigned to <Employee 3: $68 in assets> >",
"< Laptop 5: $85, assigned to <Employee 5: $136 in assets> >",
"< Laptop 6: $102, assigned to <Employee 6: $119 in assets> >",
"< Laptop 7: $119, assigned to <Employee 2: $119 in assets> >",
"< Laptop 8: $136, assigned to <Employee 9: $136 in assets> >",
"< Laptop 9: $153, assigned to <Employee 1: $153 in assets> >"
)
2011-12-29 15:52:03.548 BMITime[260:707]
Giving up ownership of arrays
2011-12-29 15:52:03.549 BMITime[260:707] deallocating <Employee 5: $136 in assets>
2011-12-29 15:52:03.549 BMITime[260:707] deallocating < Laptop 3: $51, unassigned >
2011-12-29 15:52:03.550 BMITime[260:707] deallocating < Laptop 5: $85, unassigned >
2011-12-29 15:52:03.578 BMITime[260:707] deallocating <Employee 0: $0 in assets>
2011-12-29 15:52:03.579 BMITime[260:707] deallocating <Employee 1: $153 in assets>
2011-12-29 15:52:03.579 BMITime[260:707] deallocating < Laptop 9: $153, unassigned >
2011-12-29 15:52:03.580 BMITime[260:707] deallocating <Employee 2: $119 in assets>
2011-12-29 15:52:03.580 BMITime[260:707] deallocating < Laptop 7: $119, unassigned >
2011-12-29 15:52:03.581 BMITime[260:707] deallocating <Employee 3: $68 in assets>
2011-12-29 15:52:03.581 BMITime[260:707] deallocating < Laptop 0: $0, unassigned >
2011-12-29 15:52:03.582 BMITime[260:707] deallocating < Laptop 4: $68, unassigned >
2011-12-29 15:52:03.582 BMITime[260:707] deallocating <Employee 4: $0 in assets>
2011-12-29 15:52:03.582 BMITime[260:707] deallocating <Employee 6: $119 in assets>
2011-12-29 15:52:03.583 BMITime[260:707] deallocating < Laptop 1: $17, unassigned >
2011-12-29 15:52:03.583 BMITime[260:707] deallocating < Laptop 6: $102, unassigned >
2011-12-29 15:52:03.584 BMITime[260:707] deallocating <Employee 7: $34 in assets>
2011-12-29 15:52:03.584 BMITime[260:707] deallocating < Laptop 2: $34, unassigned >
2011-12-29 15:52:03.595 BMITime[260:707] deallocating <Employee 8: $0 in assets>
2011-12-29 15:52:03.596 BMITime[260:707] deallocating <Employee 9: $136 in assets>
2011-12-29 15:52:03.596 BMITime[260:707] deallocating < Laptop 8: $136, unassigned >
[/ul]

//
//  Asset.h
//  BMITime
//
//  Created by Gregory Romane on 12/27/11.
//  Copyright (c) 2011 JDSU. All rights reserved.
//
#import <Foundation/Foundation.h>

@class Employee;


@interface Asset : NSObject
{
    NSString *label;
    __weak Employee *holder;
    unsigned int resaleValue;
    
}


@property (strong) NSString *label;
@property (weak) Employee *holder;
@property unsigned int resaleValue;

@end
//
//  Asset.m
//  BMITime
//
//  Created by Gregory Romane on 12/27/11.
//  Copyright (c) 2011 JDSU. All rights reserved.
//

#import "Asset.h"
#import "Employee.h"


@implementation Asset

@synthesize label, resaleValue, holder;


- (NSString *)description
{
    // Is holder non-nil?
    if ([self holder])
    {
        return [NSString stringWithFormat:@"< %@: $%d, assigned to %@ >", 
                [self label], [self resaleValue], [self holder]];
    }
    else
    {
        return [NSString stringWithFormat:@"< %@: $%d, unassigned >", 
                [self label], [self resaleValue]];
        
    }
}

- (void)dealloc
{
    NSLog(@"deallocating %@", self);
}

@end
//
//  Employee.h
//  BMITime
//
//  Created by Gregory Romane on 12/27/11.
//  Copyright (c) 2011 JDSU. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "Person.h"

@class Asset;


@interface Employee : Person
{
    int employeeID;
    NSMutableArray *assets;
}

@property int employeeID;

- (void)addAssetsObject:(Asset *)a;
- (unsigned int)valueOfAssets;

@end
//
//  Employee.m
//  BMITime
//
//  Created by Gregory Romane on 12/27/11.
//  Copyright (c) 2011 JDSU. All rights reserved.
//

#import "Employee.h"
#import "Asset.h"

@implementation Employee

@synthesize employeeID;

- (void)addAssetsObject:(Asset *)a
{
    // Is assets nil?
    if (!assets)
    {
        // Create the array
        assets = [[NSMutableArray alloc] init];
    }
    [assets addObject:a];
    [a setHolder:self];
}

- (unsigned int)valueOfAssets
{
    // Sum up the resale value of the assets
    unsigned int sum = 0;
    
    for (Asset *a in assets)
    {
        sum += [a resaleValue];
    }
    return sum;
}

- (float)bodyMassIndex
{
    float normalBMI = [super bodyMassIndex];
    return normalBMI * 0.9;
}

- (NSString *)description
{
    return [NSString stringWithFormat:@"<Employee %d: $%d in assets>",
            [self employeeID], [self valueOfAssets]];
}

- (void)dealloc
{
    NSLog(@"deallocating %@", self);
}


@end
//
//  Person.h
//  BMITime
//
//  Created by Gregory Romane on 12/27/11.
//  Copyright (c) 2011 JDSU. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface Person : NSObject
{
    // It has two instance variables
    float heightInMeters;
    int weightInKilos;
}

@property float heightInMeters;
@property int weightInKilos;


// This method calculates the Body Mass Index
- (float)bodyMassIndex;

@end
//
//  Person.m
//  BMITime
//
//  Created by Gregory Romane on 12/27/11.
//  Copyright (c) 2011 JDSU. All rights reserved.
//
#import "Person.h"

@implementation Person


@synthesize heightInMeters, weightInKilos;

- (float)bodyMassIndex
{
    float h = [self heightInMeters];
    return [self weightInKilos] / (h * h);
}

@end
//
//  main.m
//  BMITime
//
//  Created by Gregory Romane on 12/27/11.
//  Copyright (c) 2011 JDSU. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "Employee.h"
#import "Asset.h"

int main (int argc, const char * argv[])
{
    
    @autoreleasepool 
    {
        
        // Create an array of Employee objects
        // NSMutableArray *employees = [[NSMutableArray alloc] init];
        NSMutableArray *employees = [NSMutableArray array];
        
        for (int i = 0; i < 10; i++)
        {
            // Create an instance of Employee
            Employee *person = [[Employee alloc] init];
            
            // Give the instance variables interesting values
            [person setWeightInKilos:90 + i];
            [person setHeightInMeters:1.8 - i/10.0];
            [person setEmployeeID:i];
            
            // Put the employee in the employees array
            [employees addObject:person];
        }
        
        // keep track of all assets create to demonstrate weak references
        NSMutableArray *allAssets = [[NSMutableArray alloc] init];
        
        // Create 10 assets
        for (int i = 0; i < 10; i++)
        {
            // Create an asset
            Asset *asset = [[Asset alloc] init];
            
            // Give it an interesting label
            NSString *currentLabel = [NSString stringWithFormat:@"Laptop %d", i];
            [asset setLabel:currentLabel];
            [asset setResaleValue:i * 17];
            
            // Get a random number between 0 and 9 inclusive
            NSUInteger randomIndex = random() % [employees count];
            
            // Find that employee
            Employee *randomEmployee = [employees objectAtIndex:randomIndex];
            // Employee *randomEmployee = [employees objectAtIndex:i];          // tried doing this un-randomly
            
            // Assign the asset to the employee
            [randomEmployee addAssetsObject:asset];
            
            [allAssets addObject:asset];
            
        }
        
        // NSLog(@"Employees: %@", employees);

        
        // sort emplyees aray first by ascending valueOfAssets, then by ascending employeeID's
        NSSortDescriptor *voa = [NSSortDescriptor sortDescriptorWithKey:@"valueOfAssets" ascending:YES];
        NSSortDescriptor *ei = [NSSortDescriptor sortDescriptorWithKey:@"employeeID" ascending:YES];
        [employees sortedArrayUsingDescriptors:[NSArray arrayWithObjects:voa, ei, nil]];
        
        NSLog(@"Employees: %@", employees);
        
        NSLog(@"Giving up ownership of one employee");
        
        [employees removeObjectAtIndex:5];
        
        NSLog(@"allAssets: %@", allAssets);
        
        NSLog(@"\nGiving up ownership of arrays");
        
        allAssets = nil;
        employees = nil;
        
    }
    
    sleep(100);
    return 0;
}

#2

I just checked the Xcode documentation for sortedArrayUsingDescriptors: and it says that the method returns a copy of the array sorted using the descriptors. It doesn’t actually modify the employees array itself.

So, you should be able to assign the expression to a new array and verify that the new array is sorted appropriately.


#3

You are using a method from the base class (NSArray) called “sortedArrayUsingDescriptors”

Since your array is an NSMutableArray, you can use another method on that class called “sortUsingDescriptors” which sorts the mutable array without making a copy.


#4

Just after submitting the code I realized that I should have been calling sortUsingDescriptors instead of the one I used.