2013년 12월 22일 일요일

C++ 날짜 검증 및 특정 포맷으로 반환




EditBox로 날짜를 입력받아야 하는 경우 입력 받은 날짜를 검증하고 특정 포맷으로 변경하는 용도
/************************************************************************
 * 입력된 date를 받아서 
 * yyyyMMdd, yyyyMdd, yyyyMMd, yyyyMd 포맷으로 입력되었다는 가정하에
 * 년/월/일을 검증하여
 * yyyy-mm-dd형식으로 반환
 ************************************************************************/
const char* getDate(string date)
{
//    bool result = true;
    
    int length = date.size();       // 입력된 날짜의 문자열 길이
    
    string iy = date.substr(0, 4);  // 년도 문자열을 추출
    string im;                      // 월 문자열 저장 변수
    string id;                      // 일 문자열 저장 변수
    
    //////////////////////////////////////////////////////////////////////
    // YYYYMD로 입력 되었을 경우의 월/일 문자열
    //////////////////////////////////////////////////////////////////////
    if (length == 6)
    {
        im = date.substr(4, 1);
        id = date.substr(5, 1);
    }
    //////////////////////////////////////////////////////////////////////
    // YYYYMMD || YYYYMDD로 입력 되었을 경우의 월/일 문자열
    //////////////////////////////////////////////////////////////////////
    else if (length == 7)
    {
        im = date.substr(4, 2);
        id = date.substr(6, 1);
        // 만약 추출한 월 데이터가 12보다 크면
        // 월 데이터를 앞자리만 사용하고
        // 뒤 자리수는 일 데이터 앞자리로 옮김
        if (atoi(im.c_str()) > 12)
        {
            im = date.substr(4, 1);
            id = date.substr(5, 2);
        }
    }
    //////////////////////////////////////////////////////////////////////
    // YYYYMMDD로 입력 되었을 경우의 월/일 문자열
    //////////////////////////////////////////////////////////////////////
    else if (length == 8)
    {
        im = date.substr(4, 2);
        id = date.substr(6, 2);
    }
    //////////////////////////////////////////////////////////////////////
    // YYYY-MM-DD로 입력 되었을 경우의 월/일 문자열
    //////////////////////////////////////////////////////////////////////
    else if (length == 10)
    {
        im = date.substr(5, 2);
        id = date.substr(8, 2);
    }
    
    int iYear  = checkYear(iy);   // 년도를 검증
    int iMonth = checkMonth(im);  // 월 검증
    int iDay   = checkDay(id);    // 일 검증

    
    string m = (iMonth < 10) ? "0" + Common::itos(iMonth) : Common::itos(iMonth); // 월 문자열 생성
    string d = (iDay   < 10) ? "0" + Common::itos(iDay)   : Common::itos(iDay);   // 일 문자열 생성
    
    string dateStr = Common::itos(iYear) + "-" + m + "-" + d;
    return dateStr.c_str();
}

년/월/일 검증 함수
// 출생년도를 130년전 부터 현재까지로 한정함
int MemberLayer::checkYear(std::string date)
{
    int n = atoi(date.c_str());
    if (n < year - 130) n = year - 130;
    else if (n > year)  n = year;
    return n;
}

// 입력한 월이 1~12사이의 숫자여야 하고 현재보다 이전이여야 함
int MemberLayer::checkMonth(std::string date)
{
    int n = atoi(date.c_str());
    
    // "03"일 경우 0을 반환함으로 1의자리 수로 한번 확인
    if (n == 0) n = atoi(date.substr(1).c_str());
    
    if (n < 1) n = 1;
    else if (iYear == year)  // 입력한 년도가 현재 년도이면
    {
        if (n > month) n = month;
    }
    else
    {
        if (n > 12) n = 12;
    }
    return n;
}

// 윷년일 때 2월 날짜와 큰달과 작은달의 입력가능 날짜 제한
int MemberLayer::checkDay(std::string date)
{
    int n = atoi(date.c_str());
    if (n == 0) n = atoi(date.substr(1).c_str());
    // 입력한 생년월일이 오늘 이전이어야 함으로 년, 월이 같을 경우
    // 입력한 일이 오늘보다 크면 어제 날짜로 변경
    if (n < 1) n = 1;
    else if (iYear == year && iMonth == month)
    {
        if ( n >= day) n = day - 1;
    }
    else
    {
        if (iMonth == 2)
        {
            // 입력한 월이 2월일 경우
            // 입력 가능 한 계 날짜의 기본값을 28일로 하고
            // 윷년일 경우 29일로 설정
            int max = 28;
            if ((iYear % 4 == 0 && iYear % 100 != 0) || (iYear % 100 == 0 && iYear % 400 == 0))
            {
                max = 29;
            }
            if (n > max) n = max;
        }
        else if (iMonth == 4 || iMonth == 6 || iMonth == 9 || iMonth == 11)
        {
            if (n > 30) n = 30;
        }
        else
        {
            if (n > 31) n = 31;
        }
    }
    return n;
}

2013년 12월 19일 목요일

C++ 한글 체크

할글은 2byte가 한글자를 이루며 각 byte의 최상위 bit가 1이다.

때문에 다음과 같이 한글여부를 확인 할 수 있다.

const char* text = "한국";

(text[0] & 0x80) == 1 // 한글
(text[0] & 0x80) != 1 // 한글아님



예:
bool isHangul(const char *text)
{
    bool hangul = true;
    
    for (int i = 0; i < strlen(text); i++)
    {
        if ((text[i] & 0x80) != 0x80)
        {
            hangul = false;
        }
    }
    return hangul;
}

Cocos2d-x에서 EditBox사용하기



1. EditBox사용할 Layer의 Head를 다음과 같이 설정한다.


#ifndef __ProjectName__MemberLayer__
#define __ProjectName__MemberLayer__

#include "Common.h"
#include "cocos-ext.h" // EditBox사용을 위한 추가

USING_NS_CC_EXT; // EditBox사용을 위한 추가

// CCEditBoxDelegate 추가
class MemberLayer:public CCLayer, public CCEditBoxDelegate
{
public:
    virtual bool init();
    
    static CCScene* scene();
    
