블로그 이미지
Sunny's

calendar

1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30

Notice

2012. 5. 3. 14:34 IPhone

 

NSArray & NSMutableArray

// 빈 배열 생성
NSArray* arrEmptyArray = [NSArray array];
NSMutableArray* arrEmptyMutableArray = [NSMutableArray array];


// 특정 크기의 빈 배열 생성
NSMutableArray* arrEmptyMutableArrayWithCapacity = [NSMutableArray arrayWithCapacity:7];
NSMutableArray* arrEmptyMutableArrayWithCapacity2 = [[NSMutableArray alloc] initWithCapacity:7];
[arrEmptyMutableArrayWithCapacity2 release];


// 오브젝트들로 배열 생성
NSArray* arrFruits = [NSArray arrayWithObjects:@"Apple", @"Orange", @"Banana", @"Watermelon", @"Cherry", @"Strawberry", @"Pineapple", nil];


// 배열로부터 새로운 배열 생성
NSArray* arrFruitsCopy = [NSArray arrayWithArray:arrFruits];
NSArray* arrFruitsCopy2 = [[NSArray alloc] initWithArray:arrFruits];
[arrFruitsCopy2 release];
[arrEmptyMutableArray addObjectsFromArray:arrFruits];


// C 스타일 배열로부터 새로운 배열 생성
NSString* strFruits[3];
strFruits[0] = @”Apple”;
strFruits[1] = @”Orange”;
strFruits[2] = @”Banana”;

NSArray* arrFruitsFromCArray = [NSArray arrayWithObjects:strFruits count:3];
NSArray* arrFruitsFromCArray2 = [[NSArray alloc] initWithObjects:strFruits count:3];
[arrFruitsFromCArray2 release];


// 특정 오브젝트를 포함하고 있는지 판별
BOOL bAppleExist = [arrFruits containsObject:strFruits[0]];


// 배열 길이
NSUInteger cnt = [arrFruits count];


// 특정 범위를 C 스타일 배열로 복사
id* arr;
NSRange range = NSMakeRange(1, 2);
arr = malloc(sizeof(id) * range.length);
[arrFruits getObjects:arr range:range];
free(arr);


// 마지막 원소 리턴
id* lastObj = [arrFruits lastObject];


// 특정 인덱스 위치의 원소 리턴
id* obj = [arrFruits objectAtIndex:1];


// 특정 인덱스셋에 해당되는 원소 리턴
NSArray* arrEqualIndexSet = [arrFruits objectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(2, 5)]];


// 열거자 리턴
NSEnumerator* enumFruit = [arrFruits objectEnumerator];
NSEnumerator* enumFruitReverse = [arrFruits reverseObjectEnumerator];


// 특정 오브젝트의 인덱스 리턴, 오브젝트가 배열에 속하지 않은 경우 NSNotFound 리턴
NSUInteger idx = [arrFruits indexOfObject:@"Apple"];


// 지정된 범위내에 특정 오브젝트의 인덱스 리턴
idx = [arrFruits indexOfObject:@"Orange" inRange:NSMakeRange(0, 5)];


// 특정 오브젝트와 동일한 오브젝트의 인덱스 리턴
idx = [arrFruits indexOfObjectIdenticalTo:@"Banana"];


// 지정된 범위내에 특정 오브젝트와 동일한 오브젝트의 인덱스 리턴
idx = [arrFruits indexOfObjectIdenticalTo:@"Cherry" inRange:NSMakeRange(0, 5)];


// 특정 조건에 해당되는 첫번째 인덱스 리턴
ArrayTest* arrTest = [[ArrayTest alloc] init];
idx = [arrFruits indexOfObjectPassingTest:[arrTest blockTestingForTitle:@"Keyword"]];


// 배열의 모든 요소에 지정된 메시지를 보냄
[arrFruits makeObjectsPerformSelector:@selector(someSel:)];
[arrFruits makeObjectsPerformSelector:@selector(someSel:) withObject:@"arg"];


// 배열의 마지막에 새로운 오브젝트 추가
[arrEmptyMutableArray addObject:@"Apple"];


// 특정 위치에 새로운 오브젝트 추가
[arrEmptyMutableArray insertObject:@"Banana" atIndex:0];


// 특정 위치의 원소를 새로운 오브젝트로 교체
[arrEmptyMutableArray replaceObjectAtIndex:0 withObject:@"Lemon"];


// 배열에서 특정 오브젝트를 제거
[arrEmptyMutableArray removeObject:@"Cherry"];


// 배열에 존재하는 오브젝트와 일치하는 모든 오브젝트 제거
NSArray* arrDelTarget = [NSArray arrayWithObjects:@"Apple", @"Lemon"];
[arrEmptyMutableArray removeObjectsInArray:arrDelTarget];


// 배열의 특정 범위내에 존재하는 오브젝트를 제거
[arrEmptyMutableArray removeObject:@"Banana" inRange:NSMakeRange(1, 4)];


// 특정 인덱스의 요소를 제거
[arrEmptyMutableArray removeObjectAtIndex:3];


// 특정 인덱스들과 일치하는 요소를 제거
NSMutableIndexSet* indexes = [NSMutableIndexSet indexSetWithIndex:1];
[indexes addIndex:4];
[arrEmptyMutableArray removeObjectsAtIndexes:indexes];


// 배열의 마지막 요소 제거
[arrEmptyMutableArray removeLastObject];


// 배열에서 모든 요소 제거
[arrEmptyMutableArray removeAllObjects];


// 배열 비교
BOOL isEqualArray = [arrFruits isEqualToArray:arrFruitsCopy];


