IanMK2 Blog

제가 오늘 얘기할것은 UICustomTableView사용시 많은 분들이 "빼먹는"것에 대한 것입니다.


UICustomTableViewCell은 아시다시피 단조로운 셀을 벗어나게 할 수 있는 소중하고 멋진 녀석이죠!

그런데 많은 분들이 커스템 셀의 경우 "큰" 실수를 하시는것을 많이 보았습니다.

일단 그 실수가 뭐인가 하기 전에 이 녀석을 한번 보죠!

dequeueReusableCellWithIdentifier


"어디서 많이봤는데.." 혹은, "앗 이 이녀석은.." 등 경험에 따라 눈에 익으신분도 있고 안 그러신분도 계실 것 입니다.

어디서봤을까요?

// Customize the appearance of table view cells.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    

    static NSString *CellIdentifier = @"Cell";

    

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if (cell == nil) {

        cell = [[[UITableViewCell allocinitWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];

    }

    

    // Configure the cell...

    

    return cell;

}



바로 셀을 리턴하는 함수에서 볼 수 있습니다.
용도는 뭘까요??

아시겠지만 테이블뷰는 몇개의 데이터만 뿌릴 수 도, 수 백개의  리스트를 출력하기도 합니다.
그런데 과연 출력할 데이터가 수백개일때 셀도 수백개를 메모리에 할당하는 것일까요?

답은 당연히 "아닙니다"

static NSString *CellIdentifier = @"Cell";

 
여기서 @"Cell"이 바로 키(key) 입니다.
셀에서 하나, 혹은 몇개만 할당 후 

[tableView dequeueReusableCellWithIdentifier:CellIdentifier];

이 코드 한줄로 할당한 셀(cell)을 찾아(deque) 재활용(reuse)하는겁니다


이제 이 함수가 이해 가시나요?


모르셨던분들은 메모리가 크지않는 아이폰에서 이 함수의 존재가 달리 보이실겁니다.



이제 제가 이야기하고자 하는 것의 본론으로 들어가보죠.


많은 분들이(심지어 몇몇 기본서에서도) 커스템셀의 사용법을 알려줄 때(xib생성방식으로 할 때)


      CustomTableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:cellName];