    CREATE_FUNC(MemberLayer);
    ///////////////////////////////////////////////////////////////
    // EditBox사용을 위한 추가 시작
    ///////////////////////////////////////////////////////////////
    virtual void editBoxEditingDidBegin(CCEditBox* editBox);
    virtual void editBoxEditingDidEnd(CCEditBox* editBox);
    virtual void editBoxTextChanged(CCEditBox* editBox, const std::string& text);
    virtual void editBoxReturn(CCEditBox* editBox);
    ///////////////////////////////////////////////////////////////
    // EditBox사용을 위한 추가 끝
    ///////////////////////////////////////////////////////////////
private:
    void PrepareResources();// 본 페이지에서 사용할 리소스 로드
    void StartLayout();     // 전체 레이아웃 구성
    void PrepareEditBox();  // 이름, 생년월일, 비밀번호 입력 텍스트박스 생성
    
    CCSpriteBatchNode* batchNode;
    
    CCEditBox* Name;        // 이름을 입력할 텍스트박스
    CCEditBox* Birth;       // 생년월일을 입력할 텍스트박스
    CCEditBox* Pwd;         // 비밀번호를 입력할 텍스트박스
};

#endif /* defined(__ProjectName__MemberLayer__) */

2. cpp 파일

#pragma mark -
#pragma mark EditBox
void MemberLayer::PrepareEditBox()
{
    /*****************************************************************
     * 이름 필드
     ****************************************************************/
    Name = CCEditBox::create(CCSizeMake(300, 50), CCScale9Sprite::createWithSpriteFrameName("editBox_bg_normal.png"));
    Name->setPosition(Common::centerPoint());
    Name->setFontColor(ccRED);
    Name->setPlaceHolder("Name");
    Name->setPlaceholderFontColor(ccWHITE);
    Name->setReturnType(kKeyboardReturnTypeDefault);
    Name->setInputMode(kEditBoxInputModeAny);
    Name->setTag(1);
    Name->setDelegate(this);
    this->addChild(Name);
    
    /*****************************************************************
     * 생년월일 필드
     ****************************************************************/
    Birth = CCEditBox::create(CCSizeMake(300, 50), CCScale9Sprite::createWithSpriteFrameName("editBox_bg_complete.png"));
    Birth->setPosition(ccpAdd(Name->getPosition(), ccp(0, 100)));
    Birth->setFontColor(ccRED);
    Birth->setInputMode(kEditBoxInputModePhoneNumber);
    Birth->setDelegate(this);
    this->addChild(Birth);
    /*****************************************************************
     * 비밀번호 필드
     ****************************************************************/
    Pwd = CCEditBox::create(CCSizeMake(300, 50), CCScale9Sprite::createWithSpriteFrameName("editBox_bg_error.png"));
    Pwd->setPosition(ccpAdd(Birth->getPosition(), ccp(0, 100)));
    Pwd->setFontColor(ccRED);
    Pwd->setInputMode(kEditBoxInputModePhoneNumber);
    Pwd->setTag(3);
    Pwd->setReturnType(kKeyboardReturnTypeDone);
    Pwd->setInputFlag(kEditBoxInputFlagPassword);
    Pwd->setDelegate(this);
    this->addChild(Pwd);
}


#pragma mark -
#pragma mark EditBox Virtual Methods
void MemberLayer::editBoxEditingDidBegin(cocos2d::extension::CCEditBox *editBox)
{
    // EditBox편집이 시작될 때 발생하는 이벤트
}
void MemberLayer::editBoxEditingDidEnd(cocos2d::extension::CCEditBox *editBox)
{
    // EditBox편집이 끝날 때 발생하는 이벤트
}
void MemberLayer::editBoxTextChanged(cocos2d::extension::CCEditBox *editBox, const std::string &text)
{
    // EditBox내 Text가 변경될 때 발생하는 이벤트
}
void MemberLayer::editBoxReturn(cocos2d::extension::CCEditBox *editBox){}

EditBoxInputMode (EX) setInputMode(kEditBoxInputModeAny))

  1. kEditBoxInputModeAny = 0,
  2. kEditBoxInputModeEmailAddr,
  3. kEditBoxInputModeNumeric,
  4. kEditBoxInputModePhoneNumber,
  5. kEditBoxInputModeUrl,
  6. kEditBoxInputModeDecimal,
  7. kEditBoxInputModeSingleLine


EditBoxInputFlagType (EX) setInputFlag(kEditBoxInputFlagPassword))

  1. kEditBoxInputFlagPassword = 0,
  2. kEditBoxInputFlagSensitive,
  3. kEditBoxInputFlagInitialCapsWord,
  4. kEditBoxInputFlagInitialCapsSentence,
  5. kEditBoxInputFlagInitialAllCharacters

KeyboardReturnType (EX) setReturnType(kKeyboardReturnTypeSend))

  1. kKeyboardReturnTypeDefault = 0,
  2. kKeyboardReturnTypeDone,
  3. kKeyboardReturnTypeSend,
  4. kKeyboardReturnTypeSearch,
  5. kKeyboardReturnTypeGo

2013년 12월 11일 수요일

C++ 코드 실행시간 측정


C++ 코드 실행 시간을 측정하는 방법


#include <iostream>

using namespace std;

void countdown(int n);

int main(int argc, const char * argv[])
{
    clock_t begin, end;
    begin = clock();
    
    //////////////////////////////////////
    // 측정 할 코드
    //////////////////////////////////////
    
    end = clock();
    
    cout << "코드 실행시간 : " << (double)(end - begin) / CLOCKS_PER_SEC << " 초" << endl;
    return 0;
}

2013년 12월 4일 수요일

자식 Sprite를 포함한 사용자 정의 CCSprite - cocos2d-x


  • 자식 Sprite를 포함하는 사용자 정의 CCSprite를 정의
  •  멤버함수 Showchild를 통해 자식 Sprite의 상태(Position, Visible 등)를 제어


CustomSprite.h
#ifndef __Fortune__CustomSprite__
#define __Fortune__CustomSprite__

#include "Common.h"

class CustomSprite:public CCSprite
{
public:
    CustomSprite();
    ~CustomSprite();
    static CustomSprite* create(CCSpriteBatchNode* batchNode, int Type);
    
    void showBag();
    
private:
    static const char* fileName(int Type);
};

#endif /* defined(__Fortune__CustomSprite__) */

CustomSprite.cpp
#include "CustomSprite.h"

CustomSprite::CustomSprite(){}
CustomSprite::~CustomSprite(){}

