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];

}