Friday, February 25, 2011

parsing HTML file for iPhone apps using xcode, obj-c

Hay,

Recently I made a project where the application need to read the HTML file , parse it and display the data on the view.

Before you start , get the below files from https://github.com/topfunky/hpple


  1. HTFpple.h
  2. HTFpple.m
  3. HTFppleElement.h
  4. HTFppleElement.m
  5. XPathQuery.h
  6. XPathQuery.m

Once you get that, just do the following modifications to your project settings:

1) Goto Target on the left hand side tree. Right click on your project name and hit Get Info option from popup menu.

2) Select All configurations from Configuration combo box.

3) Search for Header Search path and the bloodline with recursive option selected

${SDKROOT}/usr/include/libxml2

4) In the same way, search for Other Linker Flag


add the below line to it:


-lxml2 


Here is the code to parse the HTML file. [ This code works for reading local HTML file attached in your project ]







NSMutableArray *array = [[NSMutableArray alloc]init];
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"myHTMLfileNameWithoutExtension" ofType:@"html"];
NSData *htmlData = [[NSData alloc] initWithContentsOfFile:filePath];
TFHpple *xpathParser = [[TFHpple alloc] initWithHTMLData:htmlData];
NSArray *chapterName  = [xpathParser search:@"//html//h1"]; // get the page title
self.chapterIndexData = chapterName;
[xpathParser release];
[htmlData release];
[array release];


Above code reads all the H1 tags in the HTML page and put them in 

chapterIndexData
  which is of type NSArray *.



Please let me know if you have any doubts regarding this.




Tuesday, January 11, 2011

show text box while typing from keyboard/keypad in iPhone

Some times, while you try to enter the text in text field's , you might not be able to see the text which you are typing in the text box. It get hide with the popup keyboard. If you don't want to hide the text box while typing, just add the below 2 functions in your code.


- (void)keyboardWasShown:(NSNotification *)aNotification {
    if ( keyboardShown )
        return;
    if( textView.text != 0 ) {
        NSDictionary *info = [aNotification userInfo];
        NSValue *aValue = [info objectForKey:UIKeyboardBoundsUserInfoKey];
        CGSize keyboardSize = [aValue CGRectValue].size;
        NSTimeInterval animationDuration = 0.300000011920929;
        CGRect frame = self.view.frame;
        frame.origin.y -= keyboardSize.height-44;
        frame.size.height += keyboardSize.height-44;
        [UIView beginAnimations:@"ResizeForKeyboard" context:nil];
        [UIView setAnimationDuration:animationDuration];
        self.view.frame = frame;
        [UIView commitAnimations];
        viewMoved = YES;
    }
    keyboardShown = YES;
}

- (void)keyboardWasHidden:(NSNotification *)aNotification {
    if ( viewMoved ) {
        NSDictionary *info = [aNotification userInfo];
        NSValue *aValue = [info objectForKey:UIKeyboardBoundsUserInfoKey];
        CGSize keyboardSize = [aValue CGRectValue].size;
        NSTimeInterval animationDuration = 0.300000011920929;
        CGRect frame = self.view.frame;
        frame.origin.y += keyboardSize.height-44;
        frame.size.height -= keyboardSize.height-44;
        [UIView beginAnimations:@"ResizeForKeyboard" context:nil];
        [UIView setAnimationDuration:animationDuration];
        self.view.frame = frame;
        [UIView commitAnimations];
        viewMoved = NO;
    }
    keyboardShown = NO;
}

Observe the screen shots below before and after the code:

Actual screen before typing

While typing, entire screen will be moved to upwards

Pleaes let me know if you have any questions or concerns.

Happy coding :)

Wednesday, December 15, 2010

Alert message sample

If you want to display a simple notification message like below, just copy paste the below code according your requirement.




UIAlertView *alert = [[UIAlertView alloc   initWithTitle:@"Only one picture allowed"   message:@"" 
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil]; 

[alert show];
[alert release]; 

in the message:"" part, you can mentioned whatever you want to display within the double quotes.

Happy coding :)

Tuesday, December 7, 2010

Implementing game center for leader boards / leaderboard on iPhone