CustomSprite* CustomSprite::create(CCSpriteBatchNode* batchNode, int Type)
{
    CCSpriteFrame* frame = CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(fileName(Type));
    
    CustomSprite* custom = new CustomSprite();
    if (custom && custom->initWithSpriteFrame(frame))
    {
        batchNode->addChild(custom, 1);
        
        ///////////////////////////////////////////////////////////////
        // 자식 스프라이트 추가
        ///////////////////////////////////////////////////////////////
        CCSprite* child = CCSprite::createWithSpriteFrameName("child.png");
        child->setTag(1);
        child->setPosition(ccp(142.0f, 75.0f));
        custom->addChild(child, -1); // 자식 스프라이트를 부모 스프라이트의 아래 위치시킴
        child->setVisible(false);    // 자식 스프라이트를 화면에서 숨김
        
        return custom;
    }
    
    CC_SAFE_DELETE(custom);
    return NULL;
}

#pragma mark -
#pragma mark 자식 스프라이트의 visible상태 설정
void CustomSprite::showchild()
{
    this->getChildByTag(1)->setVisible(true);
}
#pragma mark -
#pragma mark 타입을 int로 받아서 char*형 파일 이름을 리턴
const char* CustomSprite::fileName(int Type)
{
    std::string name = "custom_";
    
    std::stringstream type;
    type << Type;
    
    name += type.str();
    name += ".png";
    
    return name.c_str();
}

2013년 11월 29일 금요일

TTF 폰트 추가방법 - ios


1. 사용하고자 하는 .ttf 파일을 프로젝트의 Resources디렉토리에 추가한다.

2. 프로젝트에서 다음 이미지에서와 같이 폰트를 추가한다.


TTF font

3. 추가한 폰트를 CCLabelTTF에서 사용한다.

2013년 11월 25일 월요일

Cocos2d-x IOS 프로젝트에서 Sqlite3사용하기

1. 프로젝트에 sqlite3 라이브러리 추가

2. 미리 생성된 .sqlite(또는 .db)파일을 IOS프로젝트의 Resources디렉토리에 위치시킨다.
3. 초기 구동시 DB를 복사한다.

복사방법 : 



#pragma mark -
#pragma mark Initialize DB (Resource에 있는 sqlite파일을 Document로 복사)
void initializeDB()
{
    NSFileManager* fm  = [NSFileManager defaultManager];
    const char* dbPath = filePath("nih_DB.sqlite");
    
    //[fm removeItemAtPath:[NSString stringWithUTF8String:dbPath] error:NULL];
    
    BOOL fileExists    = [fm fileExistsAtPath:[NSString stringWithUTF8String:dbPath]];
    
    if(!fileExists)
    {
        // 참조 데이터베이스 파일 경로
        NSString* origin = [[NSBundle mainBundle]pathForResource:@"nih_DB" ofType:@"sqlite"];
        
        // Copy DB
        BOOL      copyDB = [fm copyItemAtPath:origin toPath:[NSString stringWithUTF8String:dbPath] error:NULL];
        if(!copyDB)
        {
            printf("Copy failed!");
        }
    }
}

#pragma mark -
#pragma mark File Path
const char* filePath(char* _name)
{
    NSString *name      = [NSString stringWithUTF8String:_name];
    NSArray *paths      = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *path      = [paths objectAtIndex:0];
    NSString *_filePath = [path stringByAppendingPathComponent:name];
    
    return [_filePath UTF8String];
}

Cocos2d-x Android 프로젝트에서 Sqlite3 사용하기

미리 생성된 DB를 사용하는 방법

1. external/sqlite3/Android.mk파일에 다음과 같은 내용을 추가한다.


LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := sqlite3_static
LOCAL_MODULE_FILENAME := libsqlite3
LOCAL_SRC_FILES := sqlite3.c
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
LOCAL_C_INCLUDES := $(LOCAL_PATH)
LOCAL_CFLAGS := -fno-fast-math 
include $(BUILD_STATIC_LIBRARY)

2. jni/Android.mk를 다음과 같이 수정한다.
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := cocos2dcpp_shared

LOCAL_MODULE_FILENAME := libcocos2dcpp

LOCAL_SRC_FILES := hellocpp/main.cpp \
                   ../../Classes/AppDelegate.cpp \

LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../Classes

LOCAL_WHOLE_STATIC_LIBRARIES += cocos2dx_static
LOCAL_WHOLE_STATIC_LIBRARIES += cocosdenshion_static
LOCAL_WHOLE_STATIC_LIBRARIES += box2d_static
LOCAL_WHOLE_STATIC_LIBRARIES += chipmunk_static
LOCAL_WHOLE_STATIC_LIBRARIES += cocos_extension_static
LOCAL_WHOLE_STATIC_LIBRARIES += sqlite3_static // 추가한 코드

include $(BUILD_SHARED_LIBRARY)

$(call import-module,cocos2dx)
$(call import-module,cocos2dx/platform/third_party/android/prebuilt/libcurl)
$(call import-module,CocosDenshion/android)
$(call import-module,extensions)
$(call import-module,external/Box2D)
$(call import-module,external/chipmunk)
$(call import-module,external/sqlite3) // 추가한 코드

3. 생성된 .sqlite(또는 .db) 파일을 프로젝트의 Resources 디렉토리에 위치시킨다.
4. 어플을 초기 구동시 DB를 복사한다.


복사방법:


#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
#include "DbManager.h"

bool isFileExist(const char* fileName);
void copyDatabase(const char* fileName);

void DbManager::initializeDB()
{
    // 프로젝트에 데이터베이스 파일이 존재하지 않으면 복사
    if (isFileExist("Fortune.sqlite") == false)
    {
        copyDatabase("Fortune.sqlite");
    }
}

#pragma mark -
#pragma mark 데이터베이스 파일 존재여부 확인
bool isFileExist(const char* fileName)
{
    if (!fileName)
    {
        return false;
    }
    std::string filePath = CCFileUtils::sharedFileUtils()->getWritablePath();
    filePath += fileName;
    FILE* file = fopen(filePath.c_str(), "r");
    CCLog("%s", filePath.c_str());
    if (file)
    {
        fclose(file);
        return true;
    }
    return false;
}

