Adding Object Subscripting Support to Your Classes

Traditionally,

NSString *constkFirstNameKey =@"firstName";

NSString *constkLastNameKey =@"lastName";


NSMutableDictionary *dictionary= [[NSMutableDictionaryalloc] init];


[dictionary setValue:@"Tim"forKey:kFirstNameKey];

[dictionary setValue:@"Cook"forKey:kLastNameKey];


__unused NSString *firstName= [dictionaryvalueForKey:kFirstNameKey];

__unused NSString *lastName= [dictionaryvalueForKey:kLastNameKey];



But with all the advances in the LLVM compiler, this code can now be shortened to this:

NSString *constkFirstNameKey =@"firstName";

NSString *constkLastNameKey =@"lastName";


NSDictionary *dictionary= @{

                             kFirstNameKey : @"Tim",

                             kLastNameKey : @"Cook",

                             };


__unused NSString *firstName= dictionary[kFirstNameKey];

__unused NSString *lastName= dictionary[kLastNameKey];





Subscripting by key

With this, you can set the value for a specific key inside an object, just like you would in a dictionary. You can also access/read-from values inside the object by providing the key.

Subscripting by index

As with arrays, you can set/get values inside the object by providing an index to that object. This makes sense for array-like classes where the elements lie in a natural order that can be represented by an index.



A:

For the first example, we are going to look at subscripting by key. To do this, we are going to create a class named Person with a firstName and a lastName. Then we are going to allow the programmer to change the first and last names by simply providing the keys to those properties.

In order to support subscripting by key on your own classes, you must implement the following two methods on your classand put the method signatures in your class’s header file; otherwise, the compiler won’t know that your class supports subscripting by key.

#import <Foundation/Foundation.h>


/* We will use these as the keys to our firstName and lastName

 properties so that if our firstName and lastName properties' names

 change in the future in the implementation, we won't break anything

 and our class will still work, as we can simply change the value of

 these constants inside our implementation file */

extern NSString *constkFirstNameKey;

extern NSString *constkLastNameKey;


@interfacePerson : NSObject


@property (nonatomic,copy) NSString *firstName;

@property (nonatomic,copy) NSString *lastName;


- (id)objectForKeyedSubscript:(id<NSCopying>)paramKey;

- (void)setObject:(id)paramObjectforKeyedSubscript:(id<NSCopying>)paramKey;


@end


//

The objectForKeyedSubscript: method will be called on your class whenever the programmer provides a key and wants to read the value of that key in your class.

To complement this method, the setObject:forKeyedSubscript: method will be called on your class whenever the programmer wants to set the value for a specified key.


#import "Person.h"


NSString *constkFirstNameKey =@"firstName";

NSString *constkLastNameKey =@"lastName";


@implementation Person


- (id)objectForKeyedSubscript:(id<NSCopying>)paramKey{


    NSObject<NSCopying>*keyAsObject = (NSObject<NSCopying>*)paramKey;

    if ([keyAsObjectisKindOfClass:[NSStringclass]]){

        NSString *keyAsString= (NSString*)keyAsObject;

        if ([keyAsStringisEqualToString:kFirstNameKey] ||

            [keyAsString isEqualToString:kLastNameKey]){

            return [selfvalueForKey:keyAsString];

        }

    }


    return nil;

}


- (void)setObject:(id)paramObjectforKeyedSubscript:(id<NSCopying>)paramKey{

    NSObject<NSCopying>*keyAsObject = (NSObject<NSCopying>*)paramKey;

    if ([keyAsObjectisKindOfClass:[NSStringclass]]){

        NSString *keyAsString= (NSString*)keyAsObject;

        if ([keyAsStringisEqualToString:kFirstNameKey] ||

            [keyAsString isEqualToString:kLastNameKey]){

            [self setValue:paramObjectforKey:keyAsString];

        }

    }

}


@end






// elsewhere

Person *person= [Personnew];

person[kFirstNameKey] = @"Tim";

person[kLastNameKey] = @"Cook";

__unused NSString *firstName= person[kFirstNameKey];

__unused NSString *lastName= person[kLastNameKey];


==

Person *person= [Personnew];

person.firstName =@"Tim";

person.lastName =@"Cook";

__unused NSString *firstName= person.firstName;

__unused NSString *lastName= person.lastName;




B:

// headers file

- (id)objectAtIndexedSubscript:(NSUInteger)paramIndex;

- (void)setObject:(id)paramObjectatIndexedSubscript:(NSUInteger)paramIndex;



- (id)objectAtIndexedSubscript:(NSUInteger)paramIndex{


    switch (paramIndex){

        case 0:{

            return self.firstName;

            break;

        }

        case 1:{

            return self.lastName;

            break;

        }

        default:{

            [NSException raise:@"Invalid index"format:nil];

        }

    }


    return nil;

}


- (void)setObject:(id)paramObjectatIndexedSubscript:(NSUInteger)paramIndex{

    switch (paramIndex){

        case 0:{

            self.firstName= paramObject;

            break;

        }

        case 1:{

            self.lastName= paramObject;

            break;

        }

        default:{

            [NSException raise:@"Invalid index"format:nil];

        }

    }

}






Now we can test out what we’ve written so far, like so:

Person *person= [Personnew];

person[kFirstNameKey] = @"Tim";

person[kLastNameKey] = @"Cook";

NSString *firstNameByKey= person[kFirstNameKey];

NSString *lastNameByKey= person[kLastNameKey];


NSString *firstNameByIndex= person[0];

NSString *lastNameByIndex= person[1];


if ([firstNameByKeyisEqualToString:firstNameByIndex]&&

    [lastNameByKey isEqualToString:lastNameByIndex]){

    NSLog(@"Success");

} else {

    NSLog(@"Something is not right");

}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值