2013年8月3日 星期六

假如七八十歲的人還在創新,我們問題就大了

原文 http://forum.inside.com.tw/viewthread.php?tid=1492

節錄:

一個多月以前我去台灣,在一個餐桌上,有一批年紀很大的企業家,頭髮都很白了,每個人都大談創新,怎麼創新?邊上有個人跟我講,台灣有希望,我想這麼大年紀的人還在創新。後來我說台灣沒希望了。 假如七八十歲的人還在創新,我們問題就大了,他們不相信年輕人比他們更會創新,其實他們應該是盡全力去努力幫助年輕人去創新,建個平台扶持他們創新、幫助他們創新。 所以我們認為比年輕人更聰明,那災難就出現了。

延伸閱讀

十九世紀的製冰業,派人在結冰的湖面或河裡,將冰塊鋸下給顧客使用,他們的工作後來被製冰廠取代,製冰廠又被電冰箱取代,假如他們願意擁抱改變,而不是去抗拒改變,他們將有機會轉進到新的技術領域,而不是眼睜睜看著自己的心血被別人取代。

老人用他們的想法創新,不接受小一輩的真正創新。

這想法就和冰塊製造廠老闆一直想創新冰塊,卻不接受電冰箱這種東西的情況類似。

對冰塊業創新是一條路,但是當電冰箱出來後,大家都能做冰塊,還守著舊思維思考怎麼運送冰塊好讓他不融化,而不去思考是否到處建小廠做冰塊,那註定失敗。

因為這是一種典範轉移、破壞(革命)性創新,而破壞性創新是不可能從原本的基礎上改進而來

同樣的問題出現在出版業、快遞業、ooxx行業,只思考怎麼更好的賣東西,而不是思考他們在賣的是東西還是資訊時,那註定會被淘汰

十九世紀的製冰業,派人在結冰的湖面或河裡,將冰塊鋸下給顧客使用,他們的工作後來被製冰廠取代,製冰廠又被電冰箱取代

有多少製冰業的老闆講創新時是在想製冰廠?製冰廠老闆有多少在思考電冰箱?

那些七八十歲的製冰廠老闆講創新時,我們都在弄電冰箱了,你相信他們和我們想的會視同一件事情嗎?

馬雲這次的觀點未必正確,不過他想講的東西是正確的,那些該放手的人就放手吧。

換個角度,台灣現在一線演員你 看得到多少3x, 4x的人?製作人呢?我們只看得到/聽得到楊佩佩之類6x,7x的人,3x/4x的人跑哪去了?是不存在還是整個被那些努力工作一輩子的人給壓住了?

當然很多東西需要時間養成,名氣、演技、成就都是,但是當這一代整個不在名單上時,這不叫做沒人成功,這叫做一種警訊

長輩活到90歲,工作到90,然後留給6x/7x的人擔子,6x/7x又活到100。這樣的企業/環境,真正新穎的想法怎麼出頭?

真正新穎的想法是沒有前例可循的, 提出來時,長輩一句你有經驗嗎?我有!沒有想法是能通過這句話的檢驗和長輩經驗門檻的

