2015년 12월 21일 월요일

swift extension 으로 UITableViewDataSource, UITableViewDelegate 함수 작성 하기

Objective - C를 기반으로 앱을 개발 해 왔다.
개발 가닥은 이미 알고 있기 때문에 ViewController에 TableVeiw 를 추가 해서 기능을 구현 하려 하면

UITableViewDataSource, UITableViewDelegate 를 상속 받아서
delegate메서드를 추가 해야 하낟.

swift도 마찬가지라 생각 하고

바로

clase SomeViewConteroller: UIViewController {

}

==>

class SomeViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

}

이렇게 상속 받은 다음

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.menuName.count

    }
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        
        let cell: HomeMenuTableViewCell = self.tableView.dequeueReusableCellWithIdentifier("HomeMenuTableViewCell") as! HomeMenuTableViewCell
        
        cell.menuImage.image = UIImage(named: self.iconName[indexPath.row])
        cell.menuLabel.text = self.menuName[indexPath.row]
        cell.checkOnOffImage.image = UIImage(named: self.checkOnOff[indexPath.row])
        
        return cell
        
    }
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        print("You selected cell #\(indexPath.row)!")
    }
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
        let isHighRes = UIDevice.currentDevice().isHighResolution
    
        if isHighRes {
            //return 99
            return 66
        }
        else
        {
            return 66
        }
    }


위와 같은 함수를 작성 해 주면 된다.

swift를 쓰니까
extension을 이용 할 수 있다.

class 선언 부는 그대로 두고

}
클래스 브레이스 끝 하단에
extension SomeViewController: UITableViewDataSource {
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.menuName.count
    }

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        
        let cell: HomeMenuTableViewCell = self.tableView.dequeueReusableCellWithIdentifier("HomeMenuTableViewCell") as! HomeMenuTableViewCell
        
        cell.menuImage.image = UIImage(named: self.iconName[indexPath.row])
        cell.menuLabel.text = self.menuName[indexPath.row]
        cell.checkOnOffImage.image = UIImage(named: self.checkOnOff[indexPath.row])
        
        return cell
        
    }

    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        print("You selected cell #\(indexPath.row)!")
    }
}

extension  SomeViewController: UITableViewDelegate {
    func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
        return 66
    }
}

이렇게 extension으로 작성을 해도 된다.


그럼 요런 넘들을 Ctrl + Opt + Cmd + 2 
Show The Code Snipet Library 에 추가 하고

중간 중간  수정 해야 하는 부분에  <#Code#> 로 처리를 하면 아주 좋은 스니핏 라이브러리가 된다.

textFieldDelegate도 마찬가지!



2015년 12월 8일 화요일

UIButton 배경이미지를 원 텍스쳐를 가지고 늘려서 버튼 만들기

무슨 말인고 하니

원으로된 png 리소스를 가지고 왼쪽 둥글게 가운데 텍스트 오른쪽 둥글게
이렇게 생긴 버튼으로

가변 길이로 버튼을 만들려고 하면 어찌 해야 하는가 이다.

Images.xcassets 를 선택 하면 다음과 같은 원 이미지가 있다고 할 때


메뉴에서 Editor -> Show Slicing


아래 처럼 Start Slicing 버튼이 보인다.


원하는 자르기 방향을 선택 하고



그중 하나를 선택 하면 나뉘어진 크기를 설정 할 수 있다.



그리고 UI Button에 이미지를 background로 설정 하면 storyboard 상에서는 찌그러진 상태
그대로 나오지만 runtime에는 원하는 예쁜 상태로 나온다.

2015년 12월 6일 일요일

xcode interface builder 에서 hex값 (RGB) 칼라 입력 하기

이번 미션에 GUI 디자이너님이 hex 값으로 색상을 남발 한다.
그럴때마다. 이걸 코드로 해야 하나 어쩌나 ..  ㅠㅠ

