2013年11月23日 星期六

Storyboard 筆記 1

取自官方的Start Developing iOS Apps Today Tutorial

當建立好一個Model可以使A前進到新的ViewController B

B返回A的方法就是在A上加入一個方法


- (IBAction)unwindToList:(UIStoryboardSegue *)segue//unwindToList是教學內實作的名稱

並在B建立一個Button Item Ctrl+Drag到Exit上 選取此方法

這樣就會有返回的行為了

2013年10月27日 星期日

Xcode 5 製作xib檔案

身為一個IOS新手 看看書學程式沒什麼了不起的
但Xcode更新成5之後
靠北 內建直接就是使用Storyboard
可是台灣市面上的書都是從原始的xib檔案開始教 甚至很多書都建議不要使用Storyboard
那怎麼辦才好勒 囧

孤狗了一下發現有人有和我一樣的問題


http://stackoverflow.com/questions/17234172/xcode-5-without-storyboard-and-arc

http://stackoverflow.com/questions/19092605/there-is-no-xib-file-when-i-create-a-new-single-view-application-in-xcode-5

大致上是
新增一個IOS的空專案
接著新增一個Objective-C Class
繼承UIViewController 並且把With XIB for user interface打勾

若要當rootViewController有兩種做法

一是不強制綁AppDelegate
AppDelegate.m:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.
    ViewController* viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];
    UINavigationController* nav = [[UINavigationController alloc] initWithRootViewController:viewController];
    self.window.rootViewController = nav;    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];
    return YES;
}

另一做法是綁在AppDelegate
AppDelegate.h:
@class ViewController;
@interface AppDelegate : UIResponder <UIApplicationDelegate]]> 
@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) ViewController* viewController; @end

AppDelegate.m:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.
    self.viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];
    self.window.rootViewController = self.viewController;
    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];
    return YES;
}

差異在於不需要再創建UINavigationController設定rootViewController後再指定去UIWindow的rootViewController

2013年8月1日 星期四

用AS3快樂的判斷手勢所畫出來的圓形吧!!


因為之前公司的需求,
研究了一下怎麼樣判斷Starling環境下所畫出來的手勢,
雖然有些功能已經沒有需求了,
不過因為覺得很有趣,
所以還是寫了這篇紀錄一下XD

主要是參考這篇文章

當然不是照單全收,
但這一篇文章關於方向的圖解讓我得到很多想法,
於是便實作了出來。
當然,有更好的做法也請知情的大大指教一下XD

首先,
我們可以透過Starling TouchEvent的BEGIN和END所取得的座標來換算角度,
再依照角度來判斷手勢所滑行的方向,
但那也只能知道方向,並無法知道使用者到底畫了些什麼,
所以我們還要再加入MOVED事件並傳入當前座標來記錄使用者到底滑了些什麼,
並將這些座標存入一個容器內。

var degree:Number = Math.atan2(y - prevPosY, x - prevPosX) * 180 / Math.PI;
var direction:int = (degree + 180.0 + 15) / 45;
direction = direction == 0? DIR_LEFT: direction;
prevPosX = x;
prevPosY = y;
if (vCommand.indexOf(direction) == -1)
{
vCommand.push(direction);
}
if (checkDir != direction)
{
checkDir = direction;
vTotalCommand.push(direction);
}

vCommand內(原諒我取了個怪名稱)所記錄的是MOVED事件時有出現過的方向,不重複記錄,
vTotalCommand則是將所有手勢方向全部記錄下來。

接著在END事件時做整個判斷,
這裡我的想法是,要畫圓的話勢必8個方向都會用到,
所以判斷圓的做法很簡單,就是看vCommand的長度夠不夠。

if (vCommand.length > 6)
{
//這是圓形
}

因為沒有要做到非常嚴警(案子的關係),所以我只檢查長度是不是大於6個,
而6個長度已經幾乎是個圓了。

若還要判斷是順時針或逆時針方向所畫的圓,
只需要把所有元素取出來做比較就好。

var count:int = 0;
for (var i:int = 0; i < vCommand.length - 1; i++)
{
if (vCommand[i] > vCommand[i+1])
{
count++;
}
else
{
count--;
}
}
if (count < 0)
{
//順時針
}
else
{
//逆時針
}

若是想要判斷像是Z字型呢?
先用一個Array或Vector將Z自行需要的方向記錄好,
接著把vTotalCommand拿出來對元素做判斷就好了。
這裡我是寫成函式,
若是Z字型則回傳true。

