특정 view에서는 default인 회색바가 아닌 검정색 bar나 투명한 검정색을 쓸 경우가 있다 (아이팟이나, Photo app처럼)

그럴 경우, UIView class에서 viewWillAppear를 override하고, 그 안에 아래의 code를 넣어주면 된다. 
한번 로드하고 안바꿀꺼라면 viewDidLoad에서 해도 되고...

[[UIApplication sharedApplicationsetStatusBarStyleUIStatusBarStyleBlackOpaque];

위의 코드는 검정색 bar로 만든다 (ipod처럼) 마지막 상수를 바꾸면 반투명 검정색 bar로 바꿀 수도 있다


Posted by yunseong

이미지 뒤집기를 할 때 UIImageView를 이용할 수 있다면, 매우 쉽게 해결할 수 있다. 

UIImage* artworkImage = [UIImage imageNamed:imageUrl];


[artworkReversedView setImage:artworkImage];

artworkReversedView.transform = CGAffineTransformMakeScale(1, -1);

위의 경우는 수평으로 뒤집기 (horizontal) 

CGAffineTransformMakeScale의 두 상수값을 조절하여 뒤집는 방향을 조절할 수 있다.
Posted by yunseong

Keyboard를 activate시키는 어떤 control이 firstResponder가 되면 keyboard는 자동으로 올라온다. 해당 control을 firstResponder가 아니게 만들면 keyboard는 사라진다. 

-(IBAction) editnigDone: (id)sender {
[sender resignFirstResponder];
}

예를 들면 UITextField는 Did End OnExit event를 위의 코드에 연결해주면 된다.

그런데 UITextView는 어떤 이벤트에 엮어야 하는거야 -_-;;


Posted by yunseong
This class is about defining class, memory management, and new feature, especially Property in Objective-C 2.0. 

define class is not familiar to C/C++ programmer, because its look is so different, We have to use '@interface' instead of 'class' and method cannot be in bracket, and method name and member variable's name can be equal. But it is not to hard to use. it is so easy!!. 

And memory management... it is really different from C/C++. There is global (This statement can be wrong) memory pool, called autorelease. It works by reference count (retain count) and it is not freed (dealloc) even though receive release message, if it's reference count (retain count) is not be 0. 

And property is also not familiar to me. i think is is similar with get {} / set {} in C#. it can reduce some boring code, and can be used by dot syntax. so convenient. 

Anyway, Here is my assignment 2-A

#import <Cocoa/Cocoa.h>



@interface PolygonShape : NSObject {

int numberOfSides;

int minimumNumberOfSides;

int maximumNumberOfSides;

float angleInDegrees;

float angleInRadians;

NSString* name;

}


- (void) dealloc;

- (id)init;

- (id)initWithNumberOfSides: (int)sides minimumNumberOfSides:(int)min maximumNumberOfSides:(int)max; 

- (void) description;


@property (readwrite) int numberOfSides;

@property (readwrite) int minimumNumberOfSides;

@property (readwrite) int maximumNumberOfSides;

@property (readonly) float angleInDegrees;

@property (readonly) float angleInRadians;

@property (readonly) NSString* name;

@end



#import "PolygonShape.h"


@implementation PolygonShape


@synthesize numberOfSides;

@synthesize minimumNumberOfSides;

@synthesize maximumNumberOfSides;


- (void)dealloc

{

NSLog(@"dealloc is called. This Polygon ivar is destroyed");

[super dealloc];

}


- (void) setNumberOfSides: (int) value

{

if (value < minimumNumberOfSides)

{

NSLog(@"Invalid number of sides: %d is less than the maximum of %d allowed", value, minimumNumberOfSides);

}

else if (value > maximumNumberOfSides)

{

NSLog(@"Invalid number of sides: %d is greater than the maximum of %d allowed", value, maximumNumberOfSides);

}

else

{

numberOfSides = value;

}

}


- (void) setMinimumNumberOfSides: (int) value

{

if (value > 2)

{

minimumNumberOfSides = value;

}

else

{

NSLog(@"Invalid minimum number of sides: %d is less than the minimum of 2 allowed", value);

}

}


- (void) setMaximumNumberOfSides: (int) value

{

if (value <= 12)

{

maximumNumberOfSides = value;

}

else

{

NSLog(@"Invalid maximum number of sides: %d is greater than the maximum of 12 allowed", value);

}

}


- (id)init

{

[self initWithNumberOfSides:5 minimumNumberOfSides:3 maximumNumberOfSides:10];

return self;

}


- (id)initWithNumberOfSides: (int)sides minimumNumberOfSides:(int)min maximumNumberOfSides:(int)max

{

[super init];

self.minimumNumberOfSides = min;

self.maximumNumberOfSides = max;

self.numberOfSides = sides;

return self;

}


- (float)angleInDegrees

{

return (180 * (numberOfSides - 2) / numberOfSides);

}


- (float)angleInRadians

{

return self.angleInDegrees * 2 * 3.14 / 360;

}


- (NSString*)name

{

NSMutableString* nameOfPolygon = [NSMutableString string];

switch (numberOfSides)

{

case 3 : nameOfPolygon = @"triangle"; break;

case 4 : nameOfPolygon = @"square"; break;

case 5 : nameOfPolygon = @"pentagon"; break;

case 6 : nameOfPolygon = @"hexagon"; break;

case 7 : nameOfPolygon = @"heptagon"; break;

case 8 : nameOfPolygon = @"octagon"; break;

case 9 : nameOfPolygon = @"enneagon"; break;

case 10 : nameOfPolygon = @"decagon"; break;

case 11 : nameOfPolygon = @"hendecagon"; break;

case 12 : nameOfPolygon = @"dodecagon"; break;

default : nameOfPolygon = @"";

}

return nameOfPolygon;

}


- (void)description

{

NSLog(@"Hello, I'm a %d-sided polygon (aka a %@) with angles of %f degrees (%f radians)", numberOfSides, self.name, self.angleInDegrees, self.angleInRadians);

}

@end



Posted by yunseong
I skipped first chapter, because it is just brief about iPhone programming (cocoa framework), and there are not much stuff to think. I can finish first assignment just followed given guide. Anyone can do it ;-)

