달력

06

« 2017/06 »

  •  
  •  
  •  
  •  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  •  

iOS9의 새로운 피쳐들 중에 비교적 쉽게 만들어 볼 수 있고.. 또 지금 하고 있는 프로젝트에도 적용해볼만한 기능이라 한번 끄적여봤다..

우선 결론부터 보자면 이렇다..





검색 화면에서 ㅇ 이라고 한글자 눌렀더니 내 Path 피드에 있던 데이터들 중에 ㅇ 들어간 녀석들을 찾아준다.. 검색된 것을 누르면 해당 모멘트(Path에서는 모멘트라고 부름 ㅎ)의 상세 화면으로 이동하는 것은 물론이다..


여기서 검색을 한다고 Path 서버를 뒤져서 데이터를 긁어오는 것은 당연히 아니고 앱에서 어떤 방법으로 어떤 데이터들을 가져오게할 것인지 코딩을 해주면 된다.. 처음 하는 거라서 약간 삽질을 하느라 시간이 좀 걸렸는데 한번 해보면 코드 자체는 간단하고 어떻게 어떤 데이터들을 검색하게 할 것인지에 대한 고민이 더 많을 것 같다..


일단 검색할 데이터를 만들어보자.. 우선


#import <CoreSpotlight/CoreSpotlight.h>
#import <MobileCoreServices/MobileCoreServices.h>

요거 두개가 필요하다..



        
    NSMutableArray *aItems = [NSMutableArray arrayWithCapacity:[[m_resultsController fetchedObjects] count]];
    
    for (PTPost *post in [m_resultsController fetchedObjects])
    {
        PTPostType postType = [post postType];
        if (postType == PTPostTypePhoto || postType == PTPostTypeVideo)
        {
            CSSearchableItemAttributeSet *attributeSet = [[CSSearchableItemAttributeSet alloc] initWithItemContentType:(NSString *)kUTTypeImage];
            if (post.title == nil)
                attributeSet.title = @"Path feed";
            else
                attributeSet.title = post.title;

            NSArray *aComments = [post sortedComments];
            if (aComments != nil && aComments.count > 0)
            {
                PTComment *comment = [post sortedComments][0];
                attributeSet.contentDescription = [comment text];
            }
            else
                continue;
            
            attributeSet.thumbnailData = [NSData dataWithContentsOfFile:post.photoFilePath];
            
            CSSearchableItem *item = [[CSSearchableItem alloc] initWithUniqueIdentifier:post.id domainIdentifier:itemDomain attributeSet:attributeSet];
            [aItems addObject:item];

        }
    }

    if (aItems.count > 0)
    {
        [[CSSearchableIndex defaultSearchableIndex] indexSearchableItems:aItems completionHandler: ^(NSError * __nullable error) {
            
            if(error != nil)
            {
                NSLog(@"indexSearchableItems error : %@", error);
            }
        }];
    }
    else
        NSLog(@"aItems count is 0");



피드 데이터가 업데이트가 되면 요 메쏘드를 한번 호출해주면 된다..

하나의 모멘트에 대해서 CSSearchableItemAttributeSet 객체와 CSSearchableItem 객체 하나씩 필요한것 같은데.. 왜 이걸 굳이 두개로 나누었을까 싶기도 한데.. 여튼.. 각 모멘트 데이터(위 코드에서는 PTPost 객체가 되시겠다)에서 제목을 가지고 오고(Path의 모멘트는 title을 쓰는 경우가 없어서 그냥 Path feed라고 나온다;;) contentDescription에 검색이 될 텍스트를 넣어주면 된다.. 그리고 검색 결과에 사용될 이미지를 thumbnailData에 넣어주면 되는데 지금 생각을 해보니 file URL을 thumbnailURL에 넣어줘도 될것 같은 필이 느껴지네.. -_-;;


이렇게 CSSearchableItemAttributeSet 객체에 셋팅을 해주고 이걸 기준으로 CSSearchableItem 객체를 만들어서 어레이를 만들고 그걸 넣어주면 끝.. 앱 설치하고 데이터 읽어와서 넣어준 후에 iOS 검색 화면을 들어가서 검색어를 입력하면 첨부한 화면처럼 검색이 된다.. 그런데 이게 시뮬레이터라 검색 결과가 상단에 나오는데 실제 폰에 올려서 확인을 해보니 SMS 내용, 메모 내용, 메일, 주소록 등등 지들이 만든게 상단에 나오고 개별 앱의 결과는 저 밑에 나오더만.. -_-;; 그래서 이걸 사람들이 많이 쓸까 살짝 걱정이 좀 되더만;;


