2012年11月28日 星期三

ios http post a file

使用NSMutableURLRequest以及NSURLConnection:
-(void) uploadBinary:(NSData * ) binary withURL:(NSString * ) urlAddress withAttName:(NSString *) attname andFilename:(NSString *) filename{
    
    NSURL *theURL = [NSURL URLWithString:urlAddress];
    NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:theURL 
                                                              cachePolicy:NSURLRequestReloadIgnoringCacheData 
                                                          timeoutInterval:20.0f];
    [theRequest setHTTPMethod:@"POST"];
    NSString *boundary = [[NSProcessInfo processInfo] globallyUniqueString];
    NSString *boundaryString = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
    [theRequest addValue:boundaryString forHTTPHeaderField:@"Content-Type"];
    
    // define boundary separator...
    NSString *boundarySeparator = [NSString stringWithFormat:@"--%@\r\n", boundary];
    
    //adding the body...
    NSMutableData *postBody = [NSMutableData data];

    [postBody appendData:[boundarySeparator dataUsingEncoding:NSUTF8StringEncoding]];
    [postBody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n",attname, filename] dataUsingEncoding:NSUTF8StringEncoding]];
    [postBody appendData:[@"Content-Type: application/octet-stream\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
    [postBody appendData:binary];
    
    [postBody appendData:[[NSString stringWithFormat:@"\r\n--%@--\r \n",boundary]
                          dataUsingEncoding:NSUTF8StringEncoding]];
    [theRequest setHTTPBody:postBody];    
    
    
    [[[NSURLConnection alloc] initWithRequest:theRequest delegate:self] autorelease];


另一種簡單的方式可以使用ASIFormDataRequest from ASIHTTPRequest lib:


ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request setRequestMethod:@"POST"];
            
[request setFile:dataDir forKey:nil];

[request setDelegate:self];
[request startAsynchronous];

=========

- (void) requestFinished:(ASIHTTPRequest *)request {
    //NSString *responseString = [request responseString];
    NSLog(@"Response %d : %@", request.responseStatusCode, [request responseString]);
    
    //NSData *responseData = [request responseData];
}

- (void) requestStarted:(ASIHTTPRequest *) request {
    NSLog(@"request started...");
}

- (void) requestFailed:(ASIHTTPRequest *) request {
    NSError *error = [request error];
    NSLog(@"%@", error);
}

2012年10月4日 星期四

iOS與Facebook SDK連結,以及簡單貼文

第一步必須在AppDelegate的地方接住http近來之Handler,並將此url遞給Facebook物件:

//=====In appDelegate.m=======

- (BOOL)application:(UIApplication *)application
            openURL:(NSURL *)url
  sourceApplication:(NSString *)sourceApplication
         annotation:(id)annotation {
    // attempt to extract a token from the url
   
    //利用rootViewController來取得擁有Facebook物件之viewController
    UINavigationController* testing = (UINavigationController*)self.window.rootViewController;
    IndexViewController *controller = (IndexViewController*)[testing.viewControllers objectAtIndex:1];

    //將url遞給facebook物件,之後facebook之Delegate才會驅動fbDidLogin與fbDidLogout
    return [controller.facebook handleOpenURL:url];
}

接著在擁有Facebook物件之ViewController初始化facebook,並使用NSUserDefault來記錄登入的狀態:

- (void)viewDidLoad
{
    [super viewDidLoad];

    //Facebook物件初始化,並登入AppID
    facebook = [[Facebook alloc] initWithAppId:AppID andDelegate:self];

    //使用NSUserDefault來記錄登入狀態
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    //檢查是否有用過
    if ([defaults objectForKey:@"FBAccessToken"]
        &&[defaults objectForKey:@"FBExpirationDate"]) {
        //如果沒有重新開一個
        facebook.accessToken = [defaults objectForKey:@"FBAccessToken"];
        facebook.expirationDate = [defaults objectForKey:@"FBExpirationDate"];
    }
}


登入程序:

-(void)login
{
     //檢查Facebokk是否連線還在
     if (![facebook isSessionValid]) {

        //如果已經不再連線狀態,重新連線
        //定義需要的權限
        NSArray *permissions =  [NSArray arrayWithObjects:
                                 @"user_hometown", @"read_stream", @"user_birthday",
                                 @"user_about_me", @"publish_stream", @"offline_access", nil];
        //登入
        [facebook authorize:permissions];
    }else{
        //如果已經在登入狀態的話,擷取使用者資訊
        [facebook requestWithGraphPath:@"me" andDelegate:self];
    }

}

貼文程序:

-(void)postToWall
{
    NSMutableDictionary* params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                                   AppID, @"app_id",
                                   @"http://www.google.com.tw/", @"link",
                                   @"http://www.google.com.tw/pic.jpg", @"picture",
                                   @"Facebook test", @"name",
                                   @"caption", @"caption",
                                   @"", @"description",
                                   @""@"message",
                                   nil];
    [facebook dialog:@"stream.publish" andParams:params andDelegate:self];

}

剩下一些FB之Delegate:

#pragma mark - FBRequestDelegate

- (void)requestLoading:(FBRequest *)request
{
    
}

- (void)request:(FBRequest *)request didReceiveResponse:(NSURLResponse *)response
{
    NSLog(@"received response:%@",response);
}

- (void)request:(FBRequest *)request didFailWithError:(NSError *)error
{
    
}

- (void)request:(FBRequest *)request didLoad:(id)result
{
    //利用Facebook物件request之資訊會傳遞到result,可以從這邊去收資料
    if ([result isKindOfClass:[NSArray class]] && [result count]>0) {
        result = [result objectAtIndex:0];
    }
    if ([result objectForKey:@"name"]){
        userName = [result objectForKey:@"name"];
    }
}

- (void)request:(FBRequest *)request didLoadRawResponse:(NSData *)data
{
    
}

//如果登入成功會呼叫此function
- (void)fbDidLogin {

    //擷取個人資訊,回饋資訊回從- (void)request:(FBRequest *)request didLoad:(id)result接收
    [facebook requestWithGraphPath:@"me" andDelegate:self];

    //將成功登入之資訊傳到NSUserDefault
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    [defaults setObject:[facebook accessToken] forKey:@"FBAccessToken"];
    [defaults setObject:[facebook expirationDate] forKey:@"FBExpirationDate"];
    [defaults synchronize];
}
-(void)fbDidLogout
{
    //登出時,清除帳戶資訊
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    if ([defaults objectForKey:@"FBAccessToken"]) {
        [defaults removeObjectForKey:@"FBAccessToken"];
        [defaults removeObjectForKey:@"FBExpirationDate"];
        [defaults synchronize];
    }
}










2012年10月1日 星期一

ios HTTP post and get


在ios使用http post方法:

      NSString *post = @"did=abc&uid=王大明&score=0.3,0.4,0.5,1.1,1.4";
        NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
        
        NSString *postLength = [NSString stringWithFormat:@"%d", [postData length]];
        
        NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
        [request setURL:[NSURL URLWithString:@"http://greenevent2.sunlight.tw/putdata2.asp"]];
        [request setHTTPMethod:@"POST"];
        [request setValue:postLength forHTTPHeaderField:@"Content-Length"];
        [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
        [request setHTTPBody:postData];
        NSURLConnection *conn=[[NSURLConnection alloc] initWithRequest:request delegate:self];
        if (conn)
        {
            receivedData = [NSMutableData data];
        }
        else
        {    
        }


在ios使用http get方法:

NSMutableURLRequest *request = [[NSMutableURLRequest allocinit];
[request setURL: apiUrl];
[request setHTTPMethod:@"GET"];


NSURLConnection *conn=[[NSURLConnection allocinitWithRequest:request delegate:self];
if (conn)
{
   receivedData = [NSMutableData data];
}



Delegate方法:

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
    NSLog(@"response");
    [receivedData setLength:0];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)d {
    [receivedData appendData:d];
    NSLog(@"didReceiveData");
    NSString* newStr = [[NSString alloc] initWithData:receivedData
                                             encoding:NSUTF8StringEncoding];
    NSLog(@"returnData:%@",newStr);

    //NSLog(@"receivedData:%@",receivedData);
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
    [[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Error", @"")
                                 message:[error localizedDescription]
                                delegate:nil
                       cancelButtonTitle:NSLocalizedString(@"OK", @"")
                       otherButtonTitles:nil] show];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    NSLog(@"connectionDidFinishLoading");
    /*
    NSString *responseText = [[NSString alloc] initWithData:self.data encoding:NSUTF8StringEncoding];
    
    // Do anything you want with it
    
    [responseText release];
     */
}

// Handle basic authentication challenge if needed
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
    NSString *username = @"username";
    NSString *password = @"password";
    
    NSURLCredential *credential = [NSURLCredential credentialWithUser:username
                                                             password:password
                                                          persistence:NSURLCredentialPersistenceForSession];
    [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
}

同步方式


  1. NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];           

  2. [request setURL:[NSURL URLWithString:urlStr]];  

  3. [request setHTTPMethod:@"GET"];  

  4. NSData *returnData = [NSURLConnection sendSynchronousRequest:request   
  5.                                            returningResponse:nil error:nil];   
  6.   
  7. [request release];  









2012年6月21日 星期四

在iOS上使用html parser

這裡是使用libxml2與hpple來做html parser。

1. 必須先將libxml2加到專案裡,可參考以下連結教學
http://justcoding.iteye.com/blog/1474176

2. 將hpple framework加到專案裡,
   下载hpple from https://github.com/topfunky/hpple
   加入以下檔案:HTFpple.h HTFpple.m HTFppleElement.h HTFppleElement.m XPathQuery.h XPathQuery.m

   NSString *htmlString=[NSString stringWithContentsOfURL:[NSURL URLWithString: @"http://ebook.sunlight.tw/"] encoding: NSUTF8StringEncoding error:nil];          NSData *htmlData=[htmlString dataUsingEncoding:NSUTF8StringEncoding];      TFHpple *xpathParser = [[TFHpple alloc] initWithHTMLData:htmlData];   
    NSArray *elements  = [xpathParser searchWithXPathQuery:@"/html/body/pre/a"]; // get the title    
    TFHppleElement *element  = [xpathParser peekAtSearchWithXPathQuery:@"/html/body/pre/a"];
    TFHppleElement *element2  = [xpathParser peekAtSearchWithXPathQuery:@"/html/body/pre/a[2]"];
    NSString *elementContent = [element objectForKey:@"href"];
  
    NSLog(@"result = %@",element);
     NSLog(@"result = %@",element2);
    NSLog(@"result = %@",[element attributes]);
    NSLog(@"result = %@",[element2 attributes]);

2012年6月14日 星期四

沙巴自由行

第一天
早上:8:00~11:30 飛機中
中午:Shangri-La Tanjung Aru Resort (MV)
下午:市區觀光。
DSCF3658
晚上:市區酒吧街,飯店海灘


第二天
     美人魚島深潛 AM07:00–PM17:00

晚上:飯店SPA、游泳池、Sunset Bar喝酒

第三天
早上:深海釣魚
中午:吃自己釣的魚
下午:前往Gayana島
     入住加雅娜島Gayana Eco Resort Kota Kinabalu (BAYU VILLA)
         (無人島沒有便利商店…請出發前準備好)

晚上:房間跳海浮潛 (聽說有時候有水母,請小心)
                  

第四天
早上:Gayana PADI 潛水中心,深潛、獨木舟、跳水

下午:Same
晚上:爽就好
第五天
早上:發呆
下午:回市區準備上機
晚上:17:45~21:05回程飛機

2012年6月6日 星期三

ipad上電子書製作

最近有機會要寫一些類似電子書的程式,找到了Baker framework。看起來相當方便,
想自己利用HTML + CSS + JavaScript製作iOS上頭的數位出版品app的朋友,Baker ebook framework,目前的版本,幾乎只要利用HTML、CSS、JavaScript就可以搞定,幾乎免碰Obj-C。但是如果需要修改到介面的話,可能就需要自己動手改。這framework沒有提供到書架的功能有點可惜,希望以後可以support一本以上的電子書。


可以配合Laker就可以製作出相當精美的電子書 http://www.lakercompendium.com/

下列連結為有網友中文化的Baker guide
http://b.hjwu.me/blog/2011/11/07/getting-started-with-Baker-framework/


設計

利用 Baker 創建出一本書就像架設一個網站一樣,你所需要的只有
假設上述兩點你都已經具備了,接下來就是回答下面三個問題
  1. 你要如何將你的書中內容分開成多個 HTML pages ?
    Baker 做出來的書是由多個 HTML page 所組成。由於 HTML page 並沒有限制內容的長度,所以你可以把一整個章節全部放在單一個 page 內。
  2. 你是要放在那種平台上 ?
    Baker 支援 iPhone/iPod 跟 iPad, 所以請選擇你想要放置的平台並針對它去設計你的書。
  3. 你希望書籍是以何種方向呈現
    Baker 支援橫向與縱向兩種樣式。選擇一個你喜歡的書籍樣式,或著針對這兩種提供一個漂亮的樣式。
如果你對上面的問題都有了答案,那你你可以開始設計你的書。別忘了你可以利用所有 HTML5 與 CSS3 的特點,以及適用於 WebKit 的 JavaScript libraries. 如果你想要測試你的成果,試著以 Safari Mobile [註1] 方式瀏覽: Baker 呈現的方式正如同它們在你希望的平台。
[註1]應該是指修改 Safari 的 “開發人員” -> “使用者代理程式”。

套件

現在你的書已經準備好了,接下來就打包它成為一個套件然後丟到 Baker 吧:
  1. 先建立一個名為 “book” 的資料夾,並且複製所有你的書本檔案丟進去 “book” 裡面。所有的 HTML 檔案跟書中內容都需要在 “book” 資料夾中, Baker 只會看到 “book” 資料夾內的內容。
  2. 再建立一個名為 “book.json” 的檔案,裡面包含了 Baker 所需要的參數,以便 Baker 能正確顯示你的書。這個檔案被稱為 manifest 並且需滿足 HPub 標準。你可以在這裡找到所有參數的完整解釋。在做完上面的步驟後,你的 “book” 資料夾將會是一個 HPub 套件,接著就是讓它轉成 APP 吧。
附註: 你可能注意到,HPub 套件只是一堆 HTML pages。 這意味著,一旦你確定所有 page 彼此被鏈接,你能發佈它在網路上而不用另外的工作以及你的使用者能夠在標準的瀏覽器上閱讀它

第一次建置

現在準備開始使用 Baker,在此之前你還需要兩個東西:
  • 最新版本的 Xcode。如果你是註冊過的 Apple developer,你可以從 Apple Developers website 免費下載。 如果你還沒有註冊過, 你可以到這裡註冊. 如果你不想註冊而只是想測試 Baker 在你的機器上,那麼你可以從 Mac App Store 下載。
  • 一臺 Mac。很遺憾,在 Windows 上是沒有 Xcode。
準備好了嗎?讓我們開始在模擬器上測試你的 APP 吧:
  1. 下載最新版本的 Baker Framework package 並將它解壓縮至 Baker 資料夾。
  2. 將你自己的 “book” 資料夾 取代 Baker 資料夾中預設的 “book” 資料夾。
  3. 雙擊 Baker.xcodeproj 這個檔案以讓 Xcode 開啓這個 project。
  4. 檢查左上角的 “Scheme” 是顯示 “Baker > iPad 5.0 Simulator”。
  5. 點擊 “Run” 按鈕。
如果一切都沒問題的話,你應該會看到你的 Baker app 會在 iPad 模擬器上執行,並且展開妳書本中的第一頁。
如果有出錯的話, 請在完全的清除之後重新再執行一次: 移除模擬器上的 app (就如同你在實際的 iPad 上移除的方法) 然後按 Product -> Clean Build Folder 來清理 Xcode 的建置… (打開 Product 選單時,你需要按 alt 才能夠看到這個選項)

個人化你的書

你已經快做好了。現在在送上 App Store 前,放一些注意力在你的 app 上。
  • 重新命名你的 app
    在 project 的 Navigator 邊欄上選擇(最上面的) “Baker” 然後按 “enter”:你應該能夠改變名字。重新命名為你想要的(這個將會是你的 APP 在 APP Store 上的名字)。
  • 選擇你要建置的機器平台
    在 Project 的主要視窗 (當你點擊 Project Navigator 的最上方選項,它應該會自動被打開) 點擊 “Build Settings”. 搜尋 “Targeted Device Family” 然後選擇你要的機器平台。
  • 選擇適合的 iOS
    在 Project 的主要視窗點擊 “Info” 的 “Deployment Target” 內的 “iOS Deployment Target” [註2]。選擇你希望你的 APP 可以運行的 iOS 版本: Baker 可以在 iOS 4.0 以上的版本運行。
    [註2] 原文是 In the Project Build Settings, right under the “Targeted Device Family” entry, you should see another one called “iOS Deployment Target”. 但是我在 “Targeted Device Family” 下並沒有看到,而是在 “Info” 內看到
  • 改變你的 APP 圖示
    你應該為你的 APP 使用個人的圖示。請參照 Apple Custom Icon and Image Creation Guidelines 來製造你的圖示並將它們放到 “Baker” 資料夾內的 “Resource” 資料夾。
  • 檢查 Baker 的擴充 HPub 參數
    除了標準的 HPub 設定之外,Baker 提供一系列的參數來客制化你的書的外觀。這些參數都列在這裡
就這樣。現在重新再執行你的 app 在模擬器上 : 當你已經準備好的話。
請不要太相信你的模擬器: 記住你的使用者是在真實的 iPad 跟 iPhone 上看你的 APP。請先在實機上測試過後再釋出你的 APP。

發佈在 Apple App Store

在發佈你的 APP 到 App Store 上時,請參照 Apple 提供的詳細教學(需要登入):
  1. 你在進入 iTunes Connect website 時必須準備好應用程式.
  2. 你必須依照 iOS Provisioning Portal under Distribution 的指示建立好編譯過的應用程式以釋出。
  3. 你必須要上傳編譯過的應用程式。
這部分完全由 Apple 控管,所以你可以使用官方的 channels 跟教學來了解如何去做.. 或是在網路上發問。Apple 上也有一些有趣的額外提示。
全部就這樣,歡呼吧 :)