然後就是只能依循前例,大家繼續想怎麼更有效率的從河裡挖冰而不是去思考電冰箱怎麼用比較好(攤手

到了這地步,真正的創新就不可能了 XD

500 元的實價登錄網站

 

http://www.appledaily.com.tw/realtimenews/article/politics/20121105/150504/1

李鴻源還說,民眾自行製作「實價登錄地圖」,其實與內政部實價登錄網站不一樣,「我們是在蓋房子,他們在窗戶上貼了彩色玻璃」,但已交代,應讓網站使用更友善。

基本上,這是不可能做到的

只要還是政府公務員在主導整個案子的話

這不是說公務員不盡心、不盡力

或者是對案子抱著得過且過的心態

而是結構性使然

哪來的結構性?

一、(很多)政府專案的結案報告都是一堆..公務員在審

想想看,你們公司開了一個社群網站專案

然後外包給外面公司

定下案子的是覺得大家有我也要有的公司老闆

決定規格的是帶著老花眼鏡,有很多業務經驗,待了 10 年以上,只會用 Office 和 Yahoo 的業務主管

主導過程的是只想著準時下班,能閃則閃,網站成果和他沒一毛錢關係的櫃檯人員

外包公司問架構時,櫃檯人員都說可以

開發出草稿時,櫃檯人員也說可以

盡心盡力做出一個 UX 很好的網站時

主管就直接打槍:根據我多年經驗,這不是我們要的東西,重做!

再花 100% 精力做一版後

主管:根據我多年經驗,這個東西不合格

然後呢?專案人力、資源都快滿了

只好 60% 來一版

問櫃檯,櫃檯模擬兩可,okok

問主管,主管勉強點頭說可以

問老闆?

老闆就直接打槍:根據我多年經驗,這不是我們要的東西,重做!

再花 40% 精力做一版後

老闆:根據我多年經驗,這個東西不合格

然後時間到了

只好再花 20% 隨便改一改,趕快送出去

老闆出國考察

櫃檯幫忙遞交

主管不敢點頭答應,就開一個結案會議拉大家一起討論

大家看一看,那邊顏色不對、這邊圖片太小,這個版權宣告不正確

UX? UI? 那是啥鳥?

從頭到尾根本沒有人在乎這東西!

只有上面主管的思考是絕對的!

設計的再好、說服了再多人,都比不過最上面的摸不著頭緒、沒用過網站看一眼就說的一句話

這樣的公務員所「設計」出來的網站

能用才有鬼..

不過我沒接觸過政府資訊部門所開發的網站

都是一些小單位

所以以上說法也許有所偏頗(大概5-99%?)

還是請以實際經驗為準

--

不過公部門專案被主管打槍好像是常態就是了..

2013年8月1日 星期四

git alias 在 windows 7 上的位置

本來想弄個簡單的 git alias, 沒想到弄半天都過不了
一氣之下,就直接跑去改 .gitconfig 了

檔案位置在 HOME="$HOMEDRIVE$HOMEPATH"
例如 C:\Users\MyLogin\.gitconfig

參考來源
http://stackoverflow.com/questions/2114111/where-does-git-config-global-get-written-to


同場加映
使用 git 寫工作日誌

worklog = log --pretty=format:'%ad %s' --date=local --since=2.days

實際使用時,移動到git目錄,使用 git worklog > c:\0730.txt

2013年7月2日 星期二

sqlite 3 自定函数方法

关键字 sqlite3_create_function

这方法 ios 应该可以接受

来自

http://www.thismuchiknow.co.uk/?p=71

使用方法

sqlite3_create_function(sqliteDatabasePtr, "distance", 4, SQLITE_UTF8, NULL, &distanceFunc, NULL, NULL);

记得先定义函数

#define DEG2RAD(degrees) (degrees * 0.01745327) // degrees * pi over 180

static void distanceFunc(sqlite3_context *context, int argc, sqlite3_value **argv){// check that we have four arguments (lat1, lon1, lat2, lon2)assert(argc == 4);// check that all four arguments are non-nullif (sqlite3_value_type(argv[0]) == SQLITE_NULL || sqlite3_value_type(argv[1]) == SQLITE_NULL || sqlite3_value_type(argv[2]) == SQLITE_NULL || sqlite3_value_type(argv[3]) == SQLITE_NULL) {sqlite3_result_null(context);return;}// get the four argument valuesdouble lat1 = sqlite3_value_double(argv[0]);double lon1 = sqlite3_value_double(argv[1]);double lat2 = sqlite3_value_double(argv[2]);double lon2 = sqlite3_value_double(argv[3]);// convert lat1 and lat2 into radians now, to avoid doing it twice belowdouble lat1rad = DEG2RAD(lat1);double lat2rad = DEG2RAD(lat2);// apply the spherical law of cosines to our latitudes and longitudes, and set the result appropriately// 6378.1 is the approximate radius of the earth in kilometressqlite3_result_double(context, acos(sin(lat1rad) * sin(lat2rad) + cos(lat1rad) * cos(lat2rad) * cos(DEG2RAD(lon2) - DEG2RAD(lon1))) * 6378.1);}

sqlite 3 自定函数

关键字 sqlite3_create_function

这方法 ios 应该可以接受

来自

http://www.thismuchiknow.co.uk/?p=71

使用方法

sqlite3_create_function(sqliteDatabasePtr, "distance", 4, SQLITE_UTF8, NULL, &distanceFunc, NULL, NULL);

记得先定义函数

#define DEG2RAD(degrees) (degrees * 0.01745327) // degrees * pi over 180

static void distanceFunc(sqlite3_context *context, int argc, sqlite3_value **argv){// check that we have four arguments (lat1, lon1, lat2, lon2)assert(argc == 4);// check that all four arguments are non-nullif (sqlite3_value_type(argv[0]) == SQLITE_NULL || sqlite3_value_type(argv[1]) == SQLITE_NULL || sqlite3_value_type(argv[2]) == SQLITE_NULL || sqlite3_value_type(argv[3]) == SQLITE_NULL) {sqlite3_result_null(context);return;}// get the four argument valuesdouble lat1 = sqlite3_value_double(argv[0]);double lon1 = sqlite3_value_double(argv[1]);double lat2 = sqlite3_value_double(argv[2]);double lon2 = sqlite3_value_double(argv[3]);// convert lat1 and lat2 into radians now, to avoid doing it twice belowdouble lat1rad = DEG2RAD(lat1);double lat2rad = DEG2RAD(lat2);// apply the spherical law of cosines to our latitudes and longitudes, and set the result appropriately// 6378.1 is the approximate radius of the earth in kilometressqlite3_result_double(context, acos(sin(lat1rad) * sin(lat2rad) + cos(lat1rad) * cos(lat2rad) * cos(DEG2RAD(lon2) - DEG2RAD(lon1))) * 6378.1);}

iOS 撷图方法

来自 http://blog.csdn.net/monsterguaishou/article/details/8512180

截取本区域(self.view):

UIGraphicsBeginImageContext(CGSizeMake(self.view.frame.size.width,self.view.frame.size.height));

  

 [self.view.layer renderInContext:UIGraphicsGetCurrentContext()];

  

 UIImage *viewImage UIGraphicsGetImageFromCurrentImageContext();

   UIGraphicsEndImageContext();   UIImageWriteToSavedPhotosAlbum(viewImagenilnilnil);

全屏截图:

UIWindow *screenWindow [[UIApplication sharedApplication] keyWindow];

   UIGraphicsBeginImageContext(screenWindow.frame.size);   [screenWindow.layer renderInContext:UIGraphicsGetCurrentContext()];   UIImage *viewImage UIGraphicsGetImageFromCurrentImageContext();

   UIGraphicsEndImageContext();   UIImageWriteToSavedPhotosAlbum(viewImagenilnilnil);

以上2种方法真机和模拟器都可以运行.在photo.app里可以看到照片

苹果最新开放的接口函数(全屏截图),已经有人试过了,不会reject:

CGImageRef UIGetScreenImage()

  

 CGImageRef img UIGetScreenImage();

   UIImagescImage=[UIImage imageWithCGImage:img];   UIImageWriteToSavedPhotosAlbum(scImagenilnilnil);

It still works,but only on-device (not in simulator) .

截图另存为指定名字:

UIWindow *screenWindow [[UIApplication sharedApplication] keyWindow];

 UIGraphicsBeginImageContext(screenWindow.frame.size);[screenWindow.layer renderInContext:UIGraphicsGetCurrentContext()];UIImage *screenshot UIGraphicsGetImageFromCurrentImageContext();UIGraphicsEndImageContext()NSData *screenshotPNG UIImagePNGRepresentation(screenshot);

 NSArray *paths NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMaskYES);NSString *documentsDirectory [paths objectAtIndex:0];

 NSError *error nil;[screenshotPNG writeToFile:[documentsDirectorystringByAppendingPathComponent:@"screenshot.png"] options:NSAtomicWriteerror:&error];

部分代码来自:http://stackoverflow.com/questions/692464/emailing-full-screen-of-iphone-app

没有ipad真机截图发布app的可以用此方法做个透明按钮点,哈哈.

 

//播放截图声音NSString* path = [[NSBundle mainBundle]pathForResource:@”photoShutter” ofType:@”caf”];//NSString *path = [[NSBundlebundleWithIdentifier:@"com.apple.UIKit"] pathForResource:@”Tink”ofType:@”aiff”];SystemSoundID soundID;AudioServicesCreateSystemSoundID((CFURLRef)[NSURLfileURLWithPath:path], &soundID);AudioServicesPlaySystemSound(soundID);// we don’t dispose of the sound to keep the sound in the cache forthe next timeAudioServicesDisposeSystemSoundID(soundID);

可以用这顺带播放一下声音

在 uiwebview 事件加入调整宽度的 viewport 设定

refer: http://stackoverflow.com/questions/15826714/how-to-size-uiwebview-in-a-uimodalpresentationformsheet

在 webview 事件加入 JS,塞入 viewport 设定

不过这是处理外部网页的方法

内部网页的话,还是请后台网页人员加入 viewport 设定比较好

- (void)webViewDidFinishLoad:(UIWebView *)webView

{

NSString* js =

@"var meta = document.createElement('meta'); "

@"meta.setAttribute( 'name', 'viewport' ); "

@"meta.setAttribute( 'content', 'width = 540px, initial-scale = 1.0, user-scalable = yes' ); "

@"document.getElementsByTagName('head')[0].appendChild(meta)";

[[self webView] stringByEvaluatingJavaScriptFromString: js];

}

2013年7月1日 星期一

iOS 登入 windows doamin

复习一下什么是 windows active domain

http://www.cnblogs.com/GreenGrass/archive/2012/08/16/2642303.html

所以,Windows Doamin/Active Domain 其实是 LDAP 的一个应用

因此,找 iOS 的 windows domain 登入方法时,可以从 ladp 开始找

例如 openldap

http://stackoverflow.com/questions/929120/search-open-directory-ldap-with-objective-c

2013年6月25日 星期二

iOS app 訊息功設計

這次的 app 需要一各訊息中心功能

不過一開始說的很簡陋,就依照最簡單的作法下去處理

結果後來因為訊息種類持續增加,前面就要加入訊息分類頁面

有了訊息分類就要顯示未讀訊息,包括在訊息分類頁面和乘載此頁面的tabbar controller

然後,因為加入了推播功能…收到推播時當然也應該要進行合理更新…

因為這些歷程,整各架構就大改四次

以下是這幾次架構的簡述

V1: 訊息展示頁面,使用 tableview controller

開啟時更新訊息,然後 insert to row

V2:訊息分類頁面,出現時更新訊息,取得未讀放到分類 icon 上

V3

由於更新訊息時是使用訊息分類頁面,反饋到 tabbar controller 更新 badge 的步驟太複雜(事件難控制)

所以改成使用 notification center 處理

然後又是一次大改..

V4

為了要支援推播,所以需要在接收到推播時更新訊息,然後用 notification center 事件更新

但是單純只改這部份的話,程式又會變得複雜

所以就把更新訊息功能單獨取出成立物件

並且修改成 程式進入前景、收到推播、進入訊息中心時更新訊息

更新後,使用notification center 通知更新頁面

這樣修改後

會有三個觸發程式更新訊息的時間點,進入前景、收到推播、進入訊息分類頁面時

事實上,前兩個應該就夠了

不過由於這個 app 是在企業內使用,有可能會在無法收到推播的環境下作業

因此加入了進入分頁時也會更新訊息的功能避免這種狀況

這些功能也從一開始存在於個別 VC 中的情況轉變成公用程式

但是因為公用程式太多太雜,最後又變成一個擁有自己參數和設定的獨立物件

在這過程中

會發現由於一開始的需求不確定,單純使用簡單的設計

但是後來隨著不斷的改進,慢慢的趨向了主流的設計模式

許多設計模式也許一開始覺得太..複雜用不上

那是很正常的

但是當功能開始複雜後,為了彼此間的整合,就會慢慢趨向許多設計模式的作法

因此,即使目前的功能簡單

但是短期內有可能大幅演進的時候

一開始多花點時間設計好架構

就可以大幅縮短日後的修改、維護所需花費的心力

而Best Practice 就是許多人在處理幾乎相同的工作時,歸納、精簡出來的實作範例

設計模式則是在處理「概念」類似的工作時,歸納出來的作法之抽象模型

2013年6月24日 星期一

Sharekit 心得 (轉)

用 sharekit 整合

twitter

http://blog.csdn.net/sjx19871225/article/details/8777951

facebook

http://blog.csdn.net/sjx19871225/article/details/8517120

FMDB 相關

http://akabeko.me/blog/2011/11/ios-sqlite-fmdb/#fmdb_04

大量插入時,可以使用 transaction 增進效能(差異很大)

[db beginTransaction]

for () {

}

[db commit];

[db close] 方法只有在 table scheme 有改變時才需要呼叫

而且每次重開都會影響效能(由原作回答,2013? /3/30)

http://stackoverflow.com/questions/15720272/when-to-close-sqlite-database-using-fmdb

[db intForQuery] 方法的效果是取得第一各欄位的資料回傳

所以要使用 select count(*) from table where xxxx 讓 fmdb 取得正確的資料

2013年6月21日 星期五

擺脫內建ui,快速自製-custom-uitabbar

來自 http://jwill.pixnet.net/blog/post/29978299-ios-%E6%93%BA%E8%84%AB%E5%85%A7%E5%BB%BAui%EF%BC%8C%E5%BF%AB%E9%80%9F%E8%87%AA%E8%A3%BD-custom-uitabbar

純備份

不知道這作法和使用其他 tabbarcontroller 套件比較如何

在 UIApplication 中加入:

[self.tabBarController.tabBar.superview.addSubview: fakeTabBG];

[self.tabBarController.tabBar.superview addSubview: fakeTab];

[self.tabBarController.tabBar.superview addSubview: fakeNavBar];

在自製的 fakeTabItem (TabBar 下面的 Tab,其實是以 UIButton 實作)

[fakeTabItem4 addTarget:self action:@selector(tabItemPressed:) forControlEvents:UIControlEventTouchUpInside];

每個 Tab Button trigger 原生 tabBarController

- (void)tabItemPressed: (UIButton *) sender

{

nowTabIndex = [[[NSNumber alloc] initWithInteger: sender.tag] intValue] -1;

self.tabBarController.selectedIndex = nowTabIndex;

[self chkPressed];

}

Thread safe Singleton 寫法

http://stackoverflow.com/questions/2199106/thread-safe-instantiation-of-a-singleton

+(MyClass *)sharedInstance

{

static MyClass *sharedInstance = nil;

static dispatch_once_t pred;

dispatch_once(&pred, ^{

sharedInstance = [MyClass alloc];

sharedInstance = [sharedInstance init];

});

return sharedInstance;

}

2013年6月20日 星期四

正規表示法 regular expression

大原則是分次取得包含內容的元素

最後才去掉標籤

當然情況比較複雜時就看需求了

以下會先使用 matchesInString 取得元素

然後用 replaceInString 將前後 tag 去掉留下中間的值

                

                NSString *aa = @"123123<span class=\"g\">span content</span>243242424";

                

                NSError *errRegex = NULL;

                

                NSRegularExpression *regex = [NSRegularExpression

                 regularExpressionWithPattern:@"<span class=\"g\">(.|\n)*?</span>"

                 options:NSRegularExpressionCaseInsensitive

                 error:&errRegex];

                

                NSUInteger countMatches = [regex numberOfMatchesInString:aa

                 options:0 range:NSMakeRange(0, [aa length])];

                [regex enumerateMatchesInString:aa options:0

                 range:NSMakeRange(0, [aa length])

                 usingBlock:^(NSTextCheckingResult *match,

                 NSMatchingFlags flags, BOOL *stop) {

                

                 NSLog(@"Ranges: %ld", [match numberOfRanges]);

                

                 NSString *matchFull = [aa substringWithRange:[match range]];

                 NSLog(@"Match: %@", matchFull);

                        

                        NSRegularExpression *regexx = [NSRegularExpression

                        regularExpressionWithPattern:@"<(.|\n)*?>"

                        options:NSRegularExpressionCaseInsensitive

                        error:&errRegex];

                        

                        NSString *modifiedString = [regexx

                                 stringByReplacingMatchesInString:matchFull

                                options:0 range:NSMakeRange(0, [matchFull length]) withTemplate:@""];

                        NSLog(@"%@", modifiedString);

                }];

                

                if (errRegex) {

                 NSLog(@"%@", errRegex);

                }

2013年6月19日 星期三

iOS 使用 webservice 方法

原文 http://bbs.csdn.net/topics/330170341

#import <UIKit/UIKit.h>

@interface Hello_SOAPViewController : UIViewController

{

        IBOutlet UITextField *nameInput;

        IBOutlet UILabel *greeting;

        NSMutableData *webData;

        NSMutableString *soapResults;

        NSXMLParser *xmlParser;

        BOOL *recordResults;

}

@property(nonatomic, retain) IBOutlet UITextField *nameInput;

@property(nonatomic, retain) IBOutlet UILabel *greeting;

@property(nonatomic, retain) NSMutableData *webData;

@property(nonatomic, retain) NSMutableString *soapResults;

@property(nonatomic, retain) NSXMLParser *xmlParser;

-(IBAction)buttonClick: (id) sender;

@end

#import "Hello_SOAPViewController.h"

@implementation Hello_SOAPViewController

@synthesize greeting, nameInput, webData, soapResults, xmlParser;

-(IBAction)buttonClick:(id)sender

{

        recordResults = FALSE;

        

        NSString *soapMessage = [NSString stringWithFormat:

        @"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"

        "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"

        "<soap:Body>\n"

"<Hello xmlns=\"http://viium.com/\">\n"

        "<name>%@</name>\n"

"</Hello>\n"

        "</soap:Body>\n"

        "</soap:Envelope>\n", nameInput.text

        ];

        NSLog(soapMessage);

        

        NSURL *url = [NSURL URLWithString:@"http://viium.com/WebService/HelloWorld.asmx"];

        NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:url];

        NSString *msgLength = [NSString stringWithFormat:@"%d", [soapMessage length]];

        

        [theRequest addValue: @"text/xml; charset=utf-8" forHTTPHeaderField:@"Content-Type"];

        [theRequest addValue: @"http://viium.com/Hello" forHTTPHeaderField:@"SOAPAction"];

        [theRequest addValue: msgLength forHTTPHeaderField:@"Content-Length"];

        [theRequest setHTTPMethod:@"POST"];

        [theRequest setHTTPBody: [soapMessage dataUsingEncoding:NSUTF8StringEncoding]];

        

        NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];

        

        if( theConnection )

        {

                webData = [[NSMutableData data] retain];

        }

        else

        {

                NSLog(@"theConnection is NULL");

        }

        

        [nameInput resignFirstResponder];

        

}

