iOS7에서 UITableViewCell의 AccessoryView에 버튼을 배치하고 버튼의 selector에서 cell을 참조하기

아래와 같이 특정 서비스에서 친구를 초대하거나 follow할 때 주로 쓰는 UI화면이 있다. UITableView에 UITableViewCell 혹은 이를 상속받는 클래스 구조인데, 여기서 Invite 버튼을 터치했을 때 버튼이 속하는 NSIndexPath를 받기 위해 아래와 같이 코딩을 할 때가 있다. /* UITableView의 data source 메소드 중 cellForRowAtIndexPath: 메소드 */ – (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (!cell) { UIButton *inviteButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; /* 프로퍼티 정의는 생략 */ [inviteButton addTarget:self action:@selector(onInvite:) forControlEvents:UIControlEventTouchUpInside]; cell.accessoryView = inviteButton; } return cell; } /* Invite 버튼의 selector 메소드 */ – (void)onInvite:(id)sender { if ([sender isKindOfClass:[UIButton class]]) { UIButton *inviteButton = (UIButton *)sender; UITableViewCell *selectedCell = (UITableViewCell *)[inviteButton superview]; NSIndexPath *indexPath = [_tableView indexPathForCell:selectedCell]; NSLog(@"selected row is :%d", indexPath.row); } } 이 경우 onInvite: 메소드의 [inviteButton superview] 가 iOS7 미만에서는 포인터를 가져오는데 문제가 없었지만 iOS7 부터는 문제가 된다. view의 구조를 봤을 때 Invite 버튼은 UITableViewCell의 accesoryView로 대치되었기 때문에 superview는…

다각형의 버튼들 배치

일반적으로 버튼은 rectangle. 즉, 사각형의 영역으로 범위를 정의한다. 하지만 위 스크린샷(노란색과 파란색이 각각 버튼이다.)처럼 종종 다각형(polygon) 형태의 버튼 모양이 디자인으로 나올 수 있고 이를 무조건 rectangle로 만들라고 디자이너에게 요구할 수도 없다. 다각형 버튼 각자의 영역이 겹치지 않는다면 큰 문제가 되지 않지만 여기서 문제는 겹칠 때. 이 때는 respond가 addSubview 메소드를 나중에 호출한 버튼이 호출된다. 당연하다. iOS의 UIView 구조는 포토샵의 레이어와 유사한 구조이다. 이를 해결하기 위해서는 여러가지 방법이 있을 수 있지만 가장 효율적인 방법은 터치한 지점에 해당하는 버튼 이미지의 alpha 값을 가지고와 미리 정해놓은 threshold와 비교해서 response를 return값으로 판단할 수 있다. 이를 충실하게 구현해놓은 Open Source가 있어서 소개한다. https://github.com/ole/OBShapedButton 위 코드는 UIButton을 상속받은 OBShapedButton 클래스와 특정 지점의 Alpha값을 가지고 올 수 있도록 메소드가 정의된 UIImage의 category 클래스가 전부이다. 사용법은 두 클래스를 프로젝트에 추가하고 UIButton으로 정의하던 클래스를 OBShapedButton으로 정의하면 된다. 이 코드는 대부분의 iOS에서 사용할 수 있다. 추가적인 팁으로 화면에 여러 개의 버튼이 배치되었을 때 동시에 버튼들을 누르면 모두 눌러지는 것을 확인할…

Tumblr API(v2)를 이용해 Link 연동 시 Link의 메타이미지가 나타나지 않는 문제를 해결하는 꼼수

오랜만의 포스팅이네요. 이직과 육아라는 핑계를 대보며.. Tumblr API는 언뜻봐서는 참 심플합니다. OAuth 1.0a를 이용하고 REST 방식을 충실히 따르고 있습니다. (사실 OAuth 1.0a는 OAuth 2.0에 비해 참 까탈스럽기는 하죠.. 그래서 xAuth도 제공하지만 이는 Twitter와 같이 따로 승인을 받아야 합니다.) 이 글을 통해 공개할 팁은 API를 이용해 Link를 공유할 때의 팁입니다. Tumblr에서는 post 시 여러 type 들(Text / Photo / Link / Video / Quote / Audio / Chat)이 존재합니다. 만약 Tumblr API를 이용하여 특정 Link를 공개할 때 쉽게 생각한다면 type=link로 생각하실 것입니다. 하지만 이렇게 한다면 아래와 같이 web에서의 결과와 다른 결과를 볼 수 있습니다. 아래는 web에서 Link를 선택하여 직접 포스팅한 결과로 공유한 Link에 포함된 이미지를 보여줍니다. 반면, API로 해당 작업을 수행하면 아래와 같이 대표 이미지가 없이 포스팅됩니다. 상/하단 이미지를 보시면 차이점이 확실히 드러나죠? 링크만 덜렁 나타나니 업로드해도 참 보기 좋지 않은데요. 이럴 때는 이렇게!! 우선 post 타입은 link가 아닌 photo로 설정하고, parameter로 link에 공유할 link를 source에 대표적으로 보여줄 이미지 URL을 넣어줍니다.…

포인터형 CF Object를 NS Object로 bridge 하기

iOS 내부에는 NS Object와 함께 CF Object로 이루어진(based) framework가 존재합니다. xcode 4 이후 ARC가 적용되면서 이 두 object간 값을 bridge하는 __bridge 전처리기가 사용되는데 이 두 object간의 변환 방법입니다. CFTypeRef inTypeRef = (__bridge CFTypeRef)result; OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)baseInformation, &inTypeRef); if (status == errSecSuccess) { result = (__bridge_transfer NSData *)inTypeRef; password = [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding]; } 위 예제는 Security.framework를 이용하여 Keychain에 저장된 값을 가져오는 예제입니다. SecItemCopyMatching(CFDictionaryRef query, CFTypeRef *result) 함수의 두 번째 인자는 포인트를 가지는 CFTypeRef인데 이 값을 NSData로 옮기는 과정에서 위에서 설명한 변환법을 볼 수 있습니다. 즉, __bridge_transfer (NS Object)CG Object를 이용하여 옮긴 것입니다.