Actually i already study about objective-c a few months back. but i cannot study with concentration, so i almost forgot everything. This class  reminds me, and i can remember what i studied ago.  And, i can use some unfamiliar class like NSEnumerator, NSURL, NSProcessInfo, so on. 

Here is assgnment 1-B.  Because these are my private, there is no comment ;-)

void PrintPathInfo()

{

NSString *path = @"~";

path = [path stringByExpandingTildeInPath];

NSLog(@"My home folder is %@", path);

NSArray *pathCompArray = [path pathComponents];

NSEnumerator *foreachEnum = [pathCompArray objectEnumerator];

NSString* item;

while (item = [foreachEnum nextObject])

{

NSLog(@"%@\n", item);

}

}


void PrintProcessInfo()

{

NSString *processName = [[NSProcessInfo processInfo] processName];

int processId = [[NSProcessInfo processInfo] processIdentifier];

NSString* outputStr = [NSString stringWithFormat: @"Process Name : %@, Process ID : '%d'",

  processName, processId];

NSLog(outputStr);

}


void PrintBookmarkInfo()

{

NSArray *keyArray = [NSArray arrayWithObjects: @"Stanford University"

@"Apple"

@"CS193P",

@"Stanford on iTunes U",

@"Stanford Mall", nil];

NSArray *strValueArray = [NSArray arrayWithObjects: @"http://www.stanford.edu",

  @"http://www.apple.com",

  @"http://cs193p.stanford.edu",

  @"http://itunes.stanford.edu",

  @"stanfordshop.com", nil];

NSMutableDictionary *bookMark = [NSMutableDictionary dictionaryWithCapacity: 5];

// c-style iteration

for (int nIdx = 0; nIdx < [keyArray count]; nIdx++)

{

[bookMark setValue: [NSURL URLWithString: [strValueArray objectAtIndex: nIdx]] forKey: [keyArray objectAtIndex: nIdx]]; 

}

NSEnumerator *keyEnum = [bookMark keyEnumerator];

NSString* key;

// Iteration with enumerator

while (key = [keyEnum nextObject])

{

NSURL *url = [bookMark objectForKey: key];

NSLog(@"Key : '%@' URL : '%@'\n", key, [url relativeString]);

}

}