인터페이스 빌더에서 색상을 설정 할때 RGB hex 값을 어떻게 입력 하나...




인터페이스 빌더에서 칼라의  상하 표시를 누른다음 Other를 선택

첫번째 칼라휠, 두번째 칼라 슬라이더 ..... 이렇게 상단에 아이콘이 있다.

칼라 슬라이더 두번째 것을 고른다 기본은

Gray Scale Slider인데 이것을 RGB Sliders로 선택하면
위와 같은 그림에 Hex Color # 입력 화면이 있다.
여기에 hex 코드 값을 3바이트를 입력 하면 원하는 색상으로 선택이 가능 하다.

2015년 12월 5일 토요일

iOS Launch 화면에 Button을 추가 하려면?

이번 미션에서  splash 이미지 하단에 시작 버튼을 넣어 달라는 고객!

음.. 자동으로 만들어지는 LaunchScreen.xib 에 Button을 넣고
Class를 코드를 만들어서 Button 이벤트를 코딩 하는 방법?

이건 아닌 듯 하다.

처음에는 이것으로 어떻게 꾸역 꾸역 처리가 될줄 알고 삽질을 하였다.
일단 포기

AppDelegate 에서 MainViewController는 이미 UINavgationBar를 가지도록 구상 했다.

splash 화면은 전체화면으로 나와야 한다.

그래서 내가 구상한 방법은

AppDelegate에서

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
}

여기서 일단 IntroViewController (전체 화면에 시작 버튼만을 가진 놈으로 시작을 한다.)

그런다음 IntroViewController에서 Button 이벤트에서
AppDelegate의 다시 window에 rootViewController를 MainViewController로 달아주는 방법이다.

IntroViewController에서 AppDelegate를 참조 하는 방법은 다음과 같다.

let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate

그러면 AppDelegate에서 UINavigationBar를 붙이고 하는 모든 작업을 IntroViewController에서 코드로 구현 할 수 있기 때문에 Splash화면에서 Button으로 다음 진행을 할수 있다.





2015년 12월 3일 목요일

Images.xcassets 작업 하기

이미지 리소스 파일이 수십개 
그리고 각각 2x  , 3x  파일들이 수십개 있다.

이런것을  xcode의  images.xcassets 에 넣는 작업을 한다고 할때

드레그 해서 넣으면.. 어떻게 될까

예를 들어 
button@2x.png
button@3x.png

이러한 파일을 그냥 집어 넣으면

button
button-1

이렇게 두개의 아이템이 된다.

이런경우 하나는 2x 나머지 하나는 3x 이미지를 가지고 있다.

images.xcassets를 파인더에서 보면
그냥 폴더이고 하위에 button폴더와 button-1 폴더가 존재 하고
그하위에는  json 파일과 실제 button@2x.png 파일이 존재 한다.

이것을 일일이 복사하고 json 파일을 편집하는 것은 거의 미친 짓이다.

그럼 해결 방법은 







2015년 12월 2일 수요일

계층형에 내부 반복 (Array) 로 복잡한 json 문자열 생성하기

이번 미션에서는 어떠한 데이터를 받아서 json문자열을 생성 해야  한다.

지금 까지는 간단한 key :  value 형태의 json 문자열을 생성하여  WAS통신 하는 앱을 개발 했는데 그것은 간단한 NSArray 의 key value를 SBJson 모듈에 넣어서 생성 하면 간단 했다.

이번의 경우는

     timezone
     activity
        -- startTime
        -- stopTime
        -- calorie
        -- detail
            --startTime
            --stopTime
            --stepCnt
            -- distance
            -- mode
     sleep
        -- startTime
        -- stopTime
        -- calorie
        -- detail
            -- startTime
            -- stopTime
            -- settingstartTime
            -- settingstopTime
     

            mode