if (cell == nil) {
NSArray* nib= [[NSBundle mainBundleloadNibNamed:cellName owner:self options:nil];

    cell = [nib objectAtIndex:0];        

}


이렇게만 설명하고 끝이납니다.


자 우리는 이때 의심을 한번 가져봐야 합니다. 과연 위의 코드로 셀을 생성할 때 저 

dequeueReusableCellWithIdentifier

로 리턴된값이 항상 nil일 수도 있지않을까 라고 말이죠.

근거는 간단합니다.

커스텀이 아닐때와 비교해보면 말이죠.




cell = [[[UITableViewCell allocinitWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] 


NSArray* nib= [[NSBundle mainBundleloadNibNamed:cellName owner:self options:nil];

cell = [nib objectAtIndex:0];        


자 이제 의심이 가기 시작하시나요?


눈치채셨겠지만 기본 셀은 reuseIdentifier라는 인자로 구분자를 넘겨줌니다.

하지만 커스템셀생성시엔 전혀 그런 과정이 없죠.

따라서 tableview에는 셀이 어떠한 Identifier로 큐잉이 되지 않는거죠.


자. 그렇다면 해결법은 무엇일까요??

간단합니다. 저 identifier를 적어주면 되는것이지요.





저것을 적어주지않고 그냥 해서 스크롤 내릴때마다 메모리에 셀이 계속해서 올라가게 되기 때문이죠.

모두들 CustomTableViewCell사용시 주의하세요~!
Posted by IanMK2

끝까지위로 뒤집는 컬 효과는 UIViewAnimationTransitionCurlUp
또는 UIModalTransitionStylePartialCurl 등으로 효과를 낼 수 있다. 
하지만 원하는것은 절반만 뒤집어 아래에 숨겨진 버튼을 사용하는것.
구글에게 물었더니 다음과같이 따끈따근한 예제가!
 
CATransition *animation = [CATransition animation];

[animation setDelegate:self];

[animation setDuration:0.35];

[animation setTimingFunction:UIViewAnimationCurveEaseInOut];

if (!curled){

animation.type = @"pageCurl";

animation.fillMode = kCAFillModeForwards;

animation.endProgress = 0.58;

    } else {

animation.type = @"pageUnCurl";

        animation.fillMode = kCAFillModeBackwards;

animation.startProgress = 0.42;

}

[animation setRemovedOnCompletion:NO];

[[logo.view layer] addAnimation:animation forKey:@"pageCurlAnimation"];

if (!curled) {

logo.view.alpha = 0;

} else {

logo.view.alpha = 1;

}

curled = !curled;

Posted by IanMK2

Client가 adhoc버전의 파일을 원해 보냈는데 아무리 해도 설치가 안된단다.
내컴에서도 해봤는데 어랍쇼 이게왜 안되는거지..
그래서 구글신에게 물어보았더니 아래와같이 재밌게 해결법을 제시하셨다.


Ad hoc distribution of iPhone, and now iPad, applications can feel like a circus sideshow.  Developers come clambering out of the Provisioning Portal like its an undersized automobile to jump through flaming code signing hoops.  Generate a certificate, create an application id, add devices, create a provision, install them all and try not to get burned.  If you fail to do one step, or perform a step incorrectly, the application build results will usually guide you to the solution.  But what about when you do everything by the book and you still get an error?

The majority of my distribution issues usually sprout up when Apple releases a new version of the iPhone SDK.  This time it happened to be installing iPhone SDK 4.  After upgrading I needed to generate some Ad Hoc distributions.  Since these apps are only supposed to be targeted for iPhone devices, the "Base SDK" gets configured for "iPhone Device 4.0" and the "Targeted Device Family" is set to "iPhone". The only other parameter that needed changing was the "iPhone OS Deployment Target".  This app was not quite ready for "4.0" so I switched the value to "iPhone OS 3.1.3".

I configured three apps using the described values in exactly the same fashion.  The Ad Hoc distributions were generated and then zipped off to be installed.  To my dismay I received an email saying that one of the apps was incapable of being installed.  When the app is dragged into iTunes, nothing happens.  Successive attempts to drag the app into iTunes prompts this warning:

A provisioning profile named embedded.mobileprovision already exists on this computer.  Do you want to replace it?

Click the "Yes" button.  Nothing happens.  Click the "No" button.  Nothing happens.  At this point, I have no idea if I want to replace it.  I just want the app to sync with iTunes.  Time and time again I verify that all provisions are installed and configured properly.  Of course, none of which are named embedded.mobileprovision.  Search Google for embedded.mobileprovision and see what turns up.  Maybe a Twitter feed from a confused and frustrated developer.

There may be a multitude of reasons why this warning would appear when attempting an Ad Hoc installation but let me share with you the reason I was experiencing this issue.  Contrary to the message, the problem had nothing to do with an existing embedded.mobileprovision profile.  Some secret sleuthing lead me to believe that the issue originated when I choose a different "iPhone OS Deployment Target" in the project settings.  While I cannot prove this, I can at least show you some things to check manually before iAnarchy.

Every application has an Info.plist file that is created out of the box.  Find it in your application "Resources" group and it may look something like this:

 

Notice the dictionary entry "Application Requires iPhone Environment".  Notice the checkbox is clearly checked.  That makes sense.  We are developing an application using the iPhone SDK so it is only necessary that the application requires an iPhone environment.  Now open that same file as "Plain Text" to view the XML document which makes up this info dictionary.  Ours looks something like this:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>CFBundleDevelopmentRegion</key>
    <string>English</string>
    <key>CFBundleDisplayName</key>
    <string>${PRODUCT_NAME}</string>
    <key>CFBundleExecutable</key>
    <string>${EXECUTABLE_NAME}</string>
    <key>CFBundleIconFile</key>
    <string></string>
    <key>CFBundleInfoDictionaryVersion</key>
    <string>6.0</string>
    <key>CFBundleName</key>
    <string>${PRODUCT_NAME}</string>
    <key>CFBundlePackageType</key>
    <string>APPL</string>
    <key>CFBundleSignature</key>
    <string>????</string>
    <key>CFBundleVersion</key>
    <string>1.0</string>
    <key>LSRequiresIPhoneOS</key>
    <true/>
    <key>NSMainNibFile</key>
    <string>MainWindow</string>
    <key>UIStatusBarStyle</key>
    <string>UIStatusBarStyleBlackOpaque</string>
</dict>
</plist>

The pertinent key/value pair we are looking for is "LSRequiresIPhoneOS" and an XML node indicating <true/>.  999 times out of 1000 I would guess this is normal.  But on my 1000th attempt to build an app I see different a value:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>CFBundleDevelopmentRegion</key>
    <string>English</string>
    <key>CFBundleDisplayName</key>
    <string>${PRODUCT_NAME}</string>
    <key>CFBundleExecutable</key>
    <string>${EXECUTABLE_NAME}</string>
    <key>CFBundleIconFile</key>
    <string></string>
    <key>CFBundleInfoDictionaryVersion</key>
    <string>6.0</string>
    <key>CFBundleName</key>
    <string>${PRODUCT_NAME}</string>
    <key>CFBundlePackageType</key>
    <string>APPL</string>
    <key>CFBundleSignature</key>
    <string>????</string>
    <key>CFBundleVersion</key>
    <string>1.0</string>
    <key>LSRequiresIPhoneOS</key>
    <string>YES</string>
    <key>NSMainNibFile</key>
    <string>MainWindow</string>
    <key>UIStatusBarStyle</key>
    <string>UIStatusBarStyleBlackOpaque</string>
</dict>
</plist>

Notice how the value for <key>LSRequiresIPhoneOS</key> has been modified from a (bool)<true/> to a (string)<string>YES</string>.  How on earth this happened I cannot guarantee, but I can tell you that this is the reason "A provisioning profile named embedded.mobileprovision already exists on this computer".  If you take the time to manually replace the <string> node with a <true/> node you may be one step closer to a successful Ad Hoc distribution.

Posted by IanMK2

정말 사람 환장하게하는 에러다.
구글링결과 다음과같은 방법으로 해결

  1. Close your Xcode project
  2. Navigate to your project folder in the Finder
  3. Right click on your .xcodeproj file and ‘Show Package Contents’
  4. Drag the project.pbxproj file to Xcode (or any plain text editor)
  5. Perform a search for the term ‘provision’ to find the PROVISIONING_PROFILE entry.
  6. Copy the existing profile ID and paste it into the find field of a find and a replace dialog.
  7. Open up the Organizer window (Window menu > Organizer) and navigate to your new profile under IPHONE DEVELOPMENT > Provisioning Profiles
  8. Click on your provisioning profile and copy its Profile Identifier
  9. Paste the string into the replace field in your open find and replace dialog.
  10. Replace all instances of the identifier, save the file, close it, and reopen your Xcode project.
  11. That should do it, build and go to run your app on your new device.
Posted by IanMK2
A. 배포전에 진행사항
1. Distribution Provisioning Profiles 만들기
- 개발사이트 우측 Program portal
- App ID 만들기
: New App ID
: Description -> 어플id
: Bundle Seed ID -> Generate New (그대로)
: Bundle Identifier -> 홈페이지URL을 거꾸로 + 어플ID (예: kr.co.hello.skyworld )
- Provisioning -> Distribution
: New Profile
: (0)App Store -> Profile Name : 보통 어플 ID와 동일하게 입력 -> 위에 입력한 App ID 선택
- Provisioning Profile을 다운로드 받는다.
- Macintosh HD > 사용자 > 홍길동(?) > 라이브러리 > MobileDevice > Provision Profiles에 복사한다.

2. Xcode에서 배포파일 만들기
- Xcode project(Groups & Files) Info
: Configurations 탭에서 "Release" 항목을 아래 Duplicate한후 "Distribution"으로 Rename한다.
: Build 탭에서 좌측상단 Configuration을 Distribution으로 변경
: Base SDK를 iPhone Device 2.2.1로 변경한다.(아이폰2세대 지원할 경우)
: 항목중 Code Signing 에서 Any iPhone OS Device내용을 1.에서 만든 Provisioning
Profile을 선택한다. (iPhone Distribution : 홍길동)
- Resource 그룹 중에 Info.plist를 열면
: Bundle display name을 입력하고, Bundle identifier를 입력한다.(예:kr.co.hello.skyworld)
: Bundle version은 일반적으로 1.0으로 하고 향후 업뎃할때 1.1로 함

- 배포용 파일 만들기
: 상단 툴바 상태를 [ Device - 2.2.1 | Distribution ]으로 한다. (2.2.1 지원할 경우)
: 메뉴바에서 Build를 선택한 후 [ Build ]를 한다.
: 빌드가 성공하면 Groups & Files의 Products 그룹에 Project name .app가 생성된다.
: .app에 마우스 우클릭하여 Reveal in finder를 선택한다.
: finder폴더 위치가 프로젝트 - build- Distribution iphoneos 로 연결된다.
: 확장자 없는 파일이 배포될 파일이다.
: 확장자 없는 파일을 압축한 후 (.zip) 개발 사이트를 통해 앱스토어에 등록한다.

B. AppStore에 등록하기
1. iPhone Developer Program
a. Over view
- iTunes Connect -> Manage Your Applications -> Add New Application
- Does your prodect contain encryption ? 암호화 유무
- Application name : 앱스토어에 나타나는 이름
- Applicaiotn Description : 앱스토에에 나타나는 어플 설명
- Device Requirements : 아이폰, 이이팟 선택
- Primary Category, Secondary Category : 장르 선택
- Copyright : 자작권자
- Version Number : 어플리케이션 버전, Xcode Boundle version (예: 1.0)
- SKU Number : 개발자가 관리하는 관리코드, 본인이 관리하는 어플의 유일코드
- Keywords : 검색어 (주의사항 : 자작권위반, 유명인사이름, 애플관련 단어는 절대 안됨)
- Application URL, Support URL : 개인 블로그나 기타 어플 피드백용 홈페이지
- email...
- Demo : 리뷰어가 어플 테스트시 도움이 되는 설명사항
----------------
b. Ratings
- 등급 넣기 : 일반적으로 NONE
----------------
c. Upload
- Application : Build한후 zip으로 만든 파일 , Upload 완료후에 iPhone3.0테스트 완료했다는 체크 하기
- Large 512 icon : 512*512 jpg파일 -> 어플의 57*57아이콘과 동일한 이미지로 하기 , 앱스토어에 노출됨
- Primary Screenshot: 어플 화면
- Additional Screenshots : 등록할때 뒷부분 이미지부터 선택할 것 4->3->2->1순으로.
----------------
d. pricing
날짜 선택 : in Review 후 Ready For Sale되면 RFS 날짜 기준으로 판매 될 예정, 손 볼 것 없음
가격 선택 : 표를 보고 확인하기.
----------------
e. localization : 각 국가별 언어로 해당 언어를 따로 보여 주기
예: korean을 선택후 어플 이름, 설명을 한글로 넣으면 한국앱스토어에선 한글로 나타남
----------------
f. Review
위 사항 최종 확인
----------------
일단 등록 끝

C. 애플에서의 진행 상태
1) Waiting for Review : 테스트 대기상태
2) In Review : 애플에서 어플 테스트 중
3) Ready for sale : 앱스토어에 판매 대기 및 판매중
4) Reject : 판매 보류, 이후는 어플리케이션 수정후 B.사항부터 할 것 version은 수정하지 않는다.

---------------
Posted by IanMK2