category 是Objective-C 里面最常用到的功能之一。category 可以为已经存在的类增加方法,而不需要增加一个子类。而且,我们可以在不知道某个类内部实现的情况下,为该类增加方法。如果我们想增加某个框架(framework)中的类的方法,category 就非常有效。比如,如果想在NSString 上增加一个方法来判断它是否是有效的 URL,那么就可以这样做:
[java] view plaincopy
- @interface NSString (hello)
- - (BOOL) isURL;
- @end
是不是觉得与类的定义非常像,确实,就是category 没有父类,而且后面要跟括号里面写category 的名字,名字可以随便取。下面是刚刚 isURL 的实现:
[java] view plaincopy
- @implementation NSString(hello)
- - (BOOL) isURL{
- if( [self hasPrefix:@"http://"] )
- return YES;
- else
- return NO;
- }
- @end
现在就可以在任何NSString类对象上调用这个方法了。下面是一个调用的例子:
[java] view plaincopy
- NSString* str1 = @"http://www.blog.csdn.net/iukey";
- NSString* str2 = @"刘伟Lewis";
- if([str1 isURL])
- NSLog(@"str1 is a URL");
- if([str2 isURL])
- NSLog(@"str2 is a URL");
[java] view plaincopy
- #import "类名.h"
- @interface 类名(类别名)
- //新方法的声明
- @end
[java] view plaincopy
- #import "类名类别名.h"
- @interface 类名(类别名)
- //新的实现方法
- @end
注意:类别并不能为类声明新的实例变量,他只包含方法。然而在类作用域内所有实例变量,都能被这些类别访问。他们包括为类声明的所有的实例变量,甚至那些被@private 修饰的变量。可以为一个类添加多个类别,但每个类别名必须不同,而且每个类别都必须声明并实现一套不同的方法。
[java] view plaincopy
- // GrayScale.h
- // XOGameFrame
- //
- // Created by song on 11-1-12.
- // Copyright 2011 __MyCompanyName__. All rights reserved.
- //
- #import <Foundation/Foundation.h>
- @interface UIImage (grayscale)
- - (UIImage *)convertToGrayscale ;
- @end
[java] view plaincopy
- //
- // GrayScale.m
- // XOGameFrame
- //
- // Created by song on 11-1-12.
- // Copyright 2011 __MyCompanyName__. All rights reserved.
- //
- #import "GrayScale.h"
- @implementation UIImage (grayscale)
- typedef enum {
- ALPHA = 0,
- BLUE = 1,
- GREEN = 2,
- RED = 3
- } PIXELS;
- - (UIImage *)convertToGrayscale {
- CGSize size = [self size];
- int width = size.width;
- int height = size.height;
- // the pixels will be painted to this array
- uint32_t *pixels = (uint32_t *) malloc(width * height * sizeof(uint32_t));
- // clear the pixels so any transparency is preserved
- memset(pixels, 0, width * height * sizeof(uint32_t));
- CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
- // create a context with RGBA pixels
- CGContextRef context = CGBitmapContextCreate(pixels, width, height, 8, width * sizeof(uint32_t), colorSpace,
- kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedLast);
- // paint the bitmap to our context which will fill in the pixels array
- CGContextDrawImage(context, CGRectMake(0, 0, width, height), [self CGImage]);
- for(int y = 0; y < height; y++) {
- for(int x = 0; x < width; x++) {
- uint8_t *rgbaPixel = (uint8_t *) &pixels[y * width + x];
- // convert to grayscale using recommended method: http://en.wikipedia.org/wiki/Grayscale#Converting_color_to_grayscale
- uint32_t gray = 0.3 * rgbaPixel[RED] + 0.59 * rgbaPixel[GREEN] + 0.11 * rgbaPixel[BLUE];
- // set the pixels to gray
- rgbaPixel[RED] = gray;
- rgbaPixel[GREEN] = gray;
- rgbaPixel[BLUE] = gray;
- }
- }
- // create a new CGImageRef from our context with the modified pixels
- CGImageRef image = CGBitmapContextCreateImage(context);
- // we're done with the context, color space, and pixels
- CGContextRelease(context);
- CGColorSpaceRelease(colorSpace);
- free(pixels);
- // make a new UIImage to return
- UIImage *resultUIImage = [UIImage imageWithCGImage:image];
- // we're done with image now too
- CGImageRelease(image);
- return resultUIImage;
- }
- @end
[cpp] view plaincopy
- #import <Foundation/Foundation.h>
- /*
- 定义分类的过程大致可分为以下几个步骤:
- 第一步、创建一个带有接口的新文件,即创建已有类
- 第二步、在新文件中添加需要扩展的方法及方法的实现,即需要添加的分类
- */
- //NSString 表示将要添加分类的类名称,该类必须是已存在的。
- //CamelCase 是为类添加的方法名称。
- //只能添加方法,不能添加变量。
- //头文件命名惯例:ClassName+CategoryName.h
- @interface NSString (CamelCase)
- -(NSString*) camelCaseString;
- @end
- @implementation NSString (CamelCase)
- -(NSString*) camelCaseString
- {
- //调用NSString的内部方法获取驼峰字符串。
- //self指向被添加分类的类。
- NSString *castr = [self capitalizedString];
- //创建数组来过滤掉空格, 通过分隔符对字符进行组合。
- NSArray *array = [castr componentsSeparatedByCharactersInSet:
- [NSCharacterSet whitespaceCharacterSet]];
- //把数组的字符输出
- NSString *output = @"";
- for(NSString *word in array)
- {
- output = [output stringByAppendingString:word];
- }
- return output;
- }
- @end
- int main (int argc, const char * argv[])
- {
- NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
- NSString *str = @"My name is bill.";
- NSLog(@"%@", str);
- str = [str camelCaseString];
- NSLog(@"%@", str);
- [pool drain];
- return 0;
- }
[plain] view plaincopy
- @interface MyClass : NSObject
- - (float)value;
- @end
- @interface MyClass () { //注意此处:扩展
- float value;
- }
- - (void)setValue:(float)newValue;
- @end
- @implementation MyClass
- - (float)value {
- return value;
- }
- - (void)setValue:(float)newValue {
- value = newValue;
- }
- @end