위와 같은 json 형태가 되는데 active 의 하위 key가 있고 그중 detail은 또 하위를 가지며
detal은 mode에 따라서 여러번 반복된다.
마찬가지로 sleep도 마찬가지이다.


    //sleep.detail
    NSMutableDictionary * sleep_detail1 = [[NSMutableDictionary alloc] init];
    [sleep_detail1 setValue:@"200" forKey:@"startTime"];
    [sleep_detail1 setValue:@"200" forKey:@"stopTime"];
    [sleep_detail1 setValue:@"200" forKey:@"settingstartTime"];
    [sleep_detail1 setValue:@"200" forKey:@"settingstopTime"];
    [sleep_detail1 setValue:@"Awake" forKey:@"mode"];

    NSMutableDictionary * sleep_detail2 = [[NSMutableDictionary alloc] init];
    [sleep_detail2 setValue:@"200" forKey:@"startTime"];
    [sleep_detail2 setValue:@"200" forKey:@"stopTime"];
    [sleep_detail2 setValue:@"200" forKey:@"settingstartTime"];
    [sleep_detail2 setValue:@"200" forKey:@"settingstopTime"];
    [sleep_detail2 setValue:@"Light Sleep" forKey:@"mode"];

    NSMutableDictionary * sleep_detail3 = [[NSMutableDictionary alloc] init];
    [sleep_detail3 setValue:@"200" forKey:@"startTime"];
    [sleep_detail3 setValue:@"200" forKey:@"stopTime"];
    [sleep_detail3 setValue:@"200" forKey:@"settingstartTime"];
    [sleep_detail3 setValue:@"200" forKey:@"settingstopTime"];
    [sleep_detail3 setValue:@"Deep Sleep" forKey:@"mode"];

    NSArray *sleep_detail_array = [NSArray arrayWithObjects: sleep_detail1,
                                   sleep_detail2,
                                   sleep_detail3,
                                   nil ];
    
    //sleep
    NSMutableDictionary * sleepData = [[NSMutableDictionary alloc] init];
    [sleepData setValue:@"200" forKey:@"startTime"];
    [sleepData setValue:@"200" forKey:@"stopTime"];
    [sleepData setValue:sleep_detail_array forKey:@"detail"];
    [sleepData setValue:@"200" forKey:@"calorie"];
    
    
    //activity.detail
    NSMutableDictionary * activity_detail1 = [[NSMutableDictionary alloc] init];
    [activity_detail1 setValue:@"200" forKey:@"startTime"];
    [activity_detail1 setValue:@"200" forKey:@"stopTime"];
    [activity_detail1 setValue:@"200" forKey:@"stepCnt"];
    [activity_detail1 setValue:@"200" forKey:@"distance"];
    [activity_detail1 setValue:@"Non-move" forKey:@"mode"];

    NSMutableDictionary * activity_detail2 = [[NSMutableDictionary alloc] init];
    [activity_detail2 setValue:@"200" forKey:@"startTime"];
    [activity_detail2 setValue:@"200" forKey:@"stopTime"];
    [activity_detail2 setValue:@"200" forKey:@"stepCnt"];
    [activity_detail2 setValue:@"200" forKey:@"distance"];
    [activity_detail2 setValue:@"Walking" forKey:@"mode"];

    NSMutableDictionary * activity_detail3 = [[NSMutableDictionary alloc] init];
    [activity_detail3 setValue:@"200" forKey:@"startTime"];
    [activity_detail3 setValue:@"200" forKey:@"stopTime"];
    [activity_detail3 setValue:@"200" forKey:@"stepCnt"];
    [activity_detail3 setValue:@"200" forKey:@"distance"];
    [activity_detail3 setValue:@"Fast Walking" forKey:@"mode"];

    NSMutableDictionary * activity_detail4 = [[NSMutableDictionary alloc] init];
    [activity_detail4 setValue:@"200" forKey:@"startTime"];
    [activity_detail4 setValue:@"200" forKey:@"stopTime"];
    [activity_detail4 setValue:@"200" forKey:@"stepCnt"];
    [activity_detail4 setValue:@"200" forKey:@"distance"];
    [activity_detail4 setValue:@"Running" forKey:@"mode"];

    NSArray *activity_detail_array = [NSArray arrayWithObjects: activity_detail1,
                                   activity_detail2,
                                   activity_detail3,
                                   activity_detail4,
                                   nil ];
    
    //activity
    NSMutableDictionary * activity = [[ NSMutableDictionary alloc] init];
    [activity setValue:@"200" forKey:@"statTime"];
    [activity setValue:@"200" forKey:@"stopTime"];
    [activity setValue:activity_detail_array forKey:@"detail"];
    [activity setValue:@"200" forKey:@"calorie"];
    
    //sync
    NSMutableDictionary * sync = [[ NSMutableDictionary alloc] init];
    [sync setValue:@"SEOUL" forKey:@"timezone"];
    [sync setValue:activity forKey:@"activity"];
    [sync setValue:sleepData forKey:@"sleep"];
    
    NSError *err;
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:sync options:NSJSONWritingPrettyPrinted error:&err];
    
    NSLog(@"JSON = %@", [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]);