If you want to implement game center related stuff in your iPhone application, go through the description mentioned below.

In this post, I am proving you only the implementation part for leader board /leaderboard in game center on iPhone.

Copy paste the below code in your .mm file :


- (BOOL)isGameCenterAvailable {
// Check for presence of GKLocalPlayer API.
    Class gcClass = (NSClassFromString(@"GKLocalPlayer"));
    // The device must be running running iOS 4.1 or later.
    NSString *reqSysVer = @"4.1";
    NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
    BOOL osVersionSupported = ([currSysVer compare:reqSysVer options:NSNumericSearch] != NSOrderedAscending);
    return (gcClass && osVersionSupported);
}

- (void)initGameCenter {
// Only continue if Game Center is available on this device
// Authenticate the local player
[self gameCenterAuthenticate];
// Register the GKPlayerAuthenticationDidChangeNotificationName notification
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver: self
  selector:@selector(gameCenterAuthenticationChanged)
  name:GKPlayerAuthenticationDidChangeNotificationName
object:nil];
}

- (void)gameCenterAuthenticate {
// Authenticate the local user
NSLog(@"Game Center - Trying to authenticate...");
/*if([GKLocalPlayer localPlayer].authenticated == NO) */{
[[GKLocalPlayer localPlayer] authenticateWithCompletionHandler:^(NSError *error) {
if(error == nil) {
NSLog(@"Game Center - Authenticated successfully");
} else {
NSLog(@"Game Center - Failed to authenticate");
}
}];
}
}

- (void)gameCenterAuthenticationChanged {
    [self gameCenterAuthenticate];
}
- (void) registerForAuthenticationNotification
{
    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
    [nc addObserver: self
           selector:@selector(authenticationChanged)
               name:GKPlayerAuthenticationDidChangeNotificationName
             object:nil];
}

- (void)submitHighScore {
// Report the high score to Game Center
GKScore *scoreReporter = [[[GKScore alloc] initWithCategory:@"HIGHEST_SCORES"] autorelease];
scoreReporter.value = finalScore;
[scoreReporter reportScoreWithCompletionHandler:^(NSError *error) {
if (error == nil) {
NSLog(@"Game Center - High score successfully sent");
}
}];
// Show the Game Center leaderboard
[self viewLeaderboard];
}

- (void)viewLeaderboard {
// Show the leaderboard
[self showLeaderboardCategory:@"HIGHEST_SCORES"];
}

- (void)showLeaderboardCategory:(NSString *)category {
// Show leaderboard
    GKLeaderboardViewController *leaderboardController = [[GKLeaderboardViewController alloc] init];
    if (leaderboardController != nil) {
leaderboardController.category = category;
        leaderboardController.leaderboardDelegate = self;
// Add the leaderboard view to the EAGLView
        [self presentModalViewController:leaderboardController animated: YES];
    }
[self retrieveFriends];
}
- (void)retrieveFriends
{
    GKLocalPlayer *lp = [GKLocalPlayer localPlayer];
    if (lp.authenticated)
    {
        [lp loadFriendsWithCompletionHandler:^(NSArray *friends, NSError *error) {
if (error == nil)
{
// use the player identifiers to create player objects.
}
else
{
// report an error to the user.
}
}];
    }
}

- (void) loadPlayerData: (NSArray *) identifiers
{
    [GKPlayer loadPlayersForIdentifiers:identifiers withCompletionHandler:^(NSArray *players, NSError *error) {
        if (error != nil)
        {
            // Handle the error.
        }
        if (players != nil)
        {
            // Process the array of GKPlayer objects.
        }
}];
}

- (void)leaderboardViewControllerDidFinish:(GKLeaderboardViewController *)viewController {
// Remove the leaderboard view from the EAGLView
[self dismissModalViewControllerAnimated:YES];
[viewController release];
}
- (void) retrieveTopTenScores
{
    GKLeaderboard *leaderboardRequest = [[GKLeaderboard alloc] init];
    if (leaderboardRequest != nil)
    {
        leaderboardRequest.playerScope = GKLeaderboardPlayerScopeGlobal;
        leaderboardRequest.timeScope = GKLeaderboardTimeScopeAllTime;
        leaderboardRequest.range = NSMakeRange(1,10);
        [leaderboardRequest loadScoresWithCompletionHandler: ^(NSArray *scores, NSError *error) {
            if (error != nil)
            {
                // handle the error.
            }
            if (scores != nil)
            {
                // process the score information.
            }
}];
    }
}

