Thursday 2 July 2009

[Cocoa] How to add a toolbar with button on top of a UITextView in order to add a dismiss button

The big problem with UITextView is there isn't any native way to hide the keyboard once the input ended.
The following code describes a DissmisableTextView. This view extends UITextView adding on top of the keyboard associated with this UITextView a toolbar with a "Done" Button :



Here is the code :
//
//  DismissableTextView.h
//  
//  A textView allowing to dismiss keyboard with a toolbar and a
//  Done button on top of the keyboard
//
//  Created by Vincent Demay on 02/07/09.
//  Copyright 2009 Goojet. All rights reserved.
//

#import 


@interface DismissableTextView : UITextView {

	UIToolbar* keyboardToolbar;
}

- (void) keyboardWillShow:(NSNotification *)note;
- (void) dismissKeyboard;

@end



//
//  DismissableTextView.m
//  murena
//
//  Created by Vincent Demay on 02/07/09.
//  Copyright 2009 Goojet. All rights reserved.
//

#import "DismissableTextView.h"


@implementation DismissableTextView


- (id)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
		//register a specific method on keyboard appearence
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
    }
    return self;
}



- (void)keyboardWillShow:(NSNotification *)notification 
{	
    for (UIWindow *keyboardWindow in [[UIApplication sharedApplication] windows]) {
		
        // Now iterating over each subview of the available windows
        for (UIView *keyboard in [keyboardWindow subviews]) {
			
            // Check to see if the description of the view we have referenced is UIKeyboard.
            // If so then we found the keyboard view that we were looking for.
            if([[keyboard description] hasPrefix:@"<UIKeyboard"] == YES) {
				NSValue *v = [[notification userInfo] valueForKey:UIKeyboardBoundsUserInfoKey];
				CGRect kbBounds = [v CGRectValue];
				
				if(keyboardToolbar == nil) {
					keyboardToolbar = [[UIToolbar alloc] initWithFrame:CGRectZero];
					keyboardToolbar.barStyle = UIBarStyleBlackTranslucent;
					
					UIBarButtonItem *barButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Done" style:UIBarButtonItemStyleBordered target:self action:@selector(dismissKeyboard)];
					UIBarButtonItem *flex = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
					NSArray *items = [[NSArray alloc] initWithObjects:flex, barButtonItem, nil];
					[keyboardToolbar setItems:items];	
					[items release];	
				}				
				
				[keyboardToolbar removeFromSuperview];
				keyboardToolbar.frame = CGRectMake(0, 0, kbBounds.size.width, 30);
				[keyboard addSubview:keyboardToolbar];
				keyboard.bounds = CGRectMake(kbBounds.origin.x, kbBounds.origin.y, kbBounds.size.width, kbBounds.size.height + 60);
				
				for(UIView* subKeyboard in [keyboard subviews]) {
					if([[subKeyboard description] hasPrefix:@"<UIKeyboardImpl"] == YES) {
						subKeyboard.bounds = CGRectMake(kbBounds.origin.x, kbBounds.origin.y - 30, kbBounds.size.width, kbBounds.size.height);	
					}						
				}
            }
        }
    }
}

- (void) dismissKeyboard {
	[self resignFirstResponder];
}



- (void)dealloc {
    [super dealloc];
}


@end

Tuesday 23 June 2009

Cocoa : Who to handle MouveXXX events on UIWebView

Default behavior of the UIWebView is : eat touchXXX events and not send them to the nextResponder. One way to be able to catch this kind of event on a UIWebView is to add on top of it a UIView. But at this point, links, scroll, etc... are not capture to inner components of the under UIWebView. Here is a HACK to make this struff work :
//
//  TouchUIWebView.h
//
//  Created by Vincent Demay on 19/06/09.
//  Copyright 2009 __MyCompanyName__. All rights reserved.
//

#import 

@interface DummyTapView : UIView {
	
	UIView * uiScroller_;
	UIView * uiWebDocumentView_;
}
@property(nonatomic, retain) UIView *uiScroller;
@property(nonatomic, retain) UIView *uiWebDocumentView;

@end