void PrintIntrospectionInfo()

{

NSMutableArray *anyObjArray = [NSMutableArray arrayWithCapacity: 5];

NSString *string = [NSString stringWithFormat: @"Hello, Mac!!!!"];

NSURL *url = [NSURL URLWithString: @"http://www.apple.com"];

NSProcessInfo *processInfo = [NSProcessInfo processInfo];

NSDictionary *dic = [NSDictionary dictionary];

[anyObjArray addObject: string];

[anyObjArray addObject: url];

[anyObjArray addObject: processInfo];

[anyObjArray addObject: dic];

NSEnumerator *objEnum = [anyObjArray objectEnumerator];

NSObject *obj;

while (obj = [objEnum nextObject])

{

NSLog(@"Class Name : %@\n", [obj className]);

NSLog(@"Is member of NSString : %@", [obj isMemberOfClass: [NSString class]] ? @"YES" : @"NO");

NSLog(@"Is kind of NSString : %@", [obj isKindOfClass: [NSString class]] ? @"YES" : @"NO");

SEL sel = @selector(lowercaseString);

if ([obj respondsToSelector: sel] == YES)

{

NSLog(@"lowercaseString is '%@'", [obj performSelector: sel]);

}

else

{

NSLog(@"Responds to lowercaseString : NO");

}

NSLog(@"====================================");

}

[anyObjArray removeAllObjects];

[anyObjArray release];

}




Posted by yunseong
This section is about studying "iPhone application Programming" class which is established at Stanford University online class in iTunes U. I think this stuff is so good to study not only iPhone programming but also english. My english is not so good, so i always worry about it. This will be able to help me. Of course, i cannot understand what they say yet, but it becomes better. 

Actually, I already watch lesson 1 ~ 3, and i already finish assignments 2-1 from first one. I cannot make sure that my codes are all right, but i'll publish these code even though my codes can be wrong. 
 I hope, i can finish this class, not to be tedious. ;-). I think studying iphone programming is not press me. sometimes studying things can be burden. but i think i am really able to enjoy this ;-). it is the reason that i decide to study iPhone programming. 
Posted by yunseong

 
TODO List
  • Call test method dynamically. 
  • Call 'setUp' before calling test method
  • Call 'tearDown' after calling test method
  • Call 'teatDown' whether test is passed or  not
  • Execute multiple test cases
  • Print collected test case result

I think that i accomplished first step. but how about follows test code?

- (void) testRunning

