2012年5月19日 星期六

Allocating and Returning Objects from Methods

refer to page 163 of  Addison Wesley - Programming.in.ObjectiveC.2.0.2nd (2009)

-(Fraction *) add: (Fraction *) f
{
// To add two fractions:
// a/b + c/d = ((a*d) + (b*c)) / (b * d)
// result will store the result of the addition
Fraction   *result = [[Fraction alloc] init];
int        resultNum, resultDenom;
resultNum = numerator * f.denominator +
denominator * f.numerator;
resultDenom = denominator * f.denominator;
[result setTo: resultNum over: resultDenom];
[result reduce];
return result;
}

int main (int argc, char *argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Fraction *aFraction = [[Fraction alloc] init];
Fraction *bFraction = [[Fraction alloc] init];
Fraction *resultFraction;
[aFraction setTo: 1 over: 4];   // set 1st fraction to 1/4
[bFraction setTo: 1 over: 2];   // set 2nd fraction to 1/2
[aFraction print];
NSLog (@ ” + ” );
[bFraction print];
NSLog (@ ” = ” );
resultFaction = [aFraction add: bFraction];   // <== 創建出resultFraction 並回傳
[resultFraction print];
// This time give the result directly to print
// memory leakage here!
[[aFraction add: bFraction] print];  // 創建出來給print 用的result instance  似乎沒有release
[aFraction release];
[bFraction release];
[resultFraction release]; // <== 最後要記得  release 在add 上所創出來的 resultFraction instance
[pool drain];
return 0;
}

另外一個例子來說明如何解決
int main (int argc, char *argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Fraction *aFraction = [[Fraction alloc] init];
Fraction *sum = [[Fraction alloc] init], *sum2;
int i, n, pow2;
[sum setTo: 0 over: 1]; // set 1st fraction to 0
NSLog (@ ” Enter your value for n: ” );
scanf ( “ %i ” , &n);
pow2 = 2;
for (i = 1; i <= n; ++i) {
[aFraction setTo: 1 over: pow2];
sum2 = [sum add: aFraction];
[sum release];  // release previous sum, 先釋放之前的
sum = sum2;   //然後指標指向現在創立的
pow2 *= 2;
}
NSLog (@ ” After %i iterations, the sum is %g ” , n, [sum convertToNum]);
[aFraction release];
[sum release];
[pool drain];
return 0;
}

More on Classes (include property and synthesis)

refer to Addison Wesley - Programming.in.ObjectiveC.2.0.2nd (2009)
Fraction.h

@interface Fraction : NSObject
{
int numerator;
int denominator;
}
@property int numerator, denominator;
-(void)    print;
-(void)    setTo: (int) n over: (int) d;
-(double)  convertToNum;
-(int) set: (int) n: (int) d;   // without argument name
-(void) add: (Fraction *) f;
@end

Fraction.m

#import “ Fraction.h ”
@implementation Fraction
@synthesize numerator, denominator;
// 使用 synthesize 去自動產生 numerator , denominator , setNumerator: , and  setDenominator
/* 在Objective-C 2.0以前,如果我們要取用或設定value的內容,就得自已宣告這兩個函式方法並實作他們的功能。現在我們只要使用@property就等於宣告了上述的函式。接下來,只要在類別的.m檔裡加入
@synthesize value
編譯器就會自動把上述兩個函式的功能補完。
此處參考 http://bonjouryentinglai.wordpress.com/2009/12/30/objective-c%E9%9A%A8%E6%89%8B%E7%AD%86%E8%A8%98-i%EF%BC%9Aproperty/

假如我們宣告了一個MyClass的物件myObject,當我們要取用或設定value這個資料時,就可以用:
[myObject value]; //getter取值
[myObject setValue: some Value];//setter設值
另外,Property也提供了一些設定選項讓我們進一步的調整資料成員的特性,語法是:
@property(attribute1, attribute2…)float value;
這些attribute包括:
readonly-唯讀,只能讀取而不能設定值(不能用setXXXX的函式)。
readwrite-可讀可寫(預設)。
assign-在設值時替換新舊資料(預設)。
retain-在設值時retain新的資料,release舊資料。
copy-在設值時copy一份新資料,release舊資料。
nonatomic-預設為atomic。

*/

-(void) print
{
NSLog (@ ” %i/%i ” , numerator, denominator);
}
-(double) convertToNum
{
if (denominator != 0)
return (double) numerator / denominator;
else
return 1.0;
}
-(void) setTo: (int) n over: (int) d
{
numerator = n;
denominator = d;
}
- (void) add: (Fraction *) f
{
// To add two fractions:
// a/b + c/d = ((a*d) + (b*c)) / (b * d)
numerator = numerator * f.denominator
+ denominator * f.numerator;
denominator = denominator * f.denominator;
}

- (void) reduce
{
int  u = numerator;
int  v = denominator;

int  temp;
static int pageCount ;  
//使用靜態變數,數值將會被保留到下次呼叫時,因此初值將會被自動設為0
pageCount += 1;

while (v != 0) {
temp = u % v;
u = v;
v = temp;
}
numerator /= u;
denominator /= u;
}
@end