실제 디버깅 정보로 위에서 생성한 데이터가 json 문자열로 어떻게 생성되었는지 확인해보면
다음과 같다.
JSON = {
  "timezone" : "SEOUL",
  "activity" : {
    "stopTime" : "200",
    "detail" : [
      {
        "startTime" : "200",
        "stopTime" : "200",
        "stepCnt" : "200",
        "distance" : "200",
        "mode" : "Non-move"
      },
      {
        "startTime" : "200",
        "stopTime" : "200",
        "stepCnt" : "200",
        "distance" : "200",
        "mode" : "Walking"
      },
      {
        "startTime" : "200",
        "stopTime" : "200",
        "stepCnt" : "200",
        "distance" : "200",
        "mode" : "Fast Walking"
      },
      {
        "startTime" : "200",
        "stopTime" : "200",
        "stepCnt" : "200",
        "distance" : "200",
        "mode" : "Running"
      }
    ],
    "statTime" : "200",
    "calorie" : "200"
  },
  "sleep" : {
    "startTime" : "200",
    "stopTime" : "200",
    "detail" : [
      {
        "startTime" : "200",
        "stopTime" : "200",
        "settingstopTime" : "200",
        "settingstartTime" : "200",
        "mode" : "Awake"
      },
      {
        "startTime" : "200",
        "stopTime" : "200",
        "settingstopTime" : "200",
        "settingstartTime" : "200",
        "mode" : "Light Sleep"
      },
      {
        "startTime" : "200",
        "stopTime" : "200",
        "settingstopTime" : "200",
        "settingstartTime" : "200",
        "mode" : "Deep Sleep"
      }
    ],
    "calorie" : "200"
  }
}

2015년 12월 1일 화요일

Please verify that your device’s clock is properly set, and that your signing certificate is not expired. (0xE8008018).

Please verify that your device’s clock is properly set, and that your signing certificate is not expired. (0xE8008018).

간만에 앱개발을 하려고 하는데 이런 에러를 만나면 많이 놀라셨죠.



Apple Developer Member Cnter에 접속해서

개발인증서가 만료가 되어서 그런것이다.
개발자 등록을 새로 갱신 했어도 인증서는 말료 될수 있으므로 새로 갱신 해주고 앱 프로비젼잉도 편집 해서 새로 제너레이트 해주면 된다.


iOS DevelopmentApp ID:
Xcode: iOS Wildcard AppID (*)


이왕 할때 * 즉 App ID를 와일드 카드로 만들고
이 AppID 로 개발 Provisioning Profile을 만들면

어떠한 번들 ID로 설정된 앱도 이 Provisioning Profile로 iPhone 에 넣고 테스트 할 수 있다.



2015년 11월 17일 화요일