#pragma mark -
#pragma mark copy database file
void copyDatabase(const char* fileName)
{
    std::string path = CCFileUtils::sharedFileUtils()->fullPathForFilename(fileName);
    unsigned long len = 0;
    unsigned char* data = NULL;
    
    data = CCFileUtils::sharedFileUtils()->getFileData(path.c_str(), "r", &len);
    std::string destPath = CCFileUtils::sharedFileUtils()->getWritablePath();
    destPath += fileName;
    
    FILE* file = fopen(destPath.c_str(), "w+");
    fwrite(data, sizeof(destPath.c_str()), len, file);
    fclose(file);
    delete[] data;
    data = NULL;
}
#endif

2013년 11월 19일 화요일

Delete provisioning profile from Xcode 5



Provisioning profile은 다음 디렉토리에서 제거하면 된다. 
"~/Library/MobileDevice/Provisioning\ "

2013년 11월 16일 토요일

맥에서 Android, IOS 통합개발환경 구축(cocos2d-x v2.2)




일단 설명을 돕기 위해 각 설치 디렉토리를 정리한다.

  • cocos2d-x 설치 디렉토리 : /Users/namilhan/Documents/
  • Eclipse & SDK 패키지 설치 디렉토리 :  /Applications/
  • NDK 설치 디렉토리 : /Applications/adt-bundle-mac-x86_64-20131030/(Eclipse 폴더내)


1. Cocos2d-x v2.2 설치
다운로드 주소 : http://www.cocos2d-x.org/download
다운로드가 완료되면 Documents 디렉토리 하위에 압축을 푼다.
이로서 cocos2d-x v2.2의 설치는 완료되었습니다.

2. Eclipse & SDK 패키지 설치
다운로드가 완료되면 /Applications/ 디렉토리 하위로 복사한다.
이로서 Eclipse & SDK 패키지 설치 완료

3. NDK개발킷을 설치
다운로드 주소 : http://developer.android.com/tools/sdk/ndk/index.html#download(android-ndk-r9b-darwin-x86_64.tar.bz2)
다운로드가 완료되면  /Applications/adt-bundle-mac-x86_64-20131030/ 디렉토리 하위에 압축을 푼다.
이로서 NDK 개발킷을 설치도 완료되었다.

4. 모든 설치가 완료되었으므로 이제 cocos2d-x 프로젝트를 만든다.

  • Terminal를 실행하고 /Users/namilhan/Documents/cocos2d-x-2.2/tools/project-creator 디렉토리로 이동한다.(cd입력하고 한칸 띄우고 project-creator디렉토리를 끌어다 놓고 Enter하면 이동된다.)
  • ./create_project.py 스크립트를 사용하여 프로젝트 생성(아래 이미지 참조)

 

위와 같이 proj.ios : Done!과 같이 출력이 되면 cocos2d-x-2.2/projects하위에 test프로젝트가 생성된것을 확인할 수 있다.
명령어 설명 : ./create_project.py -project [프로젝트 명] -package [팩키지명] -language [프로그램 언어]

5. Eclipse를 실행한다.
일단 생성한 프로젝트를 실행하기 전에 다음과 같은 작업이 선행돼야 한다.

  • 이클립스 상단 메뉴에서 Windows/Android SDK Manager를 선택한다.
  • 새로 열린 윈도우의 SDK Manager에서 Android 2.3.3(API 10)를 선택하고 우측하단의 Install 4 packages...를 클릭한다.
  • 새로 열린 윈도우에서 Android SDK License를 선택하고 Accept License를 선택 후 Install를 클릭하면면 SDK설치가 완료된다.

6. Eclipse 상단 메뉴에서 File/Import를 선택한다.

  • 그러면 새로운 윈도우가 열리는데 Android/Existing Android Code Into Workspace를 선택하고 Next를 선택한다.
  • 새로 열린 윈도우에서 Brower를 클릭해서 /Users/namilhan/Documents/cocos2d-x-2.2/cocos2dx/platform/android/하위에 있는 java 디렉토리를 선택하고 Open을 클릭하고 Finish를 클릭하면 Eclipse Package Explorer에 libcocos2dx가 보일것이다.

7. 이제 새로 생성한 cocos2d-x프로젝트를 Eclipse에서 연다.

  • File/New/Project를 선택해서 Select a wizard 윈도에서 Android/Android Project from Existing Code선택하고 Next를 클릭한다.
  • Import Projects 윈도우에서 Browse...를 클릭해서 cocos2d-x-2.2/Projects하위에 생성된 test프로젝트 디렉토리를 선택하고 Open을 클릭
  • Import Projects 윈도우에서 Finish를 클릭하면 Package Explorer에 test 프로젝트가 Import된 것을 확인 할 수 있다.

8. 하지만 아직 프로젝트를 실행 해볼 수 없다. 
test 프로젝트에 마우스 우클릭해서 Properties를 선택하면 다음과 같이 새루운 윈도우가 열린다.

  • C/C++ Build를 선택하고 
  • Use default build command를 선택해제하고
  • Build command에 bash ${workspace_loc:/test}/build_native.sh NDK_DEBUG=1 V=1를 입력하고
  • Build directory에 ${workspace_loc:/test}를 입력하고 OK를 클릭

9. NDK 설정
test 프로젝트에 마우스 우클릭해서 Properties를 선택한다.
C/C++ Build/Environment를 선택한다.
우측에 Add를 클릭한다.
Name에 NDK_ROOT를 입력하고
Value에 /Applications/adt-bundle-mac-x86_64-20131030/android-ndk-r9b를 입력하고 OK를 클릭한다.
 

이제 안드로이드 디바이스로 실행을 해보면 cocos2d-x의 기본 화면이 출력되는 것을 확인 할수 있다.

IOS 프로젝트는 cocos2d-x-2.2/projects 디렉토리의 프로젝트 디렉토리에서 proj.ios 디렉토리에서 [프로젝트명.xcodeproj]를 클릭하여 열면 ios프로젝트를 편집할 수 있다.

새로 생성한 코드와 리소스는 해당 프로젝트 디렉토리 하위의 Classes와 Resources에 있다.


-----------------------------------------------------------------------------------------------------------------------
Pearl Fisher

전혀 낚시같지 않은 신개념 낚시게임이에요~


진주캐기 보러가기 클릭!

2013년 11월 7일 목요일

Cocos touch 웹 브라우저 열기


