March
23rd,
2014
之前一直有聽說Heroku的服務相當好用,其實帳號也申請好了.
但是一直沒有時間把他設定起來,而是一直卡在local端學習Ruby on Rails
不過最近開始要認真把它弄起來,也要把Python開始好好的補習一下
這裡稍微記錄一下關於如何在Mac上架設Heroku Python App的筆記
主要流程參考Heroku官方教學說明,這裡只挑一些會有問題的地方加上註解:
關於Python 環境架設
由於Mac OS本身就有Python,這倒不是太困難的事情.主要是要安裝VisualEnv (這裡有更多說明)
easy_install virtualenv
Heroku login與SSH key
第一次打Heroku login 會自動把在你設定的.ssh/rsa_pub 上傳到server去當做你的key
關於Heroku Toolkit : Procfile 與 foreman
Procfile是你需要寫一個設定檔 “Procfile”去執行相關的app
foreman 可以讓你local 去執行你要建立在Heroku的app
由於架構上是利用 git 把你local 的檔案上傳到遠端的 Heroku Git server 然後去執行它.所以必須要了解Git基本指令,每次改完code可以先用foreman先在本地端預覽,然後再push到Heroku去
好了,這樣也架設好第一個Heroku 第一個App接下來要學習更複雜的Python與更多的應用
參考:
Windows Heroku Python 架設 http://danjog.blogspot.tw/2013/08/heroku-windows.html
Python DJango Heroku http://www.openfoundry.org/tw/tech-column/8564-python-django-on-heroku
Heroku with Python https://devcenter.heroku.com/articles/getting-started-with-python
Git command http://blog.longwin.com.tw/2009/05/git-learn-initial-command-2009/
Python VirtualEnv http://www.openfoundry.org/tw/tech-column/8516-pythons-virtual-environment-and-multi-version-programming-tools-virtualenv-and-pythonbrew
繼續閱讀
March
21st,
2014
一直以來,Windows Store App由於有GC (Garbage Collection)的關係,所以之前寫的App也都不容易有memory leak的產生.
最近剛好遇到這樣的問題,也好好的把一些相關的工具都學習了一下.再次筆記一下
Debugging Memory Leaks之前,你必須了解
所謂的memory leak在使用者能夠看到的永遠是記憶體被用完crash(或是app 收起來).但是就像是水管漏水一樣, 積水的地方絕對不是漏水的地方.
所以面對memory leak 的問題,第一件事情就是不斷地簡化復現(reproduce)的步驟.
由於有GC,如果你重複三到五次的動作發現有記憶體長大的情形,絕對不要貿然認為你找到關鍵的步驟.必須要超過10~15次讓系統把記憶體收回去.
通常如果是Frame 的記憶體回收,可能5~10次會發生,WinRT 的部分可能會更久
也可以跑一些其他大記憶體的App讓GC強迫產生
或是放一段時間,讓GC動作.
試著可以加上GC.Collect()的程式碼讓系統快一點回收,不過通常而言產生的效果相當有限.
找到了memory leak的部分的時候,千萬不要選擇使用 Dispose或是 Null 某些component,因為這樣都不是正確的方式.必須要回過頭來去尋找為何該記憶體無法被正常的釋放.
關於尋找Memory Leak的Tools
這邊要註解一下,大部份的C#或是.NET的memory dump tool 都只能先把關於 managed code 的部分可以先列印出來
如果memory leak 出現在WINRT或是自己寫的unmanaged code這樣就比較難去尋找了.
NP .NET Profiler tool
這個工具還不錯,只要先指定好之後.做好一次的動作就用snapshot 抓下現在的記憶體狀況,最後再把狀況dump出來就可以了
心得:
比起等等會提到的PerfView算是比較好用,當然東西會少一點.不過使用上相當直覺,相當好用.
PerfView (說明網頁)
這是微軟的工具,一樣只能提managed code的memory dump但是資訊更多還可以trace到Windows System Symbol.
使用方法也相當簡單,先dump一次後.開始執行會產生memory leak 的動作然後執行第二次dump. 打開原始跟第二次的report就可以diff然後觀看結果.
心得:
比較建議使用這個畢竟是微軟提供的工具,資訊也比較多.不過在使用的時候如果有用debugger attach 會更慢.
如何Debugging Memory Leaks
尋找正確的復現步驟,任何bug都是如此但是對於Windows Store(Mobile) system 而言,需要注意以下狀況
如果發現做一次的步驟,記憶體沒有任何的增長,代表你的方式無法復現.反之則不然
做出一次步驟發現記憶體的增長,不要以為找到復現的步驟.恐怕只是系統還未回收記憶體,建議要做到記憶體爆掉App收掉.
這裡先列出一些在managed code裡面容易發生memory leak的部分:
UIElement AddHandler/RemoveHandler
根據許多的資料(還有這裡)上來說GC應該會處理這樣的Handler,但是透過我實地拿PerfView的結果卻是會產生memory leak. 還是得注意一下.
Delegate的處理 += 記得要 -= 回去
這個是一定會出事情的,千萬要注意你的 OnNavigationTo/OnNavigationFrom 有沒有成對的 += 與 -=
利用PerfvIew 查詢reference count是否有任何的異常產生(也就是查詢到爆量或是超過自己想像的ref cnt)
利用PerfView 來觀察的部分,這邊有一些小技巧可以去觀察,驗證的方法:
[觀察]使用Diff方法,一開始先記錄下來後,做完疑似memory leak 的步驟之後,再記錄下來.
[驗證]可以把修改前的跟修改後的比對,不過這裡建議用修改前去diff 修改後~雖然數字出來會是正數但是這樣比較容易分析…
參考文章:
http://blogs.msdn.com/b/webapps/archive/2012/11/23/troubleshooting-memory-leaks-in-windows-store-apps.aspx
http://msdn.microsoft.com/en-us/magazine/jj721593.aspx
http://msdn.microsoft.com/zh-tw/magazine/jj651575.aspx#MtViewDropDownText
http://stackoverflow.com/questions/13730496/how-to-debug-memory-leaks-in-windows-store-apps
http://channel9.msdn.com/Series/PerfView-Tutorial/Tutorial-10-Investigating-NET-Heap-Memory-Leaks-Part1-Collecting-the-data
http://channel9.msdn.com/Series/PerfView-Tutorial/Tutorial-11-Investigating-NET-Heap-Memory-Leaks-Part2-Analyzing-the-data
繼續閱讀
March
18th,
2014
CorePlot 是一個相當好用來畫各種條狀圖,折線圖與圓餅圖的library. 要在手機上畫出美美的條狀圖,圓餅圖與長方圖?真的只能靠這套Library了.
以下整理一些在使用上可能會遇到的問題
遇到的問題:
“Undefined symbols for architecture x86_64”
http://stackoverflow.com/questions/18408531/xcode-build-failure-undefined-symbols-for-architecture-x86-64
主要就是你拿到的library太舊了,可以去官方網站去找最新的來用
Cannot find XXX.h
主要要記得改include path,這倒是跟使用其他library不常看到的設定選項.
使用了好用的CorePlot也必須要了解使用最基本的方式來畫圖
以下是一些基本跟UIView 有關的部分,順便複習一下
關於UIView
UIView Constructor 有兩種
(id)initWithCoder:(NSCoder *)aDecoder
(id)initWithFrame:(CGRect)frame
initWithCoder 是給 StoryBoard 上面的UIView 使用,另外一個通常是自定frame大小的時候會用到.
參數定義使用property與synthesize
要畫Label 與畫出有顏色的自定UIView 可以用以下方式
// 畫出UILable
CGRect frame = CGRectMake(20, 45, 140, 21);
UILabel *label = [[UILabel alloc] initWithFrame:frame];
[self.view addSubview:label];
[label setText:@"Number of sides:"];
// 自定UIView但是是個塗滿的黑筐
UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(0, 200, self.view.bounds.size.width, 30)];
lineView.backgroundColor = [UIColorblackColor];
[self.view addSubview:lineView];
參考:
http://greenchiou.blogspot.tw/2011/04/ios-sdk-quartz-2d-0.html
http://www.raywenderlich.com/1768/uiview-tutorial-for-ios-how-to-make-a-custom-uiview-in-ios-5-a-5-star-rating-view
設定動畫 Animation
主要是利用 UIView 的transform 裡面主要有三種 (可以達到放大,縮小,旋轉與Translation)
CGAffineTransformMakeScale
CGAffineTransformMakeRotation
CGAffineTransformMakeTranslation
詳細內容如下:
-(IBAction)startScaleTransform:(id)sender
{
self.view.transform = CGAffineTransformMakeScale(2,2);
[UIViewbeginAnimations:nilcontext:NULL];
[UIViewsetAnimationDuration:1];
self.view.transform = CGAffineTransformMakeScale(1,1);
self.view.alpha = 1.0;
[UIViewcommitAnimations];
}
參考文章:
CorePlot Github: https://github.com/core-plot/core-plot
CorePlot官方設定: https://code.google.com/p/core-plot/wiki/UsingCorePlotInApplications
設定安裝中文: http://www.cnblogs.com/lovecode/archive/2012/02/11/2346389.html
設定安裝英文: http://tech.pro/tutorial/939/using-core-plot-in-an-iphone-application
CorePlot安裝與使用導覽(英文):
Pie Chart http://www.raywenderlich.com/13269/how-to-draw-graphs-with-core-plot-part-1
Bar Chart http://www.raywenderlich.com/13271/how-to-draw-graphs-with-core-plot-part-2
繼續閱讀
March
13th,
2014
聽從一些前輩的建議,決定還是把已經寫到一半卻累到半死的iOS App來上架 這裡記錄一下上架之前會遇到的一些問題: 首先要先連到 iTune Connect 去新增一個App(當然你需要開發者帳號,也就是付每年$99的費用) 詳細流程參考: http://www.minwt.com/ios/4726.html 關於新增資料上面有一些翻譯可以參考: http://www.csdtn.net/article/2011-01-07/289703 資料都新增完了,就會使用Application Loader 去上傳你寫好的App,不過這裡我發生幾次錯誤,分享給大家. _NSSetlogCstringFunction error on Application loader 一開始我以為是NSLog的原因,不過主要的原因是因為跑到debug版本 記得到 [Product] —> [Edit Schema] —> Change run to release. 正確的包裝app方法為: device —> iOS device [Product] —> [Archive] Provisioning missing iOS Apps must contain a provisioning profile in a file named embedded.mobileprovision. Provisioning bundle identifier not match 這三個問題出現的原因其實都一樣,一般而言讓App上架的方式有兩種: 透過Application Loading,然後自己把App包裝起來以後上傳到iTune Connect 透過Xcode Organizer 來做validate 與 上傳… 這也是我推薦的方式,因為比較容易看清楚所有的問題所在. 接下來我會把我上傳的流程寫清楚(原諒都是文字,放圖實在有點懶) 參考: http://stackoverflow.com/questions/5313537/bundle-identifier-and-provisioning-profile http://lamb-mei.com/10/ios-ios-provisioning-portal-certificates/ http://kenobiluh.blogspot.tw/2012/02/certificate-provisioning-file-code.html 使用 XCode Organizer 來遞交App到Store 詳細方式如下: 先到 Xcode 裏面Project Property —> [General] —> 把 Bundle Identifier 抄下來.記得把[team] 也先選擇到你的開發者帳號 ex: com.XXX.youAppName 到 iTune Connect 新增App申請,詳細流程可以參考這裡.注意 Bundle ID要跟XCode裡面的相同(就算寫錯了~可以之後修改) 到Apple iOS Developer 網站的相關處理: [Certificates, Identifiers & Profiles] —>[Identifiers]—> 新增一個 iOS App ID 記得這裡Bundle Identifier 要跟你Xcode設定裡面一樣 ex: com.XXX.youAppName [Certificates, Identifiers & Profiles] —> [Provisioning Profiles] —> 新增一個[Distribution]的 Provisioning 這裡的App ID要使用剛剛申請的,這裡最好是一對一的mapping 比較不會有問題. 下載 Provisioning 並且點兩下安裝 到Xcode 準備打包上傳 先到Project Property —>[Build Setting] 搜尋 [PROVISIONING PROFILE] —> 將它改成你剛剛下載的Provisioning 把device 從模擬器或是手機切換到 [iOS Device] [Product] —> [Archive] 如還是有出現問題請參照以上得問題解答 這時候就可以做App Validation 跟 Distribute ...
繼續閱讀
March
11th,
2014
昨天把NSDate的一些處理稍微研究了一下,有一些處理方式可以整理一下: 1. 比較時間 (NSDate comparison) <code style="margin:0;padding:0;border:0;font-size:13.63636302948px;vertical-align:baseline;font-family:Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif;white-space:inherit;"><span style="margin:0;padding:0;border:0;font-size:13.63636302948px;vertical-align:baseline;background-color:transparent;color:#00008b;" class="kwd">if</span><span style="margin:0;padding:0;border:0;font-size:13.63636302948px;vertical-align:baseline;background-color:transparent;" class="pun">([</span><span style="margin:0;padding:0;border:0;font-size:13.63636302948px;vertical-align:baseline;background-color:transparent;" class="pln">date1 compare</span><span style="margin:0;padding:0;border:0;font-size:13.63636302948px;vertical-align:baseline;background-color:transparent;" class="pun">:</span><span style="margin:0;padding:0;border:0;font-size:13.63636302948px;vertical-align:baseline;background-color:transparent;" class="pln">date2</span><span style="margin:0;padding:0;border:0;font-size:13.63636302948px;vertical-align:baseline;background-color:transparent;" class="pun">]</span><span style="margin:0;padding:0;border:0;font-size:13.63636302948px;vertical-align:baseline;background-color:transparent;" class="pun">==</span><span style="margin:0;padding:0;border:0;font-size:13.63636302948px;vertical-align:baseline;background-color:transparent;color:#2b91af;" class="typ">NSOrderedDescending</span><span style="margin:0;padding:0;border:0;font-size:13.63636302948px;vertical-align:baseline;background-color:transparent;" class="pun">)<br></br></span><span style="margin:0;padding:0;border:0;font-size:13.63636302948px;vertical-align:baseline;background-color:transparent;" class="pun">{<br></br></span><span style="margin:0;padding:0;border:0;font-size:13.63636302948px;vertical-align:baseline;background-color:transparent;color:#2b91af;" class="typ"> NSLog</span><span style="margin:0;padding:0;border:0;font-size:13.63636302948px;vertical-align:baseline;background-color:transparent;" class="pun">(@</span><span style="margin:0;padding:0;border:0;font-size:13.63636302948px;vertical-align:baseline;background-color:transparent;color:#800000;" class="str">"date1 is later than date2"</span><span style="margin:0;padding:0;border:0;font-size:13.63636302948px;vertical-align:baseline;background-color:transparent;" class="pun">);<br></br></span><span style="margin:0;padding:0;border:0;font-size:13.63636302948px;vertical-align:baseline;background-color:transparent;" class="pun">}<br></br></span><span style="margin:0;padding:0;border:0;font-size:13.63636302948px;vertical-align:baseline;background-color:transparent;color:#00008b;" class="kwd">else</span><span style="margin:0;padding:0;border:0;font-size:13.63636302948px;vertical-align:baseline;background-color:transparent;color:#00008b;" class="kwd">if</span><span style="margin:0;padding:0;border:0;font-size:13.63636302948px;vertical-align:baseline;background-color:transparent;" class="pun">([</span><span style="margin:0;padding:0;border:0;font-size:13.63636302948px;vertical-align:baseline;background-color:transparent;" class="pln">date1 compare</span><span style="margin:0;padding:0;border:0;font-size:13.63636302948px;vertical-align:baseline;background-color:transparent;" class="pun">:</span><span style="margin:0;padding:0;border:0;font-size:13.63636302948px;vertical-align:baseline;background-color:transparent;" class="pln">date2</span><span style="margin:0;padding:0;border:0;font-size:13.63636302948px;vertical-align:baseline;background-color:transparent;" class="pun">]</span><span style="margin:0;padding:0;border:0;font-size:13.63636302948px;vertical-align:baseline;background-color:transparent;" class="pun">==</span><span style="margin:0;padding:0;border:0;font-size:13.63636302948px;vertical-align:baseline;background-color:transparent;color:#2b91af;" class="typ">NSOrderedAscending</span><span style="margin:0;padding:0;border:0;font-size:13.63636302948px;vertical-align:baseline;background-color:transparent;" class="pun">)<br></br></span><span style="margin:0;padding:0;border:0;font-size:13.63636302948px;vertical-align:baseline;background-color:transparent;" class="pun">{<br></br></span><span style="margin:0;padding:0;border:0;font-size:13.63636302948px;vertical-align:baseline;background-color:transparent;color:#2b91af;" class="typ"> NSLog</span><span style="margin:0;padding:0;border:0;font-size:13.63636302948px;vertical-align:baseline;background-color:transparent;" class="pun">(@</span><span style="margin:0;padding:0;border:0;font-size:13.63636302948px;vertical-align:baseline;background-color:transparent;color:#800000;" class="str">"date1 is earlier than date2"</span><span style="margin:0;padding:0;border:0;font-size:13.63636302948px;vertical-align:baseline;background-color:transparent;" class="pun">);<br></br></span><span style="margin:0;padding:0;border:0;font-size:13.63636302948px;vertical-align:baseline;background-color:transparent;" class="pun">}<br></br></span><span style="margin:0;padding:0;border:0;font-size:13.63636302948px;vertical-align:baseline;background-color:transparent;color:#00008b;" class="kwd">else</span><span style="margin:0;padding:0;border:0;font-size:13.63636302948px;vertical-align:baseline;background-color:transparent;" class="pun">{<br></br></span><span style="margin:0;padding:0;border:0;font-size:13.63636302948px;vertical-align:baseline;background-color:transparent;color:#2b91af;" class="typ"> NSLog</span><span style="margin:0;padding:0;border:0;font-size:13.63636302948px;vertical-align:baseline;background-color:transparent;" class="pun">(@</span><span style="margin:0;padding:0;border:0;font-size:13.63636302948px;vertical-align:baseline;background-color:transparent;color:#800000;" class="str">"dates are the same"</span><span style="margin:0;padding:0;border:0;font-size:13.63636302948px;vertical-align:baseline;background-color:transparent;" class="pun">);<br></br></span><span style="margin:0;padding:0;border:0;font-size:13.63636302948px;vertical-align:baseline;background-color:transparent;" class="pun">}</span></code> 可以拿來比較時間的先後,在NSDate大概算是最方便的. 參考: http://stackoverflow.com/questions/5965044/how-to-compare-two-nsdates-which-is-more-recent ** ** 2. 時區的轉換 使用NSDate拿來的時間都是GMT要顯示的時候得轉成當地時區(台灣是TST) -(NSString) transferGMT2TST: (NSDate)inGMT :(NSString*) newTZ { NSDateFormatter *dateFormatter = [[NSDateFormatteralloc] init]; dateFormatter.dateFormat = @”yyyy-MM-dd’T’HH:mm”; NSTimeZone *nTZ = [NSTimeZonetimeZoneWithAbbreviation:newTZ]; ...
繼續閱讀
March
7th,
2014
整理一下最近的關於iOS一些SDK學習心得
FGallery (https://github.com/gdavis/FGallery-iPhone)
自從換掉Three20與 Nimbus 之後,相簿處理的部分就換到這個SDK.其實不錯用只是對於新版本iOS相容性差了點.
優點:
其實整合相當的方便,而且完整相簿得捲動支援(Album scroll view)
缺點:
iOS7 之後,完全一整個不穩定,Git上面也一堆使用者反應.不過作者看起來不maintain 了.
替代方案:
iOS7之後可能還是換成iOS 預設提供的 UICollectionView功能相當的強大,不僅僅可以作為捲動處理,以後要做為更多的功能我想也不是問題.
WWDC 介紹影片: https://developer.apple.com/devcenter/download.action?path=/videos/wwdc_2012__hd/session_219__advanced_collection_views_and_building_custom_layouts.mov
參考介紹文章: http://www.raywenderlich.com/22324/beginning-uicollectionview-in-ios-6-part-12
Nimbus (https://github.com/jverkoey/nimbus)
這個就不詳細介紹了,提供大部分所有app會使用到的相關功能.原開發就是知名的Facebok UI SDK Three20.
最近忽然開始積極更新版本,很久沒繼續使用了.看來會找時間用用看從頭來兜出一個App
MagicalRecord (https://github.com/magicalpanda/MagicalRecord)
這個SDK主要是幫助你處理關於資料的相關處理.CoreData功能很強大,但是一開始的設置跟相關的處理卻相當的麻煩.
而這個不僅僅可以幫助你快速使用CoreData 而不用去管令人討厭的NSManagedObjectContext, NSManagedObjectModel, NSPersistentStoreCoordinator還可以操控不只是CoreData, Plist都可以使用.
如何加入:
把所有檔案加入專案
把這段加到 .pch
#import “CoreData+MagicalRecord.h”
* 建立CoreData資料庫
* AppDelegate 加入 [MagicalRecordsetupCoreDataStackWithStoreNamed:@"CoreData.sqlite”];
* 搞定
* 詳細流程參考[這篇文章](http://www.cnblogs.com/mybkn/p/3328183.html)
Inappsettingskit (http://www.inappsettingskit.com/)
設定App的設定通常都是使用Settings Bundle (參考: 這裡).如果要在app裡面更改設定就得自己都出整個頁面與設定控制,這個SDK可以快速的幫助你建制起來.
流程也簡單到不行:
把InAppSettingsKit資料夾加入你的專案
IASKAppSettingsViewController *IASKAppSettingView;
if(IASKAppSettingView == nil)
{
IASKAppSettingView = [[IASKAppSettingsViewControlleralloc] init];
IASKAppSettingView.delegate = self;
}
UINavigationController *aNavController = [[UINavigationControlleralloc] initWithRootViewController:IASKAppSettingView];
//[viewController setShowCreditsFooter:NO]; // Uncomment to not display InAppSettingsKit credits for creators.
// But we encourage you not to uncomment. Thank you!
IASKAppSettingView.showDoneButton = YES;
[self presentViewController:aNavController animated:YEScompletion:nil];
// [self SwitchPage:PAGE_SETTING];
* 中文的介紹文章: [在這裏](http://blog.csdn.net/artwebs/article/details/8295937)
我是參考這篇文章去找出相關的SDK,把這些SDK都玩過一次之後,又想去翻動我的程式了.一直改來改去~感覺很難上架了~~
繼續閱讀