-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response

{

        [webData setLength: 0];

}

-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data

{

        [webData appendData:data];

}

-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error

{

        NSLog(@"ERROR with theConenction");

        [connection release];

        [webData release];

}

-(void)connectionDidFinishLoading:(NSURLConnection *)connection

{

        NSLog(@"DONE. Received Bytes: %d", [webData length]);

        NSString *theXML = [[NSString alloc] initWithBytes: [webData mutableBytes] length:[webData length] encoding:NSUTF8StringEncoding];

        NSLog(theXML);

        [theXML release];

        

        if( xmlParser )

        {

                [xmlParser release];

        }

        

        xmlParser = [[NSXMLParser alloc] initWithData: webData];

        [xmlParser setDelegate: self];

        [xmlParser setShouldResolveExternalEntities: YES];

        [xmlParser parse];

        

        [connection release];

        [webData release];

}

-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *) namespaceURI qualifiedName:(NSString *)qName

attributes: (NSDictionary *)attributeDict

{

        if( [elementName isEqualToString:@"HelloResult"])

        {

                if(!soapResults)

                {

                        soapResults = [[NSMutableString alloc] init];

                }

                recordResults = TRUE;

        }

}

-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string

{

        if( recordResults )

        {

                [soapResults appendString: string];

        }

}