URL 문자열을 생성
NSString* url = [NSString stringWithFormat:@"https://itunes.apple.com/us/app/unsemalu/id730788250?ls=1&mt=8"];

NSURL 객체 생성
NSURL* fortune = [NSURL URLWithString:url];

브라우저 열기
[[UIApplication sharedApplication]openURL:fortune];

자주 삭제되는 Row의 Identity값 재사용방법

DECLARE @minidentval TYPE
DECLARE @nextidentval TYPE
DECLARE @count INT
SELECT  @count = COUNT(*) FROM [Table_name]
 
SELECT  @minidentval = MIN($IDENTITY) FROM [Table_name]
IF @minidentval = IDENT_SEED('[Table_name]')
     SELECT @nextidentval = MIN($IDENTITY) + IDENT_INCR('[Table_name]')
FROM [Table_name] t1
     WHERE $IDENTITY
BETWEEN IDENT_SEED('[Table_name]')
AND @count AND NOT EXISTS (SELECT * FROM [Table_name] t2
WHERE t2.$IDENTITY = t1.$IDENTITY + IDENT_INCR('[Table_name]'));
ELSE SELECT @nextidentval = IDENT_SEED('[Table_name]')

Javascript로 브라우저 확인방법



자바스크립트로 브라우저 확인하는 방법입니다.

<html>
 <head>
  <title>mobile</title>
   <script type="text/javascript">
   function detectmob() { 
     if( navigator.userAgent.match(/Android/i)|| navigator.userAgent.match(/webOS/i)
    || navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPad/i)
    || navigator.userAgent.match(/iPod/i)   || navigator.userAgent.match(/BlackBerry/i)
    || navigator.userAgent.match(/Windows Phone/i)
      )
   {
        return true;
      }
    else 
   {
     return false;
     }
   }
   if(detectmob())alert('this is mobile web browse');
   else alert('this is pc web browse');
   /* 또는
   var isMobile = {
    Android: function() {
        return navigator.userAgent.match(/Android/i);
    },
    BlackBerry: function() {
        return navigator.userAgent.match(/BlackBerry/i);
    },
    iOS: function() {
        return navigator.userAgent.match(/iPhone|iPad|iPod/i);
    },
    Opera: function() {
        return navigator.userAgent.match(/Opera Mini/i);
    },
    Windows: function() {
        return navigator.userAgent.match(/IEMobile/i);
    },
    any: function() {
        return (isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Opera() || isMobile.Windows());
    }
   };
   */
</script>
</head>
<body>

</body>
</html>

2013년 10월 16일 수요일

파일 포맷이 안 맞아서 효과음 재생이 안 될 때-(cocos2d-iphone)

파일 포맷이 안 맞아서 효과음 재생이 안 될 경우 터미널에서 아래와 같이 해당 파일의 포맷을 바꿔주면 된다.

방법:
1. 터미널을 싱행시킨다.
2. 터미널에 cd를 입력하고 효과음 파일이 들어있는 폴더를 터미널로 끌어다 놓고 enter.
3. afconvert -v -f WAVE -d LEI16 eff_sound.wav eff_sound.wav를 입력하고 enter.

끝!!!

실행이 안되던 "eff_sound.wav"를 실행이 되는 "eft_sound.wav"로 convert해준 것이다.

2013년 10월 15일 화요일

The model backing the 'DbConnection' context has changed since the database was created. Consider using Code First Migrations to update the database

Server Error in '/' Application.

The model backing the 'DbConnection' context has changed since the database was created. Consider using Code First Migrations to update the database (http://go.microsoft.com/fwlink/?LinkId=238269).


해결방법
위와 같은 에러메세지가 출력되면 Global.asax.cs의 Application_Start()에 다음 코드를 추가하면 된다.

Database.SetInitializer<YourDbConnection>(null);

 
protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();

    // Use LocalDB for Entity Framework by default
    Database.DefaultConnectionFactory = new SqlConnectionFactory(@"Data Source=(localdb)\v11.0; Integrated Security=True; MultipleActiveResultSets=True");
    Database.SetInitializer<NihConnection>(null);
    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);
}

2013년 10월 13일 일요일

ASP.NET MVC 5에서 VIEW 추가하는 방법(VS2013)




1. 아래 그림에서와 같이 Controller폴더에서 Right Click > Add > Scoffold...한다.















2. 팝업에서 MVC5 View를 선택하고 Add버튼을 클릭















3. View이름과 유형, 참조 모델... 등 정보를 입력하고 Add버튼을 클릭하면 View가 추가된다.

2013년 10월 9일 수요일

Unity3D Rigidbody Component 추가

ComponentRigidbody는 오브젝트에 물리적인 특성을 부여하는 컴포넌트이다.


추가방법오브젝트를 선택한 상태에서 [Component>Physics>Rigidbody]메뉴를 클릭하면 Inspector에 Rigidbody 항목이 표시된다.


속성 설명
Mass : 물체의 질량. 질량이 작을 수록 더 빨리, 더 멀리 움직인다. 자유낙하하는 질량의 영향을 받지 않는다.
Drag : 선형 운동 저항. 바닥이나 움직임에 대한 저항도로 이 값이 크면 속도가 떨어진다.
Angular Drag : 회전 운동 저항. 공이 굴러갈 때의 저항력으로 이 값이 0이면 한없이 굴러간다.
Use Gravity : 물체가 중력의 영향을 받는지의 여부. 이 값이 설정되면 발사한 포탄은 일정 거리를 이동한 후 추락하지만, 설정하지 않으면 영원히 날아간다.
Is Kinematic : 관절의 운동을 처리하는지 여부. 이 옵션을 설정하면 관절이 여러 마디로 되어 있는 경우 관절의 움직임에 따라 다른 관절이 부드럽게 움직인다.
Collision Detection : 물체의 연속적인 충돌을 검사하는 방법


2013년 10월 4일 금요일

Objective - c NSDate Formatter

아래 예제는 오늘의 날짜를 'yyyy-MM-dd'형식의 NSString객체로 변환하여 출력하는 예제이다.

NSDateFormatter* dateFormat = [[[NSDateFormatter alloc]init]autorelease];
[dateFormat setDateFormat:@"yyyy-MM-dd"];
NSString* date = [[NSString alloc]initWithString:[dateFormat stringFromDate:[NSDate date]]];
NSLog(@"%@", date);