private function checkZGraphic():Boolean
{
const zArray:Array = [4, 7, 4];
var first:int = vTotalCommand.indexOf(zArray[0]);
var second:int = vTotalCommand.indexOf(zArray[1]);
var last:int = vTotalCommand.indexOf(zArray[2], second);

if ( -1 == first)
{
return false;
}
if ( -1 == second)
{
return false;
}
if ( -1 == last)
{
return false;
}

if (first < second && second < last)
{
return true;
}
else
{
return false;
}
}

是不是很簡單呢(?)

那麼下次見XD



2013年7月19日 星期五

使用MultiByteToWideChar和WideCharToMultiByte進行ANSI與UTF8編碼轉換

在Windows環境下使用VC++
並沒有像QT一樣直接有QStrring可以直接對字串內容進行編碼轉換
所以我們必須對字元陣列作處理
使用MultiByteToWideChar和WideCharToMultiByte可以達成字元編碼的轉換
第一個參數所傳入的CodePage可以轉換成不同的編碼

因為我自己要使用是為了傳入TinyXml儲存資訊用
所以轉成Unicode之後還要再轉成utf-8
轉換後的字元陣列存入xml才不會是亂碼


先將ANSI轉為Unicode


//求size
int size = MultiByteToWideChar(CP_ACP, 0, pStr, -1, NULL, 0);
//使用剛剛求出的size建立寬字元字串
wchar_t *pWStr = new wchar_t[size+1];
//將字串寫入寬字元字串
MultiByteToWideChar(CP_ACP, 0, pStr, -1, pWStr, size);

執行之後 pWStr便會得到Unicode字串
然後再將Unicode轉為utf-8

//一樣求size
int utf8Size = WideCharToMultiByte(CP_UTF8, 0, pWStr, -1, NULL, 0, NULL, false);
//使用剛剛求出的size建立字串
char* utf8Str = new char[utf8Size+1];
//將寬字元字串寫入字串
WideCharToMultiByte(CP_UTF8, 0, pWStr, -1, utf8Str, utf8Size, NULL, false);

所以最後得到的utf8Str 便是我們要的utf-8字串


轉回來也是一樣

char* pStr = "中文測試";
int size = MultiByteToWideChar(CP_UTF8, 0, pStr, -1, NULL, 0);
//使用剛剛求出的size建立寬字元字串
wchar_t *pWStr = new wchar_t[size+1];
//將字串寫入寬字元字串
MultiByteToWideChar(CP_UTF8, 0, pStr, -1, pWStr, size);
//再從Unicode轉為utf8
//一樣求size
int ansiSize = WideCharToMultiByte(CP_ACP, 0, pWStr, -1, NULL, 0, NULL, false);
//使用剛剛求出的size建立字串
char* ansiStr = new char[ansiSize+1];
//將寬字元字串寫入字串
WideCharToMultiByte(CP_ACP, 0, pWStr, -1, ansiStr, ansiSize, NULL, false);

差別只是在於
utf-8和Unicode互相轉換時要傳入CP_UTF8作為CodePage的參數
ANSI和Unicode互相轉換時則是要傳入CP_ACP

經過轉碼之後TinyXml儲存的utf-8編碼XML就不再會是亂碼了

有更好的做法還請大大們告知 謝謝

2013年5月21日 星期二

iOS drawRect

隨便筆記提醒自己一下

繼承UIView的View不用呼叫drawRect
只需要在ViewController裡傳送View的setNeedDisplay方法
drawRect便會自動被執行

另外

CGContextRef context = UIGraphicsGetCurrentContext();
這個context 有點類似canvas
必須先取得該參考後才能開始執行繪圖(許多方法都必須傳入此參數)


查了幾小時終於正確的繪出矩形Orz

2013年3月21日 星期四

C++ std::string 使用fwrite及fread

此方法不一定是最好的方法,僅為個人紀錄用,
如有更好的方法還請多指教,謝謝。

因為小弟對C++ fstream概念還是很弱,所以存取檔案都先用stdio來實作。

估狗查了一些資料,後來自己想了個最簡單又直接的方法,就是把string內的字元一個一個抓出來存,讀取的時候先把長度抓出來,再依照長度把一個一個字元塞回來。

std::string str;

//write
int strSize = str.size();
fwrite(&strSize , sizeof(int), 1, pFile);
for(int i = 0; i < strLength; i++)
{
   fwrite(str[i], sizeof(char), 1, pFile);
}

//read
int strSize = str.size();
fread(&strSize , sizeof(int), 1, pFile);
str.resize(strSize);
for(int i = 0; i < strLength; i++)
{
   fread(str[i], sizeof(char), 1, pFile);
}