@interface TouchUIWebView : UIWebView {
}

@end

//
//  TouchUIWebView.m
//
//  Created by Vincent Demay on 19/06/09.
//  Copyright 2009 __MyCompanyName__. All rights reserved.
//

#import "TouchUIWebView.h"


const char* kUIScrollerName = "UIScroller";
const char* kUIWebDocumentView= "UIWebDocumentView";

@implementation DummyTapView

@synthesize uiScroller = uiScroller_;
@synthesize uiWebDocumentView = uiWebDocumentView_;

//
// retreive the scroller view in uiwebView
// used to compute scrolling in the loaded web page
//
- (UIView*) uiScroller {
	if( self.superview !=nil && uiScroller_ == nil ) {
		NSArray *views = [self.superview subviews];
		for( id view in views ) {
			const char* name = object_getClassName(view);
			if( !strncmp( name, kUIScrollerName, strlen(name) ) ) {
				uiScroller_ = view;
				return uiScroller_;
			}
		}
	}
	return uiScroller_;
}

//
// retreive the document view in UiWebView
// used to compute touch on link etc...
//
- (UIView*) uiWebDocumentView {
	if( self.superview != nil && uiWebDocumentView_ == nil ) {
		NSArray *views = [self.uiScroller subviews];
		for( id view in views ) {
			const char* name = object_getClassName(view);
			if( !strncmp( name, kUIWebDocumentView, strlen(name) ) ) {
				uiWebDocumentView_ = view;
				return uiWebDocumentView_;
			}
		}
	}
	return uiWebDocumentView_;
}

- (id) initWithFrame:(CGRect)frame {
	self = [super initWithFrame:frame];
	self.backgroundColor = [UIColor clearColor];
	return self;
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
	[self.uiScroller touchesBegan:touches withEvent:event];
	[self.uiWebDocumentView touchesBegan:touches withEvent:event];
	[self.nextResponder touchesBegan:touches withEvent:event];

}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
	[self.uiScroller touchesMoved:touches withEvent:event];
	[self.uiWebDocumentView touchesMoved:touches withEvent:event];
	[self.nextResponder touchesMoved:touches withEvent:event];

}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
	[self.uiScroller touchesEnded:touches withEvent:event];
	[self.uiWebDocumentView touchesEnded:touches withEvent:event];
	[self.superview didFinishGesturesInView:self.superview forEvent:event];
	[self.nextResponder touchesEnded:touches withEvent:event];

}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
	[self.uiScroller touchesCancelled:touches withEvent:event];
	[self.uiWebDocumentView touchesCancelled:touches withEvent:event];
	[self.nextResponder touchesCancelled:touches withEvent:event];

}
@end



@implementation TouchUIWebView

- (id)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame]) {
        // Initialization code	
		DummyTapView* view = [[DummyTapView alloc] 
							  initWithFrame:CGRectMake( 0,0,self.frame.size.width,self.frame.size.height)];
		[self addSubview:view];
		[view release];
    }
    return self;
	
}

@end

Thursday 12 March 2009

Loi Hadopi en France

«Bourbier juridique», «nuage de Tchernobyl», «pas raisonnable». Hier encore, la loi création et Internet (dite Hadopi) s’est fait tailler un joli costard. Repoussé par la loi sur l’hôpital, l’examen du projet devrait démarrer aujourd’hui à l’Assemblée nationale et, hormis une page de pub dans le Monde rassemblant les signatures de 10 000 artistes en faveur du texte, le climat est hostile.[...] (Libération)

Bannière 1 du site Dédé Ca-va-couper.fr

Wednesday 4 February 2009

Writing / Reading files on native Iphone Application

Here is a little sample to write/read files with objective c on native Iphone Application.
This snippet write into the Document Directory of the application. We will see later problems when trying to write in the Resources folder


WRITE
NSString *dataStr = @"my data";

//get Document Root
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];

//append file name to path	
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:@"myFile"];

//prepar data in A NSData from a String
NSData *aData = [dataStr dataUsingEncoding: NSUTF8StringEncoding];