///////////////////////////////////////////////////////////
////////////////// 다음과 같이 출력된다 /////////////////////////
2013-10-05

2013년 10월 2일 수요일

iOS7 Status bar hidden





iOS7으로 업그레이드 되면서 cocos2d로 개발한 앱을 다음과 같이 설정을 추가해야 Status bar를 숨길수 있다.


설정방법 :
1. Xcode의 Project navigator/Info.plist를 선택하다.


2. Info.plist파일에 Add Row해서 3번과 같이 두 설정 항목을 추가한다.


3. Status bar is initially hiddenView controller-based status bar appearance항목을 각각 YES, NO로 설정 해준다. 보통 Status bar is initially hidden항목은 기본값으로 YES가 설정 되어 있으므로 별도로 추가해 줄 필요는 없을 것이다.


-----------------------------------------------------------------------------------------------------------------------
Pearl Fisher

전혀 낚시같지 않은 신개념 낚시게임이에요~


진주캐기 보러가기 클릭!

2013년 9월 28일 토요일

DbArithmeticExpression arguments must have a numeric common type.

DbArithmeticExpression arguments must have a numeric common type.

if (oders.Count() > 0) point = oders.Where(o => (DateTime.Now - o.ShipDate).Days > 7);
위 코드를 아래와 같이 수정하면 된다.
if (oders.Count() > 0) point = oders.Where(o => EntityFunctions.DiffDays(o.ShipDate, DateTime.Now) > 7);

2013년 9월 11일 수요일

아이폰 5S-iOS7 개발관련




애플이 iOS7을 탑재한 아이폰5S와 아이폰5C를 공개했다. 애플이 아이폰과 iOS 모두에 많은 변화를 가하면서, 소프트웨어 개발자도 대응에 고심해야 하는 상황이다. 

애플은 10일(현지시간) 미국 쿠퍼티노 본사에서 비공개행사를 열고 아이폰5S와 아이폰5C를 발표했다. 지난 6월 세계개발자대회(WWDC)에서 공개됐던 iOS7도 최종버전의 배포일이 18일로 결정됐음을 알렸다. 

새 아이폰의 출시일은 이달 20일, iOS7 최종버전의 사용자 배포는 18일이다. 새로운 기기의 등장은 개발자에게 여러 수고를 안겨주는 계기로 작용한다. 그러나 이번엔 전보다 더 고생스러울 것으로 보인다. 

아이폰5S의 가장 큰 변화는 A7 프로세서를 탑재하면서, 64비트를 지원하게 됐다는 점이다. iOS7 역시 종전 iOS 대비 외관과 UI가 플랫디자인으로 대폭 수정됐다. 이같은 상황은 ‘기획-개발-테스트’에 이르는 iOS 개발 사이클 전반에 영향을 미친다. 


■디자인 변화가 기획에 미치는 영향 

1차적으로 iOS 앱 개발자들은 기획단계에서 새로운 디자인에 적응해야 한다. 우선 앱 아이콘을 114×114 픽셀에서 120×120 픽셀로 수정해야 아이폰에 제대로 된 형태로 노출된다. 

또한 앱 아이콘의 이미지 방식을 비트맵에서 벡터로 변경할 필요가 있다. 전반적인 아이콘의 화소가 늘어난 상황에서 앱의 용량증가 없이 대응하는 손쉬운 방법이기 때문이다. 함수 좌표로 색상과 형태를 표시하는 벡터 방식은 기존 비트맵 방식보다 화소를 키워도 용량이 증가하지 않는다. 

UI 측면의 변화에도 대응해야 한다. UI 패턴의 변경, 전체 화면 보기 등에 따라 앱도 변화해야 하는 것이다.

에어드롭, 개선된 멀티태스킹 기능 등에 대한 대응도 고민해야 할 부분이다. 

■64비트가 개발에 미치는 영향 

아이폰5S의 가장 큰 변화는 A7 프로세서다. 애플은 A7 프로세서가 이전 모델인 아이폰5보다 5배 빨라졌다고 주장했다. 그 이유로 64비트 기반 아키텍처가 지목됐다. 

애플은 A7 프로세서가 64비트를 지원함에 따라 더 고성능의 앱을 더 빠르게 구동할 수 있다고 강조했다. 그러나 개발자에겐 이 변화가 도전과 응전의 계기다. 

일단 새로운 앱을 개발할 때 아이폰5S에만 초점을 맞추면 크게 문제될 건 없다. 애초에 64비트 기반으로 앱을 설계하면 되기 때문이다. 문제는 하위 호환성이다. 앱을 아이폰5S 외에 다양한 아이폰에서 원활히 작동되게 하려면 기존 32비트 아키텍처도 동시에 지원해야 하는 것이다. 

또한, 애플은 아이폰5S만 내놓지 않았다. 아이폰5C도 같이 내놨다. 아이폰5C는 32비트 기반이다. 사실상 앱 개발 시 32비트와 64비트 모두 지원하는 방향으로 가야한다. 

애플은 개발도구인 X코드를 통해 32비트 앱을 64비트 앱으로 쉽게 전환할 수 있다고 주장했다. 과거처럼 유니버셜 바이너리를 지원한다고 한 것이다. 인피니티블레이드3 개발자가 2시간 만에 64비트 앱을 만들었다며 무대에 몸소 올라 설파하면서 애플의 주장에 힘을 실어줬다. 

하지만, 앱을 아이폰5와 아이폰5S 모두에서 구동하게 하려면, 동일한 앱이 두 개의 코드를 갖는 걸 감수해야 한다. 하드웨어야 OS 차원에서 알아서 판단해 32비트냐 64비트냐를 결정해 주겠지만, 기본적으로 앱의 전반적인 용량은 커지게 되는 것이다. 

문제는 여기서 그치지 않는다. 그동안 애플의 가이드라인에서 벗어나 개발해왔던 앱 개발자라면, 기존 앱을 64비트로 변환하는데 상당한 모험심을 다져야 할 것으로 보인다. 64비트 앱을 원활히 개발하려면, 애플에서 제시한 가이드라인을 엄격히 지켜야 하기 때문이다. 

가이드라인을 제대로 준수하지 않을 경우 사용자가 아이폰5S에 앱을 설치했을 때 원활히 작동하지 않는 현상이 벌어질 수 있다. 