pyodbc를 이용한 데이터 베이스

pyodbc를 이용한 간단한 데이터 베이스 접속및 쿼리를 수행 할 수 있다.

import pyodbc

ip = '127.0.0.1'
port = 20300
username = 'sys'
password = 'manager'
connstr = connstr = "DSN=ALTIBASE_SHARD;Server=%s;Port=%i;UID=%s;PWD=%s" % (ip, port, username, password)

dbconn = pyodbc.connect(connstr)
dbcursor = dbconn.cursor()

querystr = 'select * from t1'

dbcursor.execute(querystr)
rows = dbcursor.fetchall()

for row in rows:
    my_list.append(row)

데이터 베이스에 접속 해서 테이블을 셀릭트 해서 결과를 리스트에 받아 보는 예제 이다.

프로시져를 수행 하고 싶을 경우에는
'{call 프로시져명}'

의 형태의 쿼리문을 execute()메서드에 호출 해야 한다.

pyqt4 TableView컨트롤과 함께 이용하면 Query결과를 테이블뷰에 표시할 수 있다.

2015년 11월 13일 금요일

pyqt QTableView 다루기

QTableView 다루기

TableModel Class

QTDesigner에서 TableVirw 컨트롤을 디자인 한다.

이는 Table로 표시하는 (GRID) 컨트롤이다.

이를 다루기 위해서는 TableModel Class가 필요 하다.

code:

class MyTableModel(QAbstractTableModel):
    def __init__(self, parent, mylist, header, *args):
        QAbstractTableModel.__init__(self, parent, *args)
        self.mylist = mylist
        self.header = header
    def rowCount(self, parent):
        return len(self.mylist)
    def columnCount(self, parent):
        #return len(self.mylist[0])
        return len(self.header)
    def data(self, index, role):
        if not index.isValid():
            return None
        elif role != Qt.DisplayRole:
            return None
        return self.mylist[index.row()][index.column()]
    def headerData(self, col, orientation, role):
        if orientation == Qt.Horizontal and role == Qt.DisplayRole:
            return self.header[col]
        return None
    def sort(self, col, order):
        """sort table by given column number col"""
        self.emit(SIGNAL("layoutAboutToBeChanged()"))
        self.mylist = sorted(self.mylist,
            key=operator.itemgetter(col))
        if order == Qt.DescendingOrder:
            self.mylist.reverse()
        self.emit(SIGNAL("layoutChanged()"))


위 코드는 일반적인 테이블뷰의 모델 클래스 이다.

list 형의 데이터로 헤더,와 데이터 를 파라메터로 주면 테이블이 표시 된다.

node_table_header = ['Node Name', ' Server IP', ' Server Port']

node_data_list = [
#('NDOE1','127.0.0.1',20300)
]

node_table_model = MyTableModel(self, node_data_list, node_table_header )


 self.tblViewNode.setModel(node_table_model)


위 코드는 tblViewNode (QTableView) 객체에 헤더만 구성된 빈 테이블 뷰를 표시한다.

node_data_list[]에 데이터가 체워지면 화면에 표시 될수 있다.

이벤트 핸들러

self.tblViewNode.doubleClicked.connect(self.btnChangeNodeClick)
위와 같이 더블 클릭시에 호출할 함수를 연결 할 수 있다.


편집 기능이 추가된 TableModel Class 만들기

    def flags(self, index):
        if index.column() == 1: #range만 편집 가능
            return Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsEditable
        else:
            return Qt.ItemIsEnabled | Qt.ItemIsSelectable
TableModel Class에 위와 같은 함수를 추가 하면 두번째 컬럼 열은 편집 가능 한 cell 이 된다.
더블클릭을 하면 편집 모드로 진입 한다.