-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName

{

        if( [elementName isEqualToString:@"HelloResult"])

        {

                recordResults = FALSE;

                greeting.text = soapResults;

                [soapResults release];

                soapResults = nil;

        }

}

/*

Implement loadView if you want to create a view hierarchy programmatically

- (void)loadView {

}

*/

/*

Implement viewDidLoad if you need to do additional setup after loading the view.

- (void)viewDidLoad {

        [super viewDidLoad];

}

*/

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {

        // Return YES for supported orientations

        return (interfaceOrientation == UIInterfaceOrientationPortrait);

}

- (void)didReceiveMemoryWarning {

        [super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview

        // Release anything that's not essential, such as cached data

}

- (void)dealloc

{

        [xmlParser release];

        [super dealloc];

}

@end

關於 UUID

個人解法

+(NSString*)getUUID {

NSUserDefaults* pref = [NSUserDefaults standardUserDefaults];

NSString* uuid = [pref stringForKey:LOG_KEY_UUID];

if (uuid == nil || [uuid length]<=0) {

CFUUIDRef uuidObject = CFUUIDCreate(kCFAllocatorDefault);

uuid = (__bridge_transfer NSString *)CFUUIDCreateString(kCFAllocatorDefault, uuidObject);

[pref setValue:uuid forKey:LOG_KEY_UUID] ;

[pref synchronize];

CFRelease(uuidObject);

}

return uuid;

}

官方解法

http://www.neatstudio.com/show-2040-1.shtml

  1. #define NEW_UUID_KEY    @"uuid_created_by_developer"  
  2.    
  3. @interface NewUUID : NSObject {  
  4.    
  5.     NSString *uuid;  
  6.    
  7. }  
  8.    
  9. + (NSString *)identifier;  
  10.    
  11. @property (nonatomic, retain) NSString *uuid;  
  12.    
  13. @end  
  1. #import <Foundation/Foundation.h>  
  2.    
  3. #import "NewUUID.h"  
  4.    
  5. @implementation NewUUID  
  6.    
  7. @synthesize uuid;  
  8.    
  9. - (id)init {  
  10.     self = [super init];  
  11.     if (self) {  
  12.         uuid = NULL;  
  13.         return self;  
  14.     }  
  15.    
  16.     return nil;  
  17. }  
  18.    
  19. + (id)_instance {  
  20.     static id obj = nil;  
  21.     if( nil == obj ) {  
  22.         obj = [[self alloc] init];  
  23.     }  
  24.    
  25.     return obj;  
  26. }  
  27.    
  28. + (NSString *)identifier {  
  29.    
  30.     NSUserDefaults *handler = [NSUserDefaults standardUserDefaults];  
  31.     [[NewUUID _instance] setUuid:[NSString stringWithFormat:@"%@", [handler objectForKey:NEW_UUID_KEY]]];  
  32.    
  33.     if (NULL == [[NewUUID _instance] uuid] || 46 > [[[NewUUID _instance] uuid] length]) {  
  34.    
  35.         CFUUIDRef uuid = CFUUIDCreate(NULL);  
  36.         CFStringRef uuidStr = CFUUIDCreateString(NULL, uuid);  
  37.    
  38.         NSString *result = [NSString stringWithFormat:@"%@-%@", @"new-uuid-", uuidStr];  
  39.    
  40.         CFRelease(uuidStr);  
  41.         CFRelease(uuid);  
  42.    
  43.         [[NewUUID _instance] setUuid:result];  
  44.    
  45.    
  46.         [handler setObject:[[NewUUID _instance] uuid] forKey:NEW_UUID_KEY];  
  47.         [handler synchronize];  
  48.     }  
  49.    
  50.     return [[NewUUID _instance] uuid];  
  51. }  
  52.    
  53. @end  

正規表示法筆記

parse HTML tag 取出內容

<(.|\n)*?>

不錯的測試用網站

http://www.txt2re.com/index-cf.php3?s=20%3AJun%3A2013+%22This+is+an+Example%21%22&submit=Show+Matches

2013年6月10日 星期一

HTML img 標籤預設圖片用法

來源

http://stackoverflow.com/questions/980855/inputting-a-default-image-in-case-the-src-arribute-of-an-html-img-is-not-valid

html 中,image src 不存在時,使用替代圖片的作法

<img src="foo.jpg" onerror="this.src='error.jpg';">

不過使用 onerror 處理圖片有一個問題,當 error 圖片不存在時,會進入無窮迴圈(onerror > onerror > onerror… )

另一個方法是用

object 中的圖片存在時,就不會呼叫 img 內容

在 ie8 中,需要搭配 DTD for HTML 4.01 使用(不知道使用 HTML 5 標籤是否有用..)

2013年5月20日 星期一

iOS 5,iOS 6 自動旋轉設定

iOS 5 和 ios6 兼容的自動旋轉設定有點坑人..

首先,專案設定有可支援方向

這設定是全域性的,整個 app 能支援的方向都在這邊設定

但是個別的 VC 旋轉設定要在各 VC 中自行設定

而 iOS 5, iOS 6 的設定方法並不相同

iOS 5

- (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {

//檢查是否為可旋轉方向

}

// 設定旋轉後配置,可用其他方法

- (void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {

// in iOS statusBarOrientation is correct than all other orientation changes

if(UIDeviceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation))

self.view.frame = CGRectMake(0,0,1024,768);

else

self.view.frame = CGRectMake(0,0,768,1024);

}

iOS 6

如果每個 VC 都要旋轉,就算了

如果不是,在最底層的 VC 要先設定如下方法,禁用自動旋轉

- (BOOL)shouldAutorotate {

return NO;

}

然後在需要旋轉的 VC 使用

- (BOOL)shouldAutorotate{

return YES;

}

- (NSUInteger)supportedInterfaceOrientations{

return UIInterfaceOrientationMaskAllButUpsideDown;

}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{

return UIInterfaceOrientationLandscapeRight;

}

此外,在 ios 6 底下

window 需要设置 rootViewController,[window addSubview:navController.view]; 无效;

shouldAutorotate 在最底层设置才有效;

presentModalViewController 下用之前的自动旋转控制无效,须用 category 解决。

參考資料

http://fann.im/blog/2012/10/22/autorotation-changes-in-ios-6/

2013年5月16日 星期四

jqtouch animation failed on iPhone 5

恭喜那些衰到要修改 2009/11 jqtouch 版本在 iphone5 上動畫的人

Gratz to those doomed to correct jqtouch (version around 2009/11 around) and lucky reach here

jqtouch (2009/11) 版本在 iphone 5 上面有一些奇怪的問題

例如 slide 動畫在 iPhone 4 上面可以正常運作

但是在 iphone 5 上面不行

jQTouch has some weird animation behavior on iPhone 5

kind of slide animation works fine on iPhone 4 but not iPhone 5

處理的方法很簡單也很詭異

對不正常運作的方法綁定一個無意義動作即可

例如

if’s wasy to correct in a weird way..

bind these link button an animation event with meaningless action,

sort like:

$(‘#somediv’).bind(‘pageAnimationStart’, function(){

        $(‘somediv’).text($(‘somediv’).text());

});

$(‘#somediv’).bind(‘pageAnimationEnd’, function(){

        $(‘somediv’).text($(‘somediv’).text());

});

這看起來像是jQTouch 對於有事件的 div 執行動畫時的方法不同

不過因為這版本實在太舊了,懶得深入去追查

因此就模仿其他綁定動畫事件後正常的div 進行類似的動作

I guess this comes from jQTouch (2009/11 version) handles animation in different way with those bind page animation compared to those without binding.

Since this version is just too old, I don’t wanna spend lots time to track and find the bug, I decide to copy the actions from behave fine to those behave badly, and here is the result..

Quite easy code, spend 2 days tho.. because I tried lots normal solution on them but failed orz