//Write to the file.
//File will be automacally created if not exist
[aData writeToFile:filePath atomically:YES];



READ
//get Document root
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
	
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:@"myFile"];
NSString *myText = [NSString stringWithContentsOfFile:filePath]; 
if (myText) {
    return myText;
} else  {
    //can not read because file does not exists
    //make here your error handler 
}




WARNING : It is possible to get a file from Resources Folder with the follwing line :
NSString *filePath = [[NSBundle mainBundle] pathForResource:fileName ofType:extension];

Be carreful with that because if the file does not exist filePath will be null, so it will be impossible to create the file... difficult to write into the file :p

Sunday 11 January 2009

Sending HTTP request from Iphone App

How to send a HTTP request from Cocoa Application
        //prepar request
	NSString *urlString = [NSString stringWithFormat:@"http://urlToSend.com"];
	NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] autorelease];
	[request setURL:[NSURL URLWithString:urlString]];
	[request setHTTPMethod:@"POST"];
	
        //set headers
	NSString *contentType = [NSString stringWithFormat:@"text/xml"];
	[request addValue:contentType forHTTPHeaderField: @"Content-Type"];

	//create the body
	NSMutableData *postBody = [NSMutableData data];
	[postBody appendData:[[NSString stringWithFormat:@"<xml>"] dataUsingEncoding:NSUTF8StringEncoding]];
	[postBody appendData:[[NSString stringWithFormat:@"<yourcode/>"] dataUsingEncoding:NSUTF8StringEncoding]];
	[postBody appendData:[[NSString stringWithFormat:@"</xml>"] dataUsingEncoding:NSUTF8StringEncoding]];
	
        //post
	[request setHTTPBody:postBody];
	
	//get response
	NSHTTPURLResponse* urlResponse = nil;  
	NSError *error = [[NSError alloc] init];  
	NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&urlResponse error:&error];  
	NSString *result = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
	NSLog(@"Response Code: %d", [urlResponse statusCode]);
	if ([urlResponse statusCode] >= 200 && [urlResponse statusCode] < 300) {
		NSLog(@"Response: %@", result);
	        
                //here you get the response

	}

Friday 9 January 2009

Getting data from info.plist

How to get data from info.plist file in Iphone app development :
NSString * stringFromInfoPlist = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"stringInInfoPlist"];



Update : More info on *.plist files management here : iPhone Development Blog

Wednesday 7 January 2009

A little meal at office


via Thomas Nicholls

Saturday 3 January 2009

Getting contacts from adress book

Here is a simple to way to access to Iphone address book for Cocoa Iphone developers :
// open the default address book.
ABAddressBookRef m_addressbook = ABAddressBookCreate();
if (!m_addressbook) { 
    NSLog(@"opening address book"); 
}

//get people and index
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(m_addressbook);
CFIndex nPeople = ABAddressBookGetPersonCount(m_addressbook);

//iterate on each person
for (int i=0;i < nPeople;i++) {
    ABRecordRef ref = CFArrayGetValueAtIndex(allPeople,i);

    //get phone numbers and names
    ABMultiValueRef phoneNumberProperty = ABRecordCopyValue(ref, kABPersonPhoneProperty);
    NSArray* phoneNumbers = (NSArray*)ABMultiValueCopyArrayOfAllValues(phoneNumberProperty);
    NSString* name = (NSString*)ABRecordCopyValue(ref, kABPersonFirstNameProperty);
    CFRelease(phoneNumberProperty);

    //Loop to display results
    NSLog(@"Name = %@", name);
    NSLog(@"Phone numbers = ");
    for (int j=0; j<[phoneNumbers count]; j++) { 
        NSLog(@" phone -> %@", [phoneNumbers objectAtIndex:j]); 
    }

    //release memory
    [phoneNumbers release];
}

Wednesday 3 December 2008

IE (6) Death March

From http://iedeathmarch.org/:
Internet Explorer 6 will be SEVEN years old on August 27th. It came out a few weeks before the Twin Towers fell. It came out before the Nintendo GameCube. It came out before the first iPod.

It’s time to put a deadline on dropping IE6, and I say that time is now, and the deadline should be soon… say like, March 2009.