// 오브젝트가 포함된 새로운 배열 리턴
NSArray* newArray = [arrFruits arrayByAddingObject:@"kiwi"];


// 기존 배열이 합쳐진 새로운 배열 리턴
NSArray* arrAnotherFruits = [NSArray arrayWithObjects:@"Peach", @"Lime", @"Lemon", nil];
NSArray* newArray2 = [arrFruits arrayByAddingObjectsFromArray:arrAnotherFruits];


// 특정 조건에 해당되는 원소들이 포함된 새로운 배열 리턴
NSPredicate* predicate = [NSPredicate predicateWithFormat:@"fruitName contains[c] %@”, someWord];
NSArray* filteredArray = [arrFruits filteredArrayUsingPredicate:predicate];


// 특정 범위의 요소들로 이루어진 새로운 배열 리턴
NSArray* subArray = [arrFruits subarrayWithRange:NSMakeRange(2, 5)];


// 셀럭터를 이용해서 정렬된 새로운 배열 리턴
NSArray* sortedArray = [arrFruits sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];


// 배열의 모든 요소들을 지정된 문자열로 구분해 새로운 문자열 리턴
NSString* strArray = [arrFruits componentsJoinedByString:@", "];
NSLog(@”%@”, strArray);


// 배열의 모든 요소들을 프로퍼티 리스트 형식의 문자열로 리턴
NSString* strDescription = [arrFruits description];
NSLog(@”%@”, strDescription);


// 배열의 내용을 파일로 출력
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString* documentsDir = [paths objectAtIndex:0];
NSString* fullPath = [documentsDir stringByAppendingPathComponent:@"filename.plist"];
[arrFruits writeToURL:[NSURL URLWithString:fullPath] atomically:YES];

posted by Sunny's
2012. 3. 29. 14:06 IPhone

 

iPhone 어플에서 UIWebView 를 사용한 프로그램에서

웹뷰안에서 JavaScript 의 Alert 를 호출 하면 (ex -> javascript:alert("test some strings.");)
다음과 같이 호스트 이름이 얼럿창의 상단에 찍히게 된다.

보안때문에 상단의 ip 는 지웠지만 만약 웹뷰에서 lomohome.com 에서 얼럿창을 띄웠다면 lomohome.com 이라는 문구가 얼럿창의 타이틀에 뜨게 된다.

이 얼럿창은 UIWebView 에 카테고리를 이용하여 딜리게이트 메소드를 구현해주면 수정할 수 있다.
먼저 UIWebView 의 헤더파일에 다음과 같은 인터페이스를 추가해준다.

//@Geunwon,Mo 2010.9.17 : UIWebView Javascript alert 위한 카테고리.

@interface UIWebView (JavaScriptAlert)

- (void)webView:(UIWebView *)sender runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WebFrame *)frame;

@end


그리고 구현파일에 구현해준다.

//@Geunwon,Mo 2010.9.17 : UIWebView Javascript alert 위한 카테고리.

@implementation UIWebView (JavaScriptAlert)

- (void)webView:(UIWebView *)sender runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WebFrame *)frame {

NSLog(@"javascript alert : %@",message);

UIAlertView* customAlert = [[UIAlertView alloc] initWithTitle:@"Hana Bank" message:message delegate:nil cancelButtonTitle:@"확인" otherButtonTitles:nil];

[customAlert show];

[customAlert autorelease];

}

@end


요렇게 구현하고 나면 다음과 같이 Title 에 원하는 문구로 자바스크립트 얼럿을 띄울 수 있다.



구현 메소드 중, 타이틀 인자를 nil 로 넣으면 아무것도 안찍힌다.

UIAlertView* customAlert = [[UIAlertView alloc] initWithTitle:nil message:message delegate:nil cancelButtonTitle:@"확인" otherButtonTitles:nil];



posted by Sunny's
2012. 3. 28. 21:03 IPhone

 

 

전달 받을 컨트롤러 에서 NotificationCenter에 옵져버 등록 한다.

NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self selector:@selector(myFunction:) name:@"msgName" object:nil];


myFunction 함수 구현도 필요
-(void) myFunction:(NSNotification *) note {
[[note userInfo] objectForKey:@"myKey"]; // 메시지의 내의 myKey 라는 값을 가져온다.
}


통지를 보내는 쪽 에서 처리
// myKey라는 키로 value 라는 문자열을 전달 한다.
NSDictionary *dic = [NSDictionary dictionaryWithOjbect:@"value" forKey:@"myKey"];

NSNotificationCenter * nc = [NSNotificationCenter defaultCenter];
[nc postNotificationName:@"msgName" object:self userInfo:dic];


통지를 보내면 통지를 등록한 컨트롤로에 정의된 myFunction 함수가 호출된다.

◆ 데이터 여러개 보낼때
NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:EDIT_MAIN_TABLE], @"type",[NSNumber numberWithBool:YES], @"edit", nil];

◆ 데이터 하나만 보낼때
NSDictionary *dic = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:CARD_TYPE_MEMBERSHIP] forKey:@"type"];

출처 : http://comxp.tistory.com/188 


posted by Sunny's
2011. 12. 23. 10:01 IPhone

iPhone FBConnect: Facebook Connect Tutorial

Now a days social networking websites like facebook are becoming very popular, so integrating facebook with app has become a necessity to make you application popular. We are going to do the same through this tutorial. The Facebook Connect SDK provides code which third-party developers can embed into their applications to connect to their Facebook accounts and exchange information with iPhone apps. It’s a way of embedding “social context” to an iPhone app, according to Facebook.

