这次要讨论的是 Objective-C 的基础框架( Foundation Framework)。
Framework 就是一些类别(classes)、方法(method)、函式 (function)、跟文件(document)的合集。
Framework 通常是程式设计人员,常常会用到的一些功能,因为太常被使用,所以就被开发成 Framework,让做这些事情,有一个共同的方法与标准。可以想见,写 Framework 的人,通常是高手,程式码的品质比较高,考虑的也比较周延。当然你也可以写自己的 Framewok,给别人用,或是卖给别人,常见的有 2D 或是 3D Engine,其实 Engine 也就是 Framework,不过听起来更响亮一些。
Foundation Framework 包含的主题有:
- 基本物件类别,包括数值物件、字串物件、阵列、字典、及集合。
- 记忆体管理。
- 档案管理。
(一) 基本物件类别:
(1) 基本物件类别
- 数值物件(Number Object)
- 数值物件是用 Objective-C 的类别,把基本的数值型态,如 int、float、double 等,用类别包装起来。之所以这么做,是因为物件集合,所存放的内容,只能是个物件,而不能是机本型别。另外一个理由,就是记忆体管理。
- 这里举例,用 NSNumber 来存放 int, long, char, float 跟 double,然后再把 NSNumber 内存放的数值取出来。
1: #import
2:
3: int main (int argc, const char * argv[])
4: {
5: NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
6:
7: NSNumber *intNumber, *longNumber, *charNumber, *floatNumber, *doubleNumber;
8:
9: // integer value
10:
11: intNumber = [NSNumber numberWithInt: 100];
12: NSLog(@"%i", [intNumber integerValue]);
13:
14: // long value
15:
16: longNumber =[NSNumber numberWithLong: 0xabcdef];
17: NSLog(@"%lx", [longNumber longValue]);
18:
19: // char value
20:
21: charNumber = [NSNumber numberWithChar:'X'];
22: NSLog(@"%c", [charNumber charValue]);
23:
24: // float value
25:
26: floatNumber = [NSNumber numberWithFloat: 100.0];
27: NSLog(@"%g", [floatNumber floatValue]);
28:
29: // double value
30:
31: doubleNumber = [NSNumber numberWithDouble: 12345e15];
32: NSLog(@"%lg", [doubleNumber doubleValue]);
33:
34: // test two number for equality
35:
36: if ([intNumber isEqualToNumber: floatNumber] == YES)
37: NSLog(@"Number are equal");
38: else
39: NSLog(@"Number are not equal");
40:
41: // test if one number is <, ==, or > second number
42:
43: if ([intNumber compare: floatNumber] == NSOrderedAscending)
44: NSLog(@"First number is less than second");
45:
46: NSString *str = @"Programming is fun";
47: NSLog(@"%@", str);
48:
49: NSLog(@"%@", intNumber);
50: NSLog(@"%@", longNumber);
51: NSLog(@"%@", charNumber);
52: NSLog(@"%@", floatNumber);
53: NSLog(@"%@", doubleNumber);
54:
55: [pool drain];
56: return 0;
57: }
58:
- 执行结果
- 字串物件(String Object)
- 字串物件可以类比成 C++ STL 的 std::string,使用字串物件的好处是可以避免 NULL pointer 所造成的 access violation。
- 特别注意,Foundation Framework 提供 nonmutable 跟 mutable 两种字串类别物件。这个例子展示了常见的字串处理,例如取得 sub string,搜寻,置换等等。
1: #import
2:
3: int main (int argc, const char * argv[])
4: {
5: NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
6: NSString *str1 = @"This is string A";
7: NSString *search, *replace;
8: NSMutableString *mstr;
9: NSRange substr;
10:
11: // create a mutable string from nonumtable
12:
13: mstr = [NSMutableString stringWithString: str1];
14: NSLog(@"%@", mstr);
15:
16: // Insert characters
17:
18: [mstr insertString: @" mutable" atIndex: 7];
19: NSLog(@"%@", mstr);
20:
21: // Effective concatentation if insert at end
22:
23: [mstr insertString: @" and string B" atIndex: [mstr length]];
24: NSLog(@"%@", mstr);
25:
26:
27: // Or can use appendString directly
28:
29: [mstr appendString: @" and string C"];
30: NSLog(@"%@", mstr);
31:
32: // Delete substring based on range
33:
34: [mstr deleteCharactersInRange: NSMakeRange(16, 13)];
35: NSLog(@"%@", mstr);
36:
37: // Find range first and then use it for deletion
38:
39: substr = [mstr rangeOfString: @"string B and "];
40: if (substr.location != NSNotFound)
41: {
42: [mstr deleteCharactersInRange: substr];
43: NSLog(@"%@", mstr);
44: }
45:
46: // Set the mutable string directly
47:
48: [mstr setString: @"This is string A"];
49: NSLog(@"%@", mstr);
50:
51: // Now let's replace a range of chars with another
52:
53: [mstr replaceCharactersInRange:NSMakeRange(8, 8) withString:@"a mutable string"];
54: NSLog(@"%@", mstr);
55:
56: // Search and replace
57:
58: search = @"This is";
59: replace = @"An example of";
60:
61: substr = [mstr rangeOfString: search];
62: if (substr.location != NSNotFound)
63: {
64: [mstr replaceCharactersInRange: substr withString: replace];
65: NSLog(@"%@", mstr);
66: }
67:
68: // Search and replace all occurrences
69:
70: search = @"a";
71: replace = @"X";
72:
73: substr = [mstr rangeOfString: search];
74: while (substr.location != NSNotFound)
75: {
76: [mstr replaceCharactersInRange:substr withString: replace];
77: substr = [mstr rangeOfString: search];
78: }
79:
80: NSLog(@"%@", mstr);
81:
82: [pool drain];
83: return 0;
84: }
85:
- 执行结果
- 阵列物件(Array Object)
- 阵列物件,就像是 C++ STL 的 std::vector,阵列物件内可以放任意个数的物件,不过 Objective-C 的阵列物件,专门是用来放物件的。在还没对 Objective-C 熟悉之前,建议是不要 Objective-C 跟 C++ 的语法混用,也就是说,不建议在 Objective-C 用 template 的语法。
- 举了一个例子,用阵列物件来存放小于 50 的质数
1: #import
2:
3: #define MAXPRIME 50
4:
5: int main (int argc, const char * argv[])
6: {
7: NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
8:
9: int i, p, prevPrime;
10: BOOL isPrime;
11:
12: // Createa an array to store the prime numbers
13:
14: NSMutableArray *primes = [NSMutableArray arrayWithCapacity: 20];
15:
16: // Store the first two prims (2 and 3) into the array
17:
18: [primes addObject: [NSNumber numberWithInteger: 2]];
19: [primes addObject: [NSNumber numberWithInteger: 3]];
20:
21: // Calculate the remaining primes
22:
23: for (p = 5; p <= MAXPRIME; p += 2)
24: {
25: // we're testing to see if p is prime
26:
27: isPrime = YES;
28:
29: i = 1;
30: do {
31: prevPrime = [[primes objectAtIndex: i] integerValue];
32:
33: if (p % prevPrime == 0)
34: isPrime = NO;
35:
36: i++;
37: } while (isPrime == YES && p / prevPrime >= prevPrime);
38:
39: if (isPrime)
40: [primes addObject: [NSNumber numberWithInteger: p]];
41: }
42:
43: // display the result
44:
45: for (i = 0; i < [primes count]; i++)
46: {
47: NSLog(@"%li", (long) [[primes objectAtIndex: i] integerValue]);
48: }
49:
50: [pool drain];
51: return 0;
52: }
53:
- 执行的结果如下图
- 字典物件(Dictionary Object)
- 字典物件,相当于 C++ STL std::map,每次新增一对 (key, value) 然后,你可以用 key 跟 字典物件查询 value。
- 举了一个例子,key 跟 value 都是 NSString 物件,当然可以放任意的物件。
1: #import
2:
3: int main (int argc, const char * argv[])
4: {
5: NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
6:
7: NSMutableDictionary *glossary = [[NSMutableDictionary alloc] init];
8:
9: [glossary setObject: @"A class defined so other classes can inherit from it."
10: forKey: @"abstract class"];
11:
12: [glossary setObject: @"To implement all the methods defined in a protocol"
13: forKey: @"adopt"];
14:
15: [glossary setObject: @"Storing an object for later use"
16: forKey: @"archiving"];
17:
18: // Retrieve and display them
19:
20: NSLog(@"abstract class: %@", [glossary objectForKey: @"abstract class"]);
21: NSLog(@"adopt: %@", [glossary objectForKey: @"adopt"]);
22: NSLog(@"archiving: %@", [glossary objectForKey: @"archiving"]);
23:
24: // Print all key-value pairs from the dicionary
25:
26: for (NSString *key in glossary)
27: {
28: NSLog(@"%@:%@", key, [glossary objectForKey: key]);
29: }
30:
31: [glossary release];
32:
33: [pool drain];
34: return 0;
35: }
36:
- 执行的结果如下图:
- 集合物件(Set Object)
- 集合物件相当于 C++ STL std::set,你可以这样想,就是字典物件,只放 key。集合物件常常用来侦测特定的事件(Event ID),或是特定的错误(Error Code)是否发生过。
- 举的例子很简单,建立两个集合,帮集合新增及删除元素,求两个集合的交集及联集。其中用到类目(class category)来帮集合新增一个操作 print。
1: #import
2:
3: // Create an integer number
4: #define INTOBJ(v) [NSNumber numberWithInteger: v]
5:
6: // Add print method to NSSet with the Printing category
7: @interface NSSet (Printing)
8: -(void) print;
9: @end
10:
11: @implementation NSSet (Printing)
12:
13: -(void) print
14: {
15: printf("{");
16:
17: for (NSNumber *element in self)
18: printf(" %li ", (long) [element integerValue]);
19:
20: printf("}/n");
21: }
22:
23: @end
24:
25:
26: int main (int argc, const char * argv[])
27: {
28: NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
29:
30: NSMutableSet *set1 = [NSMutableSet setWithObjects:
31: INTOBJ(1), INTOBJ(3), INTOBJ(5), INTOBJ(10), nil];
32:
33: NSMutableSet *set2 = [NSMutableSet setWithObjects:
34: INTOBJ(-5), INTOBJ(100), INTOBJ(3), INTOBJ(5), nil];
35:
36: NSMutableSet *set3 = [NSMutableSet setWithObjects:
37: INTOBJ(12), INTOBJ(200), INTOBJ(3), nil];
38:
39: NSLog(@"set1: ");
40: [set1 print];
41:
42: NSLog(@"set2: ");
43: [set2 print];
44:
45: // Equality test
46: if ([set1 isEqualToSet: set2] == YES)
47: NSLog(@"set1 equal set2");
48: else
49: NSLog(@"set1 is not equal set2");
50:
51: // Membership test
52:
53: if ([set1 containsObject: INTOBJ(10)] == YES)
54: NSLog(@"set1 contains 10");
55: else
56: NSLog(@"set1 does not contain 10");
57:
58: if ([set2 containsObject: INTOBJ(10)] == YES)
59: NSLog(@"set2 contains 10");
60: else
61: NSLog(@"set2 does not contain 10");
62:
63: // add and remove objects from mutable set set1
64:
65: [set1 addObject: INTOBJ(4)];
66: [set1 removeObject:INTOBJ(10)];
67:
68: NSLog(@"set1 after adding 4 and removing 10: ");
69: [set1 print];
70:
71: // get intersection of two sets
72:
73: [set1 intersectSet: set2];
74: NSLog(@"set1 intersect set2: ");
75: [set1 print];
76:
77: // union of two sets
78:
79: [set1 unionSet: set3];
80: NSLog(@"set1 union set3: ");
81: [set1 print];
82:
83:
84:
85:
86: [pool drain];
87: return 0;
88: }
89:
- 执行结果如下图:
这一篇部落格已经太长了,让我们在下一篇,继续讨论 Objective-C 记忆体管理,及档案处理。