편집된 데이터는 data_list에 저장이 되어야 실제로 저장이 된다.
그러기 위해서는  setData 함수를 구현 해야 한다.

    def setData (self, index, variant, role=Qt.EditRole):
        if variant.toInt()[1] == True:
            self.mylist[index.row()][index.column()] = variant.toInt()[0]
        else:
            self.mylist[index.row()][index.column()] = 0
        return True

입력된 variant 값이 숫자형인 경우만 입력을 허용 하고 문자인 경우 0으로 대체 하는
예제이다.



pyqt evnet handler 연결 하기

QTDesigner를 이용하여 main폼을 디자인 한다.

이렇게 디자인된 button을 적당한 이름으로 적용 하여 .ui 파일을 생성 하고
이를 pyuic.py를 이용하여 파이썬 코드를 생성하면

main.py 파일이 생성되고
button 객체에 이름이 부여되어 생성 된다.

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName(_fromUtf8("MainWindow"))
        MainWindow.resize(680, 543)
        self.btnAddNode = QtGui.QPushButton(self.layoutWidget)
        self.btnAddNode.setObjectName(_fromUtf8("btnAddNode"))

위 코드는 main.py 로 btnAddNode 라는 이름의 button이 디자인되어 있는
제너레이트된 코드에 일부이다.

이를 이용하는 코드 에서는

button이 눌렸을때 실행 해야할 코드를 작성하고 connect() 함수를 이용하여

아래에 코드처럼 이벤트 발생시 호출 할수 있도록 연결 해야 한다.

btnAddNodeClick() 함수가 연결된 함수이다.

code:

import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *

from main import *