Create a Viewbased Application with name ‘FacebookAPI’.

Prerequisite:
1.Download Facebook Connect for iPhone SDK (http://svn.facebook.com/svnroot/platform/clients/packages/fbconnect-iphone.zip) or you can download same from here 
Just go through the project. In particular, the “Connect” sample project. Sample Project gives demo of some of the functionality.

1.1.Open src/FBConnect.xcodeproj from SDK that you downloaded, and your own project as well.

1.2.Drag n drop FBConnect group. Make sure “Copy items into destination group folder” is NOT checked. It should look as shown below

1.3.Go to Project Menu ->Edit project settings and scroll down to “User Header Search Path” add entry which will point to “src folder”

1.4.To test import all .m n .h files in case any miss. And compile.

2.Login to Facebook. After that go to Developers Page (http://www.facebook.com/developers/) as shown below.

3.Register your application with Facebook

3.1.Click on Set up New Application Button in the upper right hand corner.

3.2.Give Application name and click on create application button. Then you will see new application screen with detail including “API key”and “API Secret Key”

Note : This application will not work until you provide your Facebook application’s API keys.

Now to get started with actual coding:

Append Following code in FacebookAPIAppDelegate.h

#import<UIKit/UIKit.h>
#import "FBConnect/FBConnect.h"
#import "FBConnect/FBSession.h"

@class FacebookAPIViewController;

@interface FacebookAPIAppDelegate : NSObject  {
          UIWindow *window;
          FacebookAPIViewController *viewController;
          FBSession *_session;
}

@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet
                           FacebookAPIViewController *viewController;
@property (nonatomic,retain) FBSession *_session;
@end

Append Following code in FacebookAPIAppDelegate.m

#import "FacebookAPIAppDelegate.h"
#import "FacebookAPIViewController.h"

@implementation FacebookAPIAppDelegate

@synthesize window;
@synthesize viewController;
@synthesize _session;

- (void)applicationDidFinishLaunching:(UIApplication *)application {

// Override point for customization after app launch
[window addSubview:viewController.view];
[window makeKeyAndVisible];
}

- (void)dealloc {
          [_session release];
          [viewController release];
          [window release];
          [super dealloc];
}

@end

Here in FacebookAPIAppDelegate we have just declared _session variable of type FBSession to keep track of the session and to check if session for current user exists or not.

Append Following code in FacebookAPIViewController.h

#import <UIKit/UIKit.h>

#import "FBConnect/FBConnect.h"
#import "FBConnect/FBSession.h"

@interface FacebookAPIViewController : UIViewController   {
             FBLoginButton *loginButton;
             UIAlertView *facebookAlert;
             FBSession *usersession;
             NSString *username;
             BOOL post;
}

@property(nonatomic,retain) FBLoginButton *loginButton;
@property(nonatomic,retain)	UIAlertView *facebookAlert;
@property(nonatomic,retain)  FBSession *usersession;
@property(nonatomic,retain) NSString *username;
@property(nonatomic,assign) BOOL post;

- (BOOL)textFieldShouldReturn:(UITextField *)textField;
-(void)getFacebookName;
-(void)postToWall;

@end

Append Following code in FacebookAPIViewController.m

#import "FacebookAPIViewController.h"
#import "FacebookAPIAppDelegate.h"

#define _APP_KEY @"Your API Key Goes here"
#define _SECRET_KEY @"Your Secrete Key Goes here"

@implementation FacebookAPIViewController
@synthesize loginButton;
@synthesize facebookAlert;
@synthesize usersession;
@synthesize username;
@synthesize post;

- (void)viewDidLoad {
               FacebookAPIAppDelegate *appDelegate =
                          (FacebookAPIAppDelegate *)   [[UIApplication
                                            sharedApplication]delegate];
                if (appDelegate._session == nil){
                appDelegate._session = [FBSession
                                   sessionForApplication:_APP_KEY
                                   secret:_SECRET_KEY delegate:self];
                 }
                 if(self.loginButton == NULL)
                 self.loginButton = [[[FBLoginButton alloc] init] autorelease];
                 loginButton.frame = CGRectMake(0, 0, 100, 50);
                 [self.view addSubview:loginButton];

                 [super viewDidLoad];
}

- (void)dealloc {
               [username release];
               [usersession release];
               [loginButton release];
               [super dealloc];
}

- (void)session:(FBSession*)session didLogin:(FBUID)uid {
                self.usersession =session;
                NSLog(@"User with id %lld logged in.", uid);
                [self getFacebookName];
}

- (void)getFacebookName {
         NSString* fql = [NSString stringWithFormat:
         @"select uid,name from user where uid == %lld",
                               self.usersession.uid];
        NSDictionary* params =
        [NSDictionary dictionaryWithObject:fql
        forKey:@"query"];
   [[FBRequest requestWithDelegate:self]
  call:@"facebook.fql.query" params:params];
   self.post=YES;
}

- (void)request:(FBRequest*)request didLoad:(id)result {
              if ([request.method isEqualToString:@"facebook.fql.query"]) {
                          NSArray* users = result;
                          NSDictionary* user = [users objectAtIndex:0];
                          NSString* name = [user objectForKey:@"name"];
                          self.username = name;

                          if (self.post) {
                                     [self postToWall];
                                     self.post = NO;
                          }
              }
}

- (void)postToWall {

               FBStreamDialog *dialog = [[[FBStreamDialog alloc] init]
                                             autorelease];
               dialog.userMessagePrompt = @"Enter your message:";
               dialog.attachment = [NSString
                    stringWithFormat:@"{\"name\":\"Facebook Connect for
                    iPhone\",\"href\":\"http://developers.facebook.com/
                    connect.phptab=iphone\",\"caption\":\"Caption\",
                    \"description\":\"Description\",\"media\":[{\"type\":
                    \"image\",\"src\":\"http://img40.yfrog.com/img40/
                     5914/iphoneconnectbtn.jpg\",\"href\":
                     \"http://developers.facebook.com/connect.php?
                      tab=iphone/\"}],\"properties\":{\"another link\":
                      {\"text\":\"Facebook home page\",\"href\":
                      \"http://www.facebook.com\"}}}"];

               [dialog show];

}

- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
                [textField resignFirstResponder];
                return YES;
}

@end

Define API key and Secret key with the keys you received while registering your app on facebook.

#define _APP_KEY @"43e37a535cc09c2013bd76fde78dfcc7"
#define _SECRET_KEY @"cc14801521a0c4d1dc31b7cacb891072"

Validate session variable in ViewDidLoad. If it doesn’t exist then create the same for using API key and Secret key. For that, one needs to conform the protocol FBSessionDelegate in respective header file. Also create a login button using FBLoginButton.

While implementing protocol FBSessionDelegate one needs to implement following mandatory method

(void)session:(FBSession*)session didLogin:(FBUID)uid

This methos is automatically called when user is logged in using FBConnect SDK.
In this method we get session for that user and it’s uid which unique identifier for that user.

Once FBSession session is avaiable, we can accesss all the APIs provided by Facebook.
For now, we will see how to post user name and status on the facebook wall.

To get Facebook username a request is send in which select query is written to get username using uid.

NSString* fql = [NSString stringWithFormat:
@"select uid,name from user where uid == %lld", self.usersession.uid];
NSDictionary* params = [NSDictionary dictionaryWithObject:fql forKey:@"query"];
[[FBRequest requestWithDelegate:self] call:@"facebook.fql.query" params:params];

Override following FBRequestDelegate method to check the reponse of above query.

(void)request:(FBRequest*)request didLoad:(id)result

The argument result is an array of NSDictionary Objects which contains info for that user as key-value pairs. Retrieve it as follows:

NSArray* users = result;
NSDictionary* user = [users objectAtIndex:0];
NSString* name = [user objectForKey:@"name"];

Use FBStreamDialog class post message on the facbook wall. A dialog pops up with a message box to post on Wall.

FBStreamDialog *dialog = [[[FBStreamDialog alloc] init] autorelease];
dialog.userMessagePrompt = @"Enter your message:";
dialog.attachment = [NSString stringWithFormat:@"{\"name\":\"Facebook Connect for iPhone\",\"href\":\"http://developers.facebook.com/connect.php?tab=iphone\",\"caption\":\"Caption\",\"description\":\"Description\",\"media\":[{\"type\":\"image\",\"src\":\"http://img40.yfrog.com/img40/5914/iphoneconnectbtn.jpg\",\"href\":\"http://developers.facebook.com/connect.php?tab=iphone/\"}],\"properties\":{\"another link\":{\"text\":\"Facebook home page\",\"href\":\"http://www.facebook.com\"}}}"];
[dialog show];

Now Save project (Command +S). Build and Run Project.
Simulator will look like as follows

Click on Fconnect Button and Facebook Login Dialog will appear.

Login with your user name and Password . Wait for untill post to Wall Dialog pops up

The Msg on Facebook will something look like this

You can download the source code from here 


/*****************************************************************************************************/

따라해서 되긴 했는데... 해석이 되야 말이지 ㅋㅋ
아 앞날이 깜깜하네 ㅋㅋㅋㅋ 

어쨌든 좋은 자료 스크랩!! :) 


posted by Sunny's
2011. 12. 9. 10:57 IPhone

프로젝트 > Build Settions>Architectures

Release에 armv6 항목을 추가 하기만 하면된다.
그냥 추가만 하면 될것을 삽질좀 했다..ㅋ




posted by Sunny's
2011. 11. 6. 02:58 IPhone


- (void)viewDidLoad
{
    [super viewDidLoad];
 
    dispatch_async(kBgQueue, ^{
        NSData* data = [NSData dataWithContentsOfURL: 
          kLatestKivaLoansURL];
        [self performSelectorOnMainThread:@selector(fetchedData:) 
          withObject:data waitUntilDone:YES];
    });
}
- (void)fetchedData:(NSData *)responseData {
    //parse out the json data
    NSError* error;
    NSDictionary* json = [NSJSONSerialization 
        JSONObjectWithData:responseData //1
 
        options:kNilOptions 
        error:&error];
 
    NSArray* latestLoans = [json objectForKey:@"loans"]; //2
 
    NSLog(@"loans: %@", latestLoans); //3
}




NSString *country = [loan objectForKey:@"name"] ;
NSString *country = [(NSDictionary*)[loan objectForKey:@"location"] objectForKey:@"country"];

JSON Parse 객체는 SBJSON 을 써도 동일하며 멀티 항목인 경우 (NSDictionary*)로 캐스팅 하는거에 참고하세요~ ^^*

출처 : http://www.raywenderlich.com/5492/working-with-json-in-ios-5
posted by Sunny's
2011. 10. 31. 16:37 IPhone

Block & GCD를 이용한 async 처리

dispatch_queue_t image_queue = dispatch_queue_create("image_que", NULL);

    dispatch_async(image_queue, ^{

        NSData *iconData = [NSData dataWithContentsOfURL:[NSURL URLWithString:selectedExample.iconPath]];

        _iconImageView.image = [UIImage imageWithData:iconData];

        

        // UI 메인 쓰레드에서 변경되어야 하므로...

        dispatch_async(dispatch_get_main_queue(), ^{

            _iconImageView.image = [UIImage imageWithData:iconData];

        });

    });




posted by Sunny's
2011. 10. 31. 15:12 IPhone

There are a lot of options when it comes to parsing XML on the iPhone. The iPhone SDK comes with two different libraries to choose from, and there are several popular third party libraries available such as TBXML, TouchXML, KissXML, TinyXML, and GDataXML. How is a developer to choose?

I have been recently taking a look at the various options out there, and ended up extending the XMLPerformance sample from Apple to try out each of the above libraries to learn how they worked and compare their performance. I thought I’d share what I’ve learned thus far to others who might be searching for the best XML library for their iPhone project.

In this article we’ll give a detailed comparison of the features and performance of the most popular iPhone libraries, explain how to choose between them, and give a sample project showing how to read XML data using each of the above libraries.

SAX vs. DOM

Before we begin, I wanted to make sure everyone is aware of the most important difference between XML parsers: whether the parser is a SAX or a DOM parser.

  • SAX parser is one where your code is notified as the parser walks through the XML tree, and you are responsible for keeping track of state and constructing any objects you might want to keep track of the data as the parser marches through.
  • A DOM parser reads the entire document and builds up an in-memory representation that you can query for different elements. Often, you can even construct XPath queries to pull out particular pieces.

Ok, now let’s discuss some of the libraries!

The Most Popular XML Parsers for the iPhone

In my research, here’s what seemed to me to be the most popular XML Parsers for the iPhone, and a brief description of each one:

  • NSXMLParser is a SAX parser included by default with the iPhone SDK. It’s written in Objective-C and is quite straightforward to use, but perhaps not quite as easy as the DOM model.
  • libxml2 is an Open Source library that is included by default with the iPhone SDK. It is a C-based API, so is a bit more work to use than NSXML. The library supports both DOM and SAX processing. The libxml2 SAX processor is especially cool, as it has a unique feature of being able to parse the data as it’s being read. For example, you could be reading a large XML document from the network and displaying data that you’re reading for it to the user while you’re still downloading.
  • TBXML is a lightweight DOM XML parser designed to be as quick as possible while consuming few memory resources. It saves time by not performing validation, not supporting XPath, and by being read-only – i.e. you can read XML with it, but you can’t then modify the XML and write it back out again.
  • TouchXML is an NSXML style DOM XML parser for the iPhone. Like TBXML, it is also read-only, but unlike TBXML it does support XPath.
  • KissXML is another NSSXML style DOM XML parser for the iPhone, actually based on TouchXML. The main difference is KissXML also supports editing and writing XML as well as reading.
  • TinyXML is a small C-based DOM XML parser that consists of just four C files and two headers. It supports both reading and writing XML documents, but it does not support XPath on its own. However, you can use a related library – TinyXPath – for that.
  • GDataXML is yet another NSXML style DOM XML parser for the iPhone, developed by Google as part of their Objective-C client library. Consisting of just a M file and a header, it supports both reading and writing XML documents and XPath queries.

Ok, now let’s start comparing all these libraries!

XML Parser Performance Comparison App

XML Parser Stats Display in Test App

Apple has made an excellent code sample called XMLPerformance that allows you to compare the time it takes to parse a ~900KB XML document containing the top 300 iTunes songs with both the NSXML and libxml2 APIs.

The sample allows you to choose a parsing method and then parse the document, and it keeps statistics on how long it took to download the file and parse the file in a database. You can then go to a statistics screen to see the average download and parse times for each method.

I thought this would be an ideal way to test out how these various APIs performed against each other, so I extended the sample to include all of the above libraries. You can download the updated project below if you want to try it out on your device. It also serves as a nice example of how to use each of the above APIs!

Download Updated XMLPerformance Project

A note on the project: if the library included XPath support, I used it for a single lookup, because I felt it represented the way the library would be used in practice. But of course XPath is generally slower than manually walking through the tree, so it adds to the benchmarks for those libraries.

So anyway – I’ll discuss the results of how things performed on my device here with the sample written as-is – but feel free to give it a shot on your device, or tweak the code based on the actual XML data you need to parse!

XML Parser Performance Comparison

Here’s some graphs that shows how quickly the various parsers parsed the XML document on my device (an iPhone 3Gs):

Parsing Time By Parser

As you can see here, NSXMLParser was the slowest method by far. TBXML was the fastest, which makes sense because many features were taken out in order to optimize parse time for reading only.

I was surprised, however, to see that TBXML and some of the other DOM parsing methods performed faster than libxml2′s SAX parser, which I had thought would be the fastest of all of the methods. I haven’t profiled it, but my guess as to why it is slower is because of the frequent string compares needed to parse the document in the SAX method.

However, don’t discount libxml2′s SAX method by looking at this chart. Remember that libxml2 is the only one of these methods that can parse the document as it’s reading in – so it can let your app start displaying data right away rather than having to let the download finish first.

Ok, here’s a graph that shows the peak memory usage by parser (this was obtained through running the various methods through the Object Allocations tool):

Memory Usage By Parser

Note that the DOM methods usually require more memory overhead than the SAX methods (with the exception of TBXML, which is indeed quite efficient). This is something to consider when you are dealing with especially large documents, given the memory constraints on an iPhone.

Also note that libxml2′s SAX method is the best option as far as peak memory usage is concerned (and I suspect it would scale better than the others as well).

Finally, let’s wrap up with a chart that summarizes the differences between the parsers and everything we’ve discussed above:

NSXMLlibxml2 – SAXTBXMLTouchXMLKissXMLTinyXMLGDataXMLlibxml2 – DOM
Included with SDK? Yes Yes No No No No No Yes
Seconds to Parse 1.87 1.19 0.68 1.1 1.37 1.27 1.07 0.84
Peak Memory Usage 3.11 3.01 3.07 6.5 5.25 4.8 4.15 4.97
Parse While Downloading? No Yes No No No No No No
Edit/Save XML? No No No No Yes Yes Yes Yes
XPath Support? No No No Yes Yes Yes* Yes Yes
C or Obj-C Obj-C C Obj-C Obj-C Obj-C C Obj-C C
License Apple MIT MIT MIT MIT ZLib Apache MIT

* = with TinyXPath

Which To Choose?

Which XML parser to choose really depends on what you want to do with the parser.

  • If you just want to read small XML documents, performance doesn’t matter as much with small documents. You probably want to pick something with XPath support and something that is written in Objective-C to make your job easier. So I’d recommend either TouchXML, KissXML, or GDataXML for this case.
  • If you want to both read and write small XML documents, again performance doesn’t matter as much as functionality and ease of use. You probably want to pick something with XPath support, written in Objective-C, with read/write capability. So I’d recommend KissXML or GDataXML for this case.
  • If you want to read extremely large XML documents, performance is the critical issue here. You’ll want to consider libxml2 SAX, TBXML, or libxml DOM for this, depending on what your exact situation is.

What about the ones I didn’t mention?

  • NSXML is a decent choice if you’re dealing with relatively small documents, and you don’t feel like adding a third party library to the SDK.
  • TinyXML could be an OK choice for medium sized documents if you already have experience with the API and are comfortable with C as it ports quite easily over to the iPhone.

I took a look at two other XML libraries during the course of this investigation (VTD-XML and Objective-XML), but I couldn’t get them working. If someone else has had more luck with these, feel free to extend the sample project to include them!

Where To Go From Here?

If you’re looking for some help using one of these libraries, check out my post on How to Read and Write XML Documents with GDataXML.

And if anyone has any additional feedback about these libraries or tips that may help other developers, please chime in below!

출처 : http://www.raywenderlich.com/553
posted by Sunny's
2011. 10. 31. 13:33 IPhone

The Motivation

I've always wondered why the Foundation and Cocoa frameworks in Objective-C are so biased towards the delegate pattern. Don't get me wrong, I don't have anything against it. But there are some cases where using the observer pattern would make more sense. Take, for instance, the NSAnimationDelegate protocol. Most of the 'delegate' methods are actually just state change notifications. Out of the five methods in this protocol only one is an actual delegate method:animation:valueForProgress:.

The absence of the observer pattern, especially in the UI classes, prompted me write a reusable observable class to use in my custom UI code. Similar to Java's Observable class.

The Problem

Probably the biggest implementation difference between the observer pattern and the delegate pattern is that observable objects support multiple observers, while the delegate is just one object. But this is precisely what makes the observer pattern one of my favorites. It is also what makes it harder to implement.

Also, doing a bullet-proof implementation requires handling the case of an observer being added or removed inside a notification call. The observer collection cannot mutate while iterating so it needs a clever way of handling this (for some ways of doing this look here).

The Solution

This is how the Observable class looks like:
@interface Observable : NSObject
- (void)addObserver:(id<NSObject>)observer;
- (void)removeObserver:(id<NSObject>)observer;
- (void)notifyObservers:(NSInvocation*)invocation;
@end
It is pretty standard, except that you pass an NSInvocation when you want to send a notification. This is so that we have flexibility with observer protocols. If you haven't, you might want to check out the previous post: Making NSInvocations, but more on this later.

We start by creating the observer collection. Since this is Objective-C (possibly for iOS, e.g. iPhone), we need to be careful not to retain the observers to avoid circular references. So we need to create a non-retaining mutable set:
observers = (NSMutableSet*)CFSetCreateMutable(NULL, 0, NULL);
The reason it is a set and not an array is to make adding and removing observers faster.

And here is how you notify the observers:
- (void)notifyObservers:(NSInvocation*)invocation {
  notifying = YES;
  for (id<NSObject> observer in observers) {
    if (![pendingRemoves containsObject:observer] && [observer respondsToSelector:[invocation selector]]) {
      [invocation setTarget:observer];
      [invocation invoke];
    }
  }
  notifying = NO;
  [self commitPending];
}
The notifying flag and the commitPending method call are there to handle addition and removal of observers inside a notification. If the notifying flag is set then we don't add the observer to the main observers collection. We instead add it to a temporary collection (pendingAdds) and only in commitPending do we actually add it to the main observers collection. Here is the code:
- (void)addObserver:(id<NSObject>)observer {
  if (notifying) {
    [pendingRemoves removeObject:observer];
    [pendingAdds addObject:observer];
  } else {
    [observers addObject:observer];
  }
}
The code for removeObserver: is very similar and the code for commitPending is straight forward.

Conclusion

Let me finish by showing how you would use this. Let's say you have an animation class you want to make observable. You want to receive notification for the animation starting or stopping:
@protocol AnimationObserver
- (void)animationDidStart;
- (void)animationDidStop;
@end
Here is how you would implement the Animation class:
@interface Animation : Observable
...
- (void)start;
- (void)stop;
@end

@implementation Animation
...
- (void)start {
  ...
  NSInvocation* inv = [NSInvocation invocationWithProtocol:@protocol(AnimationObserver)
                                                  selector:@selector(animationDidStart)]
  [self notifyObservers:inv];
}

- (void)stop {
  ...
  NSInvocation* inv = [NSInvocation invocationWithProtocol:@protocol(AnimationObserver)
                                                  selector:@selector(animationDidStop)]
  [self notifyObservers:inv];
}
@end
Notice how it uses the invocationWithProtocol:selector: method from the previous post, Making NSInvocations. Actually this is precisely the use case I had in mind when I implemented the NSInvocation additions. 

So there you have it. For more information on the observer pattern you can check out the Wikipedia entry or the GOF book. If you have questions or further improvements feel free to leave a comment.

The source code for this article, including unit tests, is available at GitHub. To compile you will need Google Toolbox for Mac.

출처 : http://www.a-coding.com/2010/10/observer-pattern-in-objective-c.html 
posted by Sunny's
2011. 9. 26. 09:35 IPhone

UPDATE: We are now on v1.2 of the Windows Azure Toolkit for iOS, and consequently there have been a number of important updates to the toolkit, including support for Queues, the Windows Azure Access Control Service, APNS, code refactoring, and more. For the latest information, please refer to the following blog posts:

I am extremely excited to announce the immediate availability of the Windows Azure Toolkit for iOS!

This first release of the Windows Azure Toolkit for iOS provides an easy and convenient way of accessing Windows Azure storage from iOS-based applications. As with the Windows Azure Toolkit for Windows Phone 7 we will continue to bring additional capabilities to the toolkit, such as push notifications, Access Control Service, and more.

iOSImage1iOSImage2iOSImage3

You can get the toolkit—and all the source code—on github:

The toolkit works in two ways: the toolkit can be used to access Windows Azure storage directly, or alternatively, can go through a proxy service. The proxy service code is the same code as used in the Windows Azure Toolkit for Windows Phone 7 and negates the need for the developer to store the Azure storage credentials locally on the device.

The release of the Windows Azure Toolkit for iOS is a significant milestone, and reinforces my opinion that Windows Azure is a great place to run services for mobile applications.

Setting up your Windows Azure services

To quickly get your mobile services up and running in Windows Azure, take a look at the Cloud Ready Package for Devices (found under downloads in https://github.com/microsoft-dpe/watoolkitios-lib).

The Cloud Ready Package for Devices is designed to make it easier for you to build mobile applications that leverage cloud services running in Windows Azure. Instead of having to open up Visual Studio and compile a solution with the services you want to use, we provide you with the Windows Azure CSPKG and CSCFG files prebuilt – all you need to do is update the configuration file to point to your account.

In this video, you’ll see how easy it is to deploy this package to Windows Azure regardless of your operating system (e.g. Windows 7 or OSX) and target device (e.g. Windows Phone 7, iOS, or Android).

Unpacking the v1.0.0 library zip file

You can download the compiled storage library on github (found under downloads in https://github.com/microsoft-dpe/watoolkitios-lib). When you upzip the zip file, you’ll find several folders:

  • /4.3-device – the library binary for iOS 4.3 (device)
  • /4.3-simulator – the library binary for iOS 4.3 (simulator)
  • /include – the headers for the library

Creating your first project using the toolkit

If you are not familiar with XCode, this is a short tutorial for getting your first project up and running. Launch XCode 4 and create a new project:

clip_image002[4]_thumb

Select a View-based application and click Next.

Give the project a name and company. For the purposes of this walkthrough, we’ll call it “FirstAzureProject”. Do not include Unit Tests.

clip_image004[4]_thumb

Pick a folder to save the project to, and uncheck the source code repository checkbox.

When the project opens, right click on the Frameworks folder and select “Add Files to…”

clip_image006[4]_thumb

Locate the libwatoolkitios.a library file from the download package folder (from either the simulator or device folder), and add it to the Frameworks folder.

image

Now, click on the top most project (FirstAzureProject) in the left hand column. Click on the target in the second column. Click on the “Build Settings” header in the third column. Ensure that the “All” button is selected to show all settings.

In the search box, type in “header search” and look for an entry called “Header Search Paths”:

image

Double-click on this line (towards the right of the line), and click on the “+” button in the lower left.

image

Add the path to where the folder containing the header files are located (this is the include folder from the download). For example, "~/Desktop/v1.0.0/include" if you have extracted the folder on your desktop. Be sure to encapsulate in quotes if you have spaces in the path.

image

Now, click on the “Build Phases” tab and expand the “Link Binary with Libraries” section:

image

Click on the “+” button in the lower left, and scroll down until you find a library called “libxml2.2.7.3.dylib”. Add this library to your project.

Testing Everything Works

Now that you’ve added all of the required references, let’s test that the library can be called. To do this, double click on the [ProjectName]AppDelegate.m file (e.g. FirstAzureProjectAppDelegate.m), and add the following imports to the class:

    #import "AuthenticationCredential.h"

    #import "CloudStorageClient.h"

Perform a build. If the build succeeds, the library is correctly added to the project. If it fails, it is recommended to go back and check the header search paths.

Assuming it builds, in the .m file, add the following declarations after the @synthesize lines:

    AuthenticationCredential *credential;

    CloudStorageClient *client;

Now, add the following lines after the [self.window makeKeyAndVisible] line in the didFinishLaunchingWithOptions method:

    credential = [AuthenticationCredential credentialWithAzureServiceAccount:@"ACCOUNT_NAME" accessKey:@"ACCOUNT_KEY"];

    client = [CloudStorageClient storageClientWithCredential:credential];

    [client getBlobContainersWithBlock:^(NSArray* containers, NSError* error)

    {

    if (error)

    {

    NSLog(@"%@",[error localizedDescription]);

    }

    else

    {

    NSLog(@"%i containers were found…",[containers count]);

    }

    }];

Be sure to replace ACCOUNT_NAME and ACCOUNT_KEY with your Windows Azure storage account name and key, available on the Windows Azure portal (http://windows.azure.com).

Build and run the project. You should something similar to the following output in the debug window:

    2011-05-06 18:18:46.001 FirstAzureProject[27456:207] 2 containers were found…

The last line shows that this account has 2 containers. This will of course vary, depending on how many blob containers you have setup in your own Windows Azure account.

Doing more with the toolkit

Feel free to explore the class documentation to explore more of the toolkit API. To help, here are some additional examples:

In [ProjectName]AppDelegate.m class, add the following headers:

    #import "AuthenticationCredential.h"

    #import "CloudStorageClient.h"

    #import "BlobContainer.h"

    #import "Blob.h"

    #import "TableEntity.h"

    #import "TableFetchRequest.h"

In the didFinishLaunchingWithOptions method, after the [self.window makeKeyAndVisible] line, try testing a few of the following commands. Again, running the project will return results into the debugger window.

To authenticate using account name and key:

    credential = [AuthenticationCredential credentialWithAzureServiceAccount:@"ACCOUNT_NAME" accessKey:@"ACCOUNT_KEY"];

To authenticate instead using the proxy service from the Windows Phone 7 toolkit, you can use the following:

    credential = [AuthenticationCredential authenticateCredentialWithProxyURL:[NSURL URLWithString:@"PROXY_URL"] user:@"USERNAME" password:@"PASSWORD" withBlock:^(NSError *error)

    {

    if (error)

    {

    NSLog(@"%@",[error localizedDescription]);

    }

    else

    {

    NSLog(@"Successfully logged in");

    }

    }];

Replace the PROXY_URL, USERNAME, and PASSWORD with the information required to access your proxy service.

To create a new client using the credentials:

    client = [CloudStorageClient storageClientWithCredential:credential];

To list all blob containers (this method is not supported via the proxy server):

    // get all blob containers

    [client getBlobContainersWithBlock:^(NSArray *containers, NSError *error)

    {

    if (error)

    {

    NSLog(@"%@",[error localizedDescription]);

    }

    else

    {

    NSLog(@"%i containers were found…",[containers count]);

    }

    }];

To get all blobs within a container (this also is not supported by the proxy):

    // get all blobs within a container

    [client getBlobs:@"images" withBlock:^(NSArray *blobs, NSError *error)

    {

    if (error)

    {

    NSLog(@"%@",[error localizedDescription]);

    }

    else

    {

    NSLog(@"%i blobs were found in the images container…",[blobs count]);

    }

    }];

To get all tables from storage (this works with both direct access and proxy):

    // get all tables

    [client getTablesWithBlock:^(NSArray* tables, NSError* error)

    {

    if (error)

    {

    NSLog(@"%@",[error localizedDescription]);

    }

    else

    {

    NSLog(@"%i tables found",[tables count]);

    }

    }];

To create a table (works with both direct access and proxy):

    // create table

    [client createTableNamed:@"wadestable" withBlock:^(NSError *error)

    {

    if (error)

    {

    NSLog(@"%@",[error localizedDescription]);

    }

    else

    {

    NSLog(@"Table created");

    }

    }];

To delete a table (works with both direct access and proxy):

    //delete a table

    [client deleteTableNamed:@"wadestable" withBlock:^(NSError *error)

    {

    if (error)

    {

    NSLog(@"%@",[error localizedDescription]);

    }

    else

    {

    NSLog(@"Table was deleted");

    }

    }];

To get entities for a table (works with both account key and proxy):

    // get entities for table developers

    TableFetchRequest* fetchRequest = [TableFetchRequest fetchRequestForTable:@"Developers"];

    [client getEntities:fetchRequest withBlock:^(NSArray *entities, NSError *error)

    {

    if (error)

    {

    NSLog(@"%@",[error localizedDescription]);

    }

    else

    {

    NSLog(@"%i entities found in the developer table",[entities count]);

    }

    }];

To get entities for a table using predicate (works with both account key and proxy):

    // get entities for table developers with predicate request

    NSError* error = nil;

    NSPredicate* predicate = [NSPredicate predicateWithFormat:@"Name = 'Wade' || Name = 'Vittorio' || Name = 'Nathan'"];

    TableFetchRequest* anotherFetchRequest = [TableFetchRequest fetchRequestForTable:@"Developers" predicate:predicate error:&error];

    [client getEntities:anotherFetchRequest withBlock:^(NSArray *entities, NSError *error)

    {

    if (error)

    {

    NSLog(@"%@",[error localizedDescription]);

    }

    else

    {

    NSLog(@"%i entities returned by this request",[entities count]);

    }

    }];

Doing even more with the toolkit

If you are looking to explore the toolkit further, I recommend looking at the sample application that can be found in the watoolkitios-samples project. This project demonstrates all of the functionality of the toolkit, including creating, uploading, and retrieving entities from both table and blob storage.

출처 : http://www.wadewegner.com/2011/05/windows-azure-toolkit-for-ios/

 http://watwp.codeplex.com/


posted by Sunny's