{

WasRun* test = [[WasRun allocinitWithName@"NotExistedMethod"];

NSAssert([test wasRun] == NO@"wasRun Failed");

[test Run]; // Run with invalid method name.

NSAssert([test wasRun] == YES@"wasRun Failed");

}


In objective-C, if receiver receives unrecognized message by selector, it throws InvalidArgumentException. Hence, TestCase class has no try-catch statement, it crashed. Actually, the reason of this situation is from we cannot force that TestCase class has only one constructor. TestCase class can be instanced with "init" method, not only "initWithMethodName" method. What is more, there is no routine to validate given method name. So, before we go over next step, i'll make it more stable with add some TODO item. 

TODO List
  • Call test method dynamically. 
  • Handling exception caused by method name
  • Call 'setUp' before calling test method
  • Call 'tearDown' after calling test method
  • Call 'teatDown' whether test is passed or not
  • Execute multiple test cases
  • Print collected test case result
 

For our new requirement, i wrote 2 new TestCaseTest class method. 

- (void) testRunningWithInvalidMethodName

{

NSString* assertErrMsg = [[NSString allocinitWithString@"Assertion failed"];

WasRun* test = [[WasRun allocinitWithMethodName@"NotExistedMethod"];

NSAssert([test wasRun] == NO, assertErrMsg);

[test Run];

NSAssert([test wasRun] == NO, assertErrMsg);

NSLog(@"%s is finished\n", __FUNCTION__);

}


- (void) testRunningWithNoMethodName

{

NSString* assertErrMsg = [[NSString allocinitWithString@"Assertion failed"];

WasRun* test = [[WasRun allocinit];

NSAssert([test wasRun] == NO, assertErrMsg);

[test Run];

NSAssert([test wasRun] == NO, assertErrMsg);

NSLog(@"%s is finished\n", __FUNCTION__);

}


First is for when given not existed method name, and second is for with no name.

Above codes are compiled successfully. 

Okay, let's check first. 

For handle invalid test method name, we can use RTTI (Real-Time Type Information). Of course, Objective-C supports RTTI well. (In fact, Cocoa framework supports it). I modified "Run" method in TestCase class. 

- (void) Run

{

SEL exeMethod = NSSelectorFromString(name);


if ([self respondsToSelector: exeMethod] == YES)

{

[self performSelector: exeMethod];

}

else

{

NSLog(@"Given method named %@ cannot be resolved.", name);

}

}


Its result is



Okay. First issue (given invalid method name) is resolved. Let's check second issue, which is when receives no name. 


- (void) Run

{

    if (name != nil)

    {

        SEL exeMethod = NSSelectorFromString(name);

        if ([self respondsToSelector: exeMethod] == YES)

        {

       [self performSelector: exeMethod];

    }

else

{

    NSLog(@"[ERR]Given method named \"%@\" cannot be resolved.", name);

}

    }

    else

    {

NSLog(@"[ERR]TestCase class should be initiated with \"initWithMethodName\".\n");

    }

}



and test case execution code, here it is.

int main (int argc, const char * argv[]) {

    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];


TestCaseTest* testCaseTest = [[TestCaseTest alloc] initWithMethodName: @"testRunning"];

[testCaseTest Run];

[testCaseTest release];

TestCaseTest* testCaseTest1 = [[TestCaseTest alloc] initWithMethodName: @"testRunningWithInvalidMethodName"];

[testCaseTest1 Run];

[testCaseTest1 release];

TestCaseTest* testCaseTest2 = [[TestCaseTest alloc] initWithMethodName: @"testRunningWithNoMethodName"];

[testCaseTest2 Run];

[testCaseTest2 release];

 

    [pool drain];

    return 0;

}



Finally, i completed second step!!


Actually, i read some chapters more far from rate of current progress. There is exception handling chapter after a few chapters, but i did it more earlier, because i don't think i have to follow that book. Of course, this exception handling is too simple. It can handle only caused by method name. If there is another runtime exception on executing test, this framework will be crashed. I know that i have to use careful try-catch statement, but i'll add it when i need it ;-). It is not now. 
Posted by yunseong
TAG TDD, xUnit
Actually, our "WasRun" class has multiple functionality.
first is Check test function is called or not, and second is calling test function in really. 

We need  to make it separate. WasRun is still check function is called or not, and new class will call test function. New class's name is "TestCase".


TestCase.h / TestCase.m


#import <Cocoa/Cocoa.h>



@interface TestCase : NSObject {

NSString* name;

}


- (id) initWithMethodName: (NSString*) methodName;

- (void) Run;


@end



#import "TestCase.h"



@implementation TestCase

- (id) initWithMethodName: (NSString*) methodName

{

[super init];

name = [[NSString alloc] initWithString: methodName];

return self;

}


- (void) Run

{

SEL exeMethod = NSSelectorFromString(name);

[self performSelector: exeMethod];

}


@end



WasRun.h / WasRun.m


#import <Cocoa/Cocoa.h>

#import "TestCase.h"


@interface WasRun : TestCase {

bool wasRun;

}


- (id) initWithName: (NSString*) methodName;

- (void) testMethod;

- (bool) wasRun;

@end



#import "WasRun.h"


@implementation WasRun


- (id) initWithName: (NSString*) methodName 

{

[super initWithMethodName: methodName];

wasRun = NO;

return self;

}


-(void) testMethod

{

wasRun = YES;

}


- (bool) wasRun

{

return wasRun;

}

@end



as you can show, WasRun class is only for check method is executed or not, and TestCase class is execution trigger. 

And of course, its execution result is...


Perfect!! ;-)


I have one more thing to tell. Actually, i don't be acquainted with Cocoa framework, so i cannot find how can i bind proper method by method's name. So i ask to 'Mac bu gi' club in portal site Naver, they reply to me in a hour!! Thanks ;)

 


Posted by yunseong
TAG TDD, xUnit
Our progress was too slow like a snail's pace, but, today, we'll go far from yesterday. 
We already made compilable source code, but it does not work as our wish. 
Constructor should store specified method name to be tested, and method which is selected, should call method in class. 
So, i'll change one item to TODO list as follows.

TODO List
  • Call test method --> Call test method dynamically. 
  • Call 'setUp' before calling test method
  • Call 'tearDown' after calling test method
  • Call 'teatDown' whether test is passed or  not
  • Execute multiple test cases
  • Print collected test case result

and, here is its source code

WasRun.h

@interface WasRun : NSObject {

bool wasRun;

NSString* name; // <-- newly added for store method name to be called. 

}


- (id) initWithName: (NSString*) methodName;

- (void) testMethod;

- (bool) wasRun;

@end




WasRun.m

#import "WasRun.h"


@implementation WasRun


- (id) initWithName: (NSString*) methodName 

{

[super init];

wasRun = NO;

name = [[NSString alloc] initWithString: methodName];

return self;

}


- (void) testMethod

{

SEL exeMethod = NSSelectorFromString(name);

[self performSelector: exeMethod];

}


- (bool) wasRun

{

return wasRun;

}

@end



Okay, it looks finished. Let's check we can complete this step.... Build and RUN!!! gogogo!!
...
What the hell -_-;; Critical runtime error is happen. maybe, there is some exceptional case...


Stack frame is loading.... it looks there is stack overflow... (actually, i'm very beginner at XCode...)


Debugger displays that what is problem. in my main function, i called test function which is named "testMethod". 
But, in WasRun class, "testMethod" is the name that test function's own name, and it called itself recursively!!!

So, i changed method name "testMethod" to "Run".  (Actually, in my text book, it is already changed -_-)

Rebuild it and run... Okay!! it works well ;-) 







Posted by yunseong
TAG TDD

There were some errors on our code, because 'WasRun' class is missed. Here is 'WasRun' class implementation. 
As mentioned in TDD, this class is only for compile successfully. 


WasRun.h

#import <Cocoa/Cocoa.h>


@interface WasRun : NSObject {

bool wasRun;

}


- (id) initWithName: (NSString*) name;

- (void) testMethod;

- (bool) wasRun;

@end


WasRun.m


#import "WasRun.h"


@implementation WasRun


- (id) initWithName: (NSString*) name 

{

[super init];

wasRun = NO;

return self;

}


- (void) testMethod

{

}


- (bool) wasRun

{

return wasRun;

}

@end


After add above class, compile is successful!!, but output is...


what is this -_-;;  (Actually, there is no wonder for this result... I'm satisfied with successful compilation -_-)



Posted by yunseong
TAG TDD
이전버튼 1 2 3 이전버튼