참.. CSSearchableItem 객체를 만들 때, 넣어주는 post.id 요게 실제 검색 결과에서 선택된 항목으로부터 앱이 건네 받게 되는 스트링이고 이걸 받아서 해당 모멘트 데이터를 찾아와서 그 모멘트의 상세 페이지로 이동을 시키게 된다.. 그리고 itemDomain이라고 되어있는건 앱을 구분하는 유니크한 스트링인데 com.회사이름.어쩌고 뭐 이렇게 써주면 될듯 싶다.. 



자.. 그러면 이제 데이터는 검색 창쪽으로 보내줬으니 그쪽에서 해당 모멘트의 id를 받아와서 상세페이지로 이동하는 방법을 보자.. 요건 참 쉽다.. app delegate에다가 요거 하나 추가해주면 된다..



        
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void(^)(NSArray * __nullable restorableObjects))restorationHandler
{
    NSString *identifier = userActivity.userInfo[CSSearchableItemActivityIdentifier];
    NSString *strMomentID = identifier;

    PTPost* post = [PTPost fetchWithID:strMomentID];
    
    if (strMomentID.length == 0 || post == nil)
        return NO;

    // go to detail page
    
    return YES;
}


뭐.. 코드만 봐도 이해가 될 듯..


근데 이거 앱들이 서로 자기들꺼 밀어 넣기 시작하면 왠지 난장판이 될 것도 같아서 좀 걱정은 된다.. -_-;; 속도 문제도 있을 것이고.. 우리 앱이 저 아래로 밀리면 곤란한데.. 왠지 애플이니까 자주 선택된 앱들을 위쪽에 노출을 해줄 수도 있을 것 같은데.. 아직 이 기능을 제공하는 앱이 애플앱들 밖에 없다보니 어떻게 될지 잘 모르겠네;;


참.. 하나 빠진게있구나.. CSSearchableItemAttributeSet 요거 멤버 중에 keywords라는 것이 있는데.. 예를 들어 @[@"path", @"패스"] 요렇게 값을 넣어줬다면 iOS 검색 화면에서 'path 울랄라' 혹은 '패스 울랄라' 요렇게 입력하면 path(혹은 패스)라는 키워드를 넣은 앱들에서만 검색을 해주는데.. 이렇게 정성들여 검색할 유저가 과연 있을까 싶어서 예제에는 keywords는 사용하지 않았다.. (나라도 안쓰겠다 -_-;; 그리고 다른 앱에서 path라고 키워드 입력하면 그 앱도 검색할텐데.. 뭐야 이게.. -_-;; 아님 다른 뭔가가 더 있는건가.. -_-a)


신고
Posted by 도노보노

테이블 뷰에 editing을 yes로 주고 드래그 앤 드랍으로 셀 위치를 변경해줘야 할 필요가 생겼다.. 여기까지는 흔히 있는 일인데.. 문제는 첫 셀은 움직여서는 안된다는 조건..


        
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.row == 0)
        return NO;
    
    return YES;
}


요걸 사용해서 우선 첫 셀 오른쪽에는 드래그 앤 드롭용 가로줄3개가 안나오도록 했고 움직일 수 없도록 조치를 했는데.. 다른 셀을 끌어와서 첫 셀 자리로 들고오면 첫 셀이 밀리는 문제가 발생!!


이런 경우는 처음이라 어떻게 해야 하나 싶었는데 옆자리에 있던 고마우신 분이 찾아주심.. ㅎㅎ


  
- (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath
{
    if (proposedDestinationIndexPath.row == 0)
        return sourceIndexPath;
    
    return proposedDestinationIndexPath;
}


움직이지 않게 하고 싶은 셀의 indexPath를 체크해서 그런 경우에는 sourceIndexPath를 리턴해주면 해당 셀은 드래그 앤 드롭에서 제외돼서 꼼짝도 안하게 된다.. 그 외의 경우는 proposedDestinationIndexPath를 리턴해주면 끝!


참 쉽죠..


이렇게 오늘도 하나 배워가는 구나.. ㅎㅎ

퇴근해야지.. ㄷㄷㄷ

신고
Posted by 도노보노


티스토리 툴바