FractionTest.m

#import “ Fraction.h ”
int main (int argc, char *argv[])
{
Fraction *aFraction = [[Fraction alloc] init];
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
[aFraction setTo: 100 over: 200];
[aFraction print];
[aFraction setTo: 1 over: 3];
//[aFraction set: 1 : 3];
[aFraction pr nt];
[aFraction rele se];


Fraction *cFraction = [[Fraction alloc] init];
Fraction *bFraction = [[Fraction alloc] init];
// Set two fractions to 1/4 and 1/2 and add them together
[cFraction setTo: 1 over: 4];
[bFraction setTo: 1 over: 2];

[cFraction add: bFraction];
[cFraction print];
[cFraction release];
[bFraction release];


[pool drain];
return 0;
}

single character

refer to  Addison Wesley - Programming.in.ObjectiveC.2.0.2nd (2009)

int main (int argc, char *argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
char c;
NSLog (@ ” Enter a single character: ” );
scanf ( “ %c ” , &c);
if ( (c >=  ‘ a ’ && c <=  ‘ z ’ ) || (c >=  ‘ A ’ && c <=  ‘ Z ’ ) ) // A~Z, a~z
NSLog (@ ” It ’ s an alphabetic character. ” );
else if ( c >=  ‘ 0 ’ && c <=  ‘ 9 ’ ) // 0~9
NSLog (@ ” It ’ s a digit. ” );
else
NSLog (@ ” It ’ s a special character. ” );
[pool drain];
return 0;
}

Bitwise operators in ObjectC

refer to Addison Wesley - Programming.in.ObjectiveC.2.0.2nd (2009)

int main (int argc, char *argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
unsigned int w1 = 0xA0A0A0A0, w2 = 0xFFFF0000,
w3 = 0x00007777;
NSLog (@ ” %x %x %x ” , w1 & w2, w1 | w2, w1 ^ w2);
NSLog (@ ” %x %x %x ” , ~w1, ~w2, ~w3);
NSLog (@ ” %x %x %x ” , w1 ^ w1, w1 & ~w2, w1 | w2 | w3);
NSLog (@ ” %x %x ” , w1 | w2 & w3, w1 | w2 & ~w3);
NSLog (@ ” %x %x ” , ~(~w1 & ~w2), ~(~w1 | ~w2));
[pool drain];
return 0;
}

a0a00000 ffffa0a0 5f5fa0a0
5f5f5f5f ffff ffff8888
0 a0a0 fffff7f7
a0a0a0a0 ffffa0a0
ffffa0a0 a0a00000

Basic conversions in Objective-C

 refer to Addison Wesley - Programming.in.ObjectiveC.2.0.2nd (2009)

int main (int argc, char *argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
float  f1 = 123.125, f2;
int    i1, i2 = -150;
i1 = f1;   // floating to integer conversion
NSLog (@ ” %f assigned to an int produces %i ” , f1, i1);
f1 = i2;   // integer to floating conversion
NSLog (@ ” %i assigned to a float produces %f ” , i2, f1);
f1 = i2 / 100;   // integer divided by integer
NSLog (@ ” %i divided by 100 produces %f ” , i2, f1);
f2 = i2 / 100.0;   // integer divided by a float
NSLog (@ ” %i divided by 100.0 produces %f ” , i2, f2);
f2 = (float) i2 / 100;   // type cast operator
NSLog (@ ” (float) %i divided by 100 produces %f ” , i2, f2);
[pool drain];
return 0;
}

123.125000 assigned to an int produces 123
-150 assigned to a float produces -150.000000
-150 divided by 100 produces -1.000000
-150 divided by 100.0 produces -1.500000
(float) -150 divided by 100 produces -1.500000

objectC data type

refer to Addison Wesley - Programming.in.ObjectiveC.2.0.2nd (2009)

int main (int argc, char *argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int    integerVar = 100;
float  floatingVar = 331.79;
double doubleVar = 8.44e+11;
char   charVar =  ‘ W ’ ;
long int numberOfPoints = 131071100L;  // "%li"
// of type  long int is formed by optionally appending the letter L (in
upper or lower case) onto the end of an integer constant.
long long int maxAllowedStorage;  //  “ %lli ”
long double US_deficit_2004 =1.234e+7L;  //
// So  %Lf would display a  long dou-
ble value in floating-point notation, %Le would display the same value in scientific nota-
tion, and  %Lg would tell  NSLog to choose between  %Lf and %Le .

short int  shintvalue ;  // %hi , %ho , or  %hx
unsigned int counter = 20000UL;

NSLog (@ ” integerVar = %i ” , integerVar);
NSLog (@ ” floatingVar = %f ” , floatingVar);
NSLog (@ ” doubleVar = %e ” , doubleVar);
NSLog (@ ” doubleVar = %g ” , doubleVar);
NSLog (@ ” charVar = %c ” , charVar);
[pool drain];
return 0;
}

integerVar = 100
floatingVar = 331.790009
doubleVar = 8.440000e+11
doubleVar = 8.44e+11
charVar =  ' W '