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 에 넣고 테스트 할 수 있다.