It is a proposal from http://iedeathmarch.org/ and ... I'm in ;) : My web site does not really support IE6....

If you think IE sucks, join the IE Death March Project...

Friday 21 November 2008

Google's Starter Guide to SEO

Google has published their SEO starter guide as PDF.
It is not really a technical review but it is quitte interesting to explain to newbies how Google works.

Source : SmileyCat

Monday 20 October 2008

Join me on Goojet

We've just add a lot of cool features to Goojet, for instance, you can now export your prefered goojet to your blog ;-)

So join me on goojet to try new features
Click on the logo to subscribe

Tuesday 14 October 2008

hum, an interesting new MacBook feature

from today's keynote :

;)

Monday 13 October 2008

SEO : Free online analyzers

If you own a web site, you probably want to use the following tools.
These tools are free and can help you to improve your pageRank and your website performence.

SEOmoz Trifecta Page Strength Tool

If you would like to measure the strength of a certain page on a site, blog, or an entire domain, then check out the SEOmoz Trifecta Page Strength Tool (free registration required). Based on various factors you will see your impact within your industry and can compare it to others. Note that free accounts are limited to one report per day.



Popuri

If you think it's a lot of hassle to use several different tools Popuri might be what you're looking for. Popuri allows you to get a variety of information — from PageRank to del.icio.us bookmarks — all at once. It also includes Compete rank which provides a useful counterpoint to Alexa in order to get a better picture of how your site ranks in popularity.



Raven SEO Analyzer

The free Raven SEO Analyzer aims to help you build a better, more optimized website to rank you higher on search engines. It checks things like whether your site uses heading tags properly, has deprecated HTML, contains inline styles, and has an acceptable page weight. It also scores you out of 100 which is helpful if you're monitoring the performance of your site over time or comparing against competitors.



Mint

Mint is a web analytics tool somewhat similar to Google Analytics. It provides all the usual statistics on everything from number of visits to unique referrers. Unlike Google Analytics and other web analytics packages, it also tracks RSS feeds, browser window size, and has a library of official and community-developed plugins.



Website Grader

If you're looking to analyze the marketing effectiveness of your web site, try Website Grader. It provides you with a score out of 100 based on criteria such as web site traffic, SEO, social popularity and various other technical factors. It also provides you with advice on how you can improve your ranking. One useful feature is the ability to compare your site against multiple other websites. This could be really helpful in better understanding how your site stacks up against its competitors.



Crazy Egg

Crazy Egg is a tool that supplements your standard analytics package. It comes in 3 versions — standard (free), plus and pro — depending on how many visits and pages you want to track at once. Crazy Egg lets you track what visitors are doing on particular page and shows you what links they clicked via heatmaps and various overlays. It's a great way to test the effectiveness of different versions of a page to see which one is the most effective.



SiteYogi

SiteYogi sets out to be a one-stop-shop for web site analysis. It examines a variety of areas, including how well optimized your site is for search engines as well as the number of backlinks you have, various social media rankings, whether your code is valid, and how well ranked your site is. It provides quite a comprehensive overview.



Smart PageRank

Smart PageRank provides you with a lot more data about your site than the name suggests. Like some of the other tools mentioned, it provides you with a variety of data about your site and its ranking on various search engines. Unlike other tools, it estimates a dollar value for your site based on these factors.



SEOCentro

Looking for a variety of SEO-related tools all in one place? Then SEOCentro is worth a look. It includes tools that will check meta tags, pagerank, links popularity, keyword position, and search engine saturation. It also provides a server headers checking tool, which is useful to make sure that any 301 redirects are set up correctly.




source : http://www.smileycat.com/miaow/archives/001336.php

Tuesday 30 September 2008

Internet History

Thanks to JB to bring this link to me ;). It is a really interrresting history of the Internet.

Thursday 4 September 2008

Acid test 3 and common browsers... new Browsers

I've already talked about acid test on commons browsers. Here are some screenshots on last browsers:

IE8 Beta 2 (not really nice)





Google Chrome





Thanks to Sbucci for the screenshots