in your .h file, please add the following things:

Declare the below methods:

- (BOOL)isGameCenterAvailable;
- (void)initGameCenter;
- (void)gameCenterAuthenticate;
- (void)gameCenterAuthenticationChanged;
- (void)submitHighScore;
- (void)viewLeaderboard;
- (void) retrieveFriends;
- (void) loadCategoryTitles;
- (void) registerForAuthenticationNotification;
- (void) reportScore: (int64_t) score forCategory: (NSString*) category;
- (void)leaderboardViewControllerDidFinish:(GKLeaderboardViewController *)viewController;

Also add, GKLeaderboardViewControllerDelegate in your class declaration. 

Ex. 

@interface GameOverViewController : UIViewController <UITextFieldDelegate,  GKLeaderboardViewControllerDelegate >

Here is the hierarchy of calling these functions:

if([self isGameCenterAvailable])
{
[self initGameCenter];
[self gameCenterAuthenticate];
[self submitHighScore];
[self retrieveTopTenScores];
[self retrieveFriends];
}

Include the header files, #import <GameKit/GameKit.h>.

And add gamekit in the frameworks.
Here is the description for the above code:

Before you send your score to the game center, you need to follow the below steps:

1) Check weather the device supports game center or not [ isGameCenterAvailable ]
2) Check weather the current player has logged in or not.. i.e is this guy has registered with game center or not.
3) Then submit your score.
4) Then view the leader board :)

w.r.t the method, submitHighScore , I have used a variable called finalScore where I have my score which need to send to the game center. 
So,you use your own variable to send the score or you can also hardcode it for testing purpose.  

HIGHEST_SCORES is the one I registered the high score level in iTunesConnect.

So, make sure you already configured your game in the iTunesConnect before you actually start implementing game center. If you don't configure it, it won't work.

If you have any more doubts, please let me know.

Happy coding :)


Pradeep Daram.
pradeepfriend2000@gmail.com.


Monday, December 6, 2010

Error Domain=GKErrorDomain Code=3 in game center - iphone gamekit [ game kit ]

When you are trying to submit your score to game center, sometimes you might get the below error:

An error occured reporting the score: Error Domain=GKErrorDomain Code=3 "The requested operation could not be completed due to an error communicating with the server." UserInfo=0x1f98d0 {NSUnderlyingError=0x1f2c90 "The operation couldn’t be completed. status = 5053", NSLocalizedDescription=The requested operation could not be completed due to an error communicating with the server.

There are couple of things you might forgot to do before you actually run your code. You can direct run your code with the code supplied by apple developer center.
Below are the list of the things might be causing this error:

1) The category name should exactly match to your itunesconnect category name. You have to use, leaderboard category ID . You should not use, Category reference name.

2) Make sure you have 4.1 version of iOS. And, try to run the game on the device rather than, simulator. I heard that game center sandbox is not working properly some times with the simulator.

3) Check weather you have configured the targets properly or not. On the left hand side in your xCode, you can see Groups & Files category. If go below in that solution explorer, you can see "Targets" module. Expand "Targets" and double click on the name which has your game name followed by the device type. [ Ex. myGameName - iPad ].
Double click on that and select properties module in the dialog which popped up.

In that properties, make sure you have valid identifier name . Ex. com.sampleCompany.sampleGame

4) Project - Edit Active Target - iOS Deployment Target and change its version to 3.0 . After this, select your device type to , 4.1 .

Please let me know if you have any question or concerns :)
Happy coding

Pradeep Daram.
pradeepfriend2000@gmail.com

Intro

Hay,

I created this blog to share my opinions , tips and tricks in iPhone development. I hope this will be helpful for many developers :)

Thanks for your time guyz :)

Pradeep Daram
pradeepfriend2000@gmail.com