그러나 A7 프로세서의 64비트 지원이 어떤 방식으로 이뤄지는지 확실치 않다. 일단 A7 설계의 기반이 되는 ARM 아키텍처의 경우 아직 64비트 지원 모델이 상용화되지 않았다. ARM홀딩스 측이 ARMv8 디자인을 공개했을 뿐 실물로 나오는 건 내년이기 때문이다. 애플이 기존 ARM 아키텍처에서 64비트를 구현했는지, ARMv8을 사용하는 지 명확해져야 하는 상황이다. 

오픈GL/EL 3.0 지원여부는 개발자의 실력 신장을 부추기는 요소다. 앱을 더 화려하고, 고성능으로 구현하고 싶다면 오픈GL 3.0에 대한 설계를 할 수 있어야 한다. 초심자와 숙련자의 개발성과가 명확해질 수 있다. 

■하나 더, 디자인 변화가 개발에 미치는 영향 

iOS7의 새로운 디자인은 앱 개발에도 영향을 미친다. 앱 내 표시물의 위치를 설정할 때 개발자가 원하는대로 표출될지 확실치 않다는 지적이 나오고 있다. 좌표의 변경을 자동으로 변환해주는 조치가 이뤄지지 않았다면, 개발자가 직접 수정해가며 확인해야 한다.

맥 및 iOS 앱 개발업체 오로라플래닛의 김정 대표는 "과거 앱이 스테이터스바(아이폰 화면 위쪽 시간이 표시되는 영역)와 내비게이션바(화면 아래쪽 앞으로, 뒤로, 보내기 등 단추가 나오는 영역)를 제외한 영역을 기준으로 만들어졌는데 전체 화면을 쓰게 바뀌면서 표시할 물체의 위치가 개발자 의도와 어긋날 수 있을 것 같다"고 말했다. 

UI 측면에서도 애플의 가이드라인 준수 문제가 나온다. 이른바 ‘날코딩’, 혹은 자유분방한 방식으로 iOS 앱을 개발해왔다면, 엄청난 고생을 감수해야 한다. 어찌됐든 애플의 지시에 복종하지 않았던 개발자들은 앱을 처음 설계하던 시점으로 되돌아가 코드를 일일이 들여다 봐야할 상황이다. 

■64비트가 테스트에 미치는 영향 

앱을 64비트와 32비트 모두 지원하게 하려면, 테스트를 위해 iOS 개발자가 아이폰5S와 이전 아이폰 모델 두 종류에 다 테스트해야 한다. 

대형 개발회사 입장에서 이는 큰 문제가 되지 않는다. 이미 아이폰5를 테스트용 기기로 사용해온 개발자라면, 아이폰5S만 있으면 실제 구동 테스트를 할 수도 있을 것이다. 

그러나 군소개발업체에게 이는 상당한 부담으로 작용한다. 새 앱 개발을 위해 새로운 아이폰을 구매해야 하는 상황이다.

출처 : http://www.zdnet.co.kr/news/news_view.asp?artice_id=20130911142803

-----------------------------------------------------------------------------------------------------------------------
Pearl Fisher

전혀 낚시같지 않은 신개념 낚시게임이에요~


진주캐기 보러가기 클릭!

2013년 9월 4일 수요일

How to add UITextView in COCOS2D-iPhone




COCOS2D-iPhone에서 "UITextView"를 사용하기 위해서는 일단 클래스에 <UITextViewDelegate>를 추가해주어야 한다.

1. UITextView 정의

UITextView* _textView = [[UITextView alloc]initWithFrame:CGRectMake(x, y, w, h)];
    [_textView setBackgroundColor:[UIColor clearColor]];
    [_textView setKeyboardType:UIKeyboardTypeDefault];
    [_textView setFont:[UIFont fontWithName:@"Nanum Brush Script" size:24.0f]];
    // 네 변의 padding값 설정
    [_textView setContentInset:UIEdgeInsetsMake(t, 0.0f, 30.0f, 0.0f)];
    [_textView setScrollEnabled:YES];
    [_textView setDelegate:self];

2. UITextView 추가

[[[CCDirector sharedDirector]view]addSubview:_textView];


3. UITextView 제어

// 편집 시작시점에 발생하는 이벤트
- (void)textViewDidBeginEditing:(UITextView *)textView
{
    // textView를 키보드 위로 올라 오게끔 설정
    _textView.frame = CGRectMake(_textView.frame.origin.x,
                                 _textView.frame.origin.y, 
                                 _textView.frame.size.width,
                                 _textView.frame.size.height - 215); //resize
}
// 편집 끝나고 focus를 잃는 시점에 발생하는 이벤트
- (void)textViewDidEndEditing:(UITextView *)textView
{
    // 키보드를 숨길 것임으로 textView를 원래 사이즈로 복원
    _textView.frame = CGRectMake(_textView.frame.origin.x,
                                 _textView.frame.origin.y,
                                 _textView.frame.size.width,
                                 _textView.frame.size.height + 215);
}
// textView에 글자수가 변경될 때 발생하는 이벤트
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
    // 여기서 text는 현재 키보드 조작으로 입력된 텍스트를 의미한다.
}
// textView의 내용이 변경될 때 발생하는 이벤트
- (void)textViewDidChange:(UITextView *)textView
{
    // 입력된 총 글자수 확인은 이 메서드에서 하는것이 정확한 듯
}

3. UITextView의 제거

[_textView removeFromSuperView];
-----------------------------------------------------------------------------------------------------------------------
Pearl Fisher

전혀 낚시같지 않은 신개념 낚시게임이에요~


진주캐기 보러가기 클릭!

2013년 8월 30일 금요일

메모리 관리 Tip



- (void)dealloc
{
    CCArray* children = [self children];
    for(CCNode* tempNode in children)
    {
        if(tempNode != nil && 1 < [tempNode retainCount])
        {
            while(1 < [tempNode retainCount])
            {
                [tempNode release];
            }
        }
    }
 
    [[CCTextureCache sharedTextureCache] removeAllTextures];
    [super dealloc];
}

CCLayer에 addChild가 된 모든 CCSprite 이미지들을 배열로 만들어서 해당 배열의 모든 객체의 retainCount를 확인하고 release해주는 코드이다.

확장메서드

확장 메서드의 세가지 선언 규칙
  • static 클래스 안에 구현되어야 한다.
  • static 메서드로 선언되어야 한다.
  • 항상 첫 번째 파라미터에는 본인이 포함될 타입을 지정한다. 그리고 지정된 타입 앞에는 this 키워드가 위치해야 한다.