class TestApp (QMainWindow, Ui_MainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        self.setupUi(self)
        self.connect(self.btnAddNode, SIGNAL("clicked()"), self.btnAddNodeClick)

    def btnAddNodeClick(self):
        pass


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = ShardGui()
    window.show()
    sys.exit(app.exec_())

python pyqt GUI 개발 - QTDesigner

https://github.com/sparrowapps/learn_python/blob/master/gui/QTDesigner.txt

QT Designer 사용하기
윈도우 ananconda 패키지에 경우
C:\Anaconda3\Lib\site-package\PyQt4
에 QT Designer 실행 파일이 존재 한다.
폼 , 다이얼로그를 이프로그램을 이용하여 디자인 하면
.ui 파일이 생성된다.
.ui파일은 xml 형식으로 되어 있다.
이를 바로 python에서 로드하여 사용 하는 방법도 있다.
하지만 이렇게 생성된 파일을 python 소스 코드로 변환 하여 바로 소스로 이용하는 방법이 있다.
C:\Anaconda3\Lib\site-package\PyQt4\uic
pyuic.py 파일을 이용하면 된다.
python C:\Anaconda3\Lib\site-packages\PyQt4\uic\pyuic.py -x about.ui -o about.py
about.ui 파일을 about.py 파이썬 소스 코드로 변환 시킨다.

Mac OS ananconda package를 사용하는 경우 QT Designer
/Users/계정명/anaconda/bin
에 Designer.app으로 존재 한다.
pyuic.py 모듈 위치
/Users/계정명/anaconda/pkgs/pyqt-4.11.3-py34_0/lib/python3.4/site-packages/PyQt4/uic
같은 방법으로 리소르를 빌드 해서 클래스모듈로 변환 하여 사용 가능 하다.

OS X에 별도로 python 및 PyQt4를 설치 한경우
OS X python install
http://python-guide-kr.readthedocs.org/ko/latest/starting/install/osx.html
python , homebrew
#brew install qt
#brew install sip
#brew install pyqt
http://download.qt.io/archive/qt/4.8/4.8.6/
에서 qt creator를 설치 하여 qt designer를 사용 할 수 있다.
디자인한 UI는 .ui 파일로 저장되고 python 용 uic를 이용하여 .py 코드를 얻을수 있다.
pyuic사용 방법
sparrow:/usr/local/Cellar/pyqt/4.11.3/lib/python2.7/site-packages/PyQt4 sparrow$ python ./uic/pyuic.py -x hello.ui -o hello.py

2015년 10월 22일 목요일

가상머신 OS에서 듀얼 모니터 사용하기

가상 머신에 윈도우를 요즘 윈도우 어플 개발 할 일이 있어서 자주 이용한다.

듀얼 모니터를 사용하다가 가상 머신에 Windows 에서 갑자기 모니터가 하나가 되니 답답해 진다.

동시 실행 모드가 해결 법인듯 하지만 먼가 살짝 불편함이 있고 느릿해지는 느낌은 어쩔수 없다.

당연한 건대 내가 실행 하지 않고 있었다.

parallels 11 / OS X 엘캐피텐에서 잘 동작 된다.

덕분에 Windows 10에서도 듀얼 모니터를 활용해서 개발에 편리 함을 누린다.


2015년 10월 6일 화요일

parallels 가상 머신간에 네트워크가 필요한 경우




parallels 가상 머신 윈도우와
parallels 가상 머신 리눅스를
동시에 동작 시켜서
가상 머신 윈도우에서 가상머신 리눅스에 무언가 접속을 하고 싶은 경우
기본적을 설정된 공유 인터넷 설정으로는 접속을 할 수가 없다.

물론 외부에서도 가상 머신으로 네트워크 접속을 가능 하게 할 방법이 없다.



공유기 --------- OS X ------- 윈도우
                                        |
                                        +--- 리눅스

위와 같은 설정에서
아래와 같은 설정으로 변경은



공우기 ----------OS X
                   +----윈도우
                   |
                   +----리눅스

네트워크 브리지를 사용 하는 것이다.

http://egloos.zum.com/accuram/v/4729291
위 사이트에서 자세한 설명이 있다.


parallels 에서 가상 머신 수행중에 다음과 같이 설정을 변경 하면 간단하게 네트워크 브리지로
변경이 되고 가상 머신 윈도우에서 가상머신 리눅스에 접속 할 수 있다.


가상머신 윈도우와 가상머신 리눅스를 모두 네트워크 브리지로 변경 하고 나면 모두 192.168.xx.xx의 아이피로 변경이 되고 모두 엑세스가 가능 하다.



2015년 10월 4일 일요일

parallels 가상 디스크 용량 줄이기

256기가 SSD가 장착된 맥북프로에서 어쩔수 없이 사용하는 윈도우 가상 머쉰에 이미지 크기가 60기가  넘어가면 너무 부담 스럽다.

얼마전 타임머신 복원에서 가상디스크 이미지가 사라지는 문제때문에 자세히 설정을 찾아 보니 타임머신에서 제외 되는 이유가 있었던 백업 설정
그리고 이 백업 설정에 덤으로 SmartGuard라는 설정 까지 선택해서 스냅샷 이미지가 생성 되어 있는 상태였다.


간단하게 위 화면에서 확보 버튼 눌러야 고작 몇 메가 바이트 정도 확보된다.
현재 화면은 70기가에 육박했던 이미지를 실제 사용 용량인 35기가로 줄인 화면이다.


스마트 가드에 설정을 제거 하고 스냅샷 이미지를 모두 제거 해야 위 화면에 압축 버튼이 가능 하다. 
처음에는 압축 버튼을 눌러 봐야 용량 확보가 되지 않아 이유를 몰랐는데 스냅샷을 모두 제거 하고 나니 디스크 용량을 대폭으로 줄일수 있었다.

스냅샷 제거는 상단에 패럴럴 아이콘을 클릭해서 메뉴중에 스냅샷 관리로 스냅샷을 제거 해야 한다. 스냅샷을 생성해두면 가상머신을 이전 상태로 돌릴수 있어서 좋은 기능이긴 하나 가상머신 이미지 크기가 좀더 늘어나고 이유없이 가상머신 파티션 크기에서 모든 용량을 다 쓰는것처럼 이미지가 크다는게 문제 점이다.