public static class ExtensionString
{
    public static string LongStringLimit(this StringBuilder src, int limitLength)
    {
        string limit = src.ToString();
 
        if (src != null) src = null;
        if (limit.Length <= limitLength) return limit;
        else 
        {
            limit = limit.Substring(0, limitLength);
            return String.Format("{0}...", limit);
        }
    }
}

Execute CRUD-LINQ

ExecuteCommand : 요청할 쿼리문과 쿼리문에 적용할 파라미터를 전달받아 실행하고 실행 결과를 int 타입으로 리턴한다.
                                이 값은 쿼리문이 실행된 이후에 영향받은 데이터 건수를 가진다.

Select


IEnumerable<Products> result = north.ExecuteQuery<Products>
            ("Select * from products where unitprice >= {0}", 100);
foreach(Products prod in result)
{
    Console.WriteLIne("ProductID : {0}, Unit Price : {1}", 
                      prod.ProductID, 
                      prod.UnitPrice);
}

Insert, Update, Delete

public void ExecuteCommandTest()
{
    const string insertProd = "insert into products values({0}, {1}, {3}, {4}, {5})";
    const string updateProd = "update products set UnitPrice = UnitPrice + 2.00 where UnitPrice >= {0}";
    const string deleteProd = "delete products where unitprice >= {0}";
 
    try
    {
        int insertAffectedCnt = north.ExecuteCommand(insertProd, "Test Prod",
                                                     10,         1,
                                                     "31 boxes", 7.00,
                                                     61);
        int updateAffectedCnt = north.ExecuteCommand(updateProd, 100);
        int deleteAffectedCnt = north.ExecuteCommand(deleteProd, 100);
  
        //변경 사항을 데이터베이스에 반영
        north.SubmitChanges();
 
        //추가, 수정, 삭제 처리 후 영향받은 데이터 건수 체크
        Console.WriteLine("추가된 건 수 : {0} 수정된 건 수 : {1} 삭제된 건 수 : {2}",
                      insertAffectedCnt, updateAffectedCnt, deleteAffectedCnt);
    }
    catch(Exception ex){ Console.WriteLine(ex.Message); }
}

저장프로시저와 함수 - LINQ

저장프로시저를 이용한 다중테이블 입력 방법
예 : Customers와 CustomersInfo 두 테이블 있고 회원가입시
       Customers에는 UserName, Password, Email을 입력하고
       CustomerInfo에는 FullName과 Customers에 Primary Key인 CustomerID를 입력한다면

DB에 Stored Procedure 생성

CREATE PROCEDURE [InsertCust]
@Username VARCHAR(10),
@Password CHAR(40),
@Email VARCHAR(100),
@Fullname NVARCHAR(10)
AS
DECLARE @CustomerID INT;
BEGIN TRY
    INSERT INTO [Customers] VALUES(@Username, @Password, @Email);
    SELECT @CustomerID = [CustomerID] FROM [Customers] WHERE [UserName] = @Username;
    INSERT INTO [CustomerInfo]([CustomerID], [FullName]) VALUES(@CustomerID, @Fullname);
END TRY

BEGIN CATCH
    RETURN ERROR_NUMBER()
END CATCH
GO

Entity설정

[Function(Name="dbo.InsertCust")]
public int InsertCust(
    [Parameter(Name="Username",DbType="VarChar(10)")] string username,
    [Parameter(Name="Password",DbType="Char(40)")]    string password,
    [Parameter(Name="Email",DbType="VarChar(100)")]   string email,
    [Parameter(Name="FullName",DbType="NVarChar(30)")]string fullname)
    {
        IExecuteResult result = this.ExecuteMethodCall(
        this,
        ((MethodInfo)(MethodInfo.GetCurrentMethod())),
        username, password, email, fullname);
    return ((int)(result.ReturnValue));
}

사용방법

CustomersEntity entity = new CustomersEntity(conn);
int insert = entity.InsertCust("tomebody", "han001122", "tome@naver.com", "Tome kim");
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-

저장프로시저를 이용한 다중테이블 조회 방법
예 : CustomerInfo, Products, Orders 3개의 테이블이 있다고 가정
       CustomerInfo에서는 FullName,
       Products에서는 ProductName,
       Orders에서는 UnitPrice, Amount를 읽어온다.
       단 CustomerID, ProductID를 기준값으로

DB에 Stored Procedure 생성


CREATE PROCEDURE [SelectOrderInfo] @CustomerID INT, @ProductID INT
AS
    SELECT c.FullName, p.ProductName, o.Quantity, (o.Quantity * p.UnitPrice) AS [Amount]
    FROM [CustomerInfo] c
    JOIN [Orders] o
    On c.CustomerID = o.CustomerID
    JOIN [Products] p
    On o.ProductID = p.ProductID
    WHERE c.CustomerID = @CustomerID And o.ProductID = @ProductID
GO

Entity설정


[Function(Name="dbo.SelectOrderInfo")]
public ISingleResult<SelectOrderInfoResult> SelectOrderInfo(
    [Parameter(Name="CustomerID",DbType="Int")]int CustomerID,
    [Parameter(Name="ProductID",DbType="Int")]int ProductID)
{
    IExecuteResult result = this.ExecuteMethodCall(
        this,
        ((MethodInfo)(MethodInfo.GetCurrentMethod())),
        CustomerID, ProductID);
    return((ISingleResult<SelectOrderInfoResult>)(result.ReturnValue));
}

public partial class SelectOrderInfoResult
{
    [Column]public string FullName { get; set; }
    [Column]public string ProductName { get; set; }
    [Column]public int Quantity { get; set; }
    [Column]public int Amount { get; set; }
}
SelectProcedure entity = new SelectProcedure(conn);

Entity설정

ISingleResult<SelectOrderInfoResult> Result = entity.SelectOrderInfo(1, 1);
foreach (SelectOrderInfoResult item in Result)
{
    Console.WriteLine("{0}-{1}-{2}-{3}",
        rs.FullName,
        rs.ProductName,
        rs.Quantity,
        rs.Amount);
}

-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
ISingleResult<TEntity> : 저장 프로시저의 실행 결과로 리턴되는 엔티티 클래스의 단일 결과집합을 가진다.