2012-10-05 3 views
8

표준 액티비티 (Print, Mail, FaceBook 등)에 대한 커스텀 액티비티를 구현하려고하는데, 현재는 표준 인쇄 (AirPrint 용)와 직접적인 방법. 내 커스텀 클래스의 메서드 중 아무 것도 호출되지 않기 때문에 분명히 근본적인 것이 빠져있다. 지금은 호출 시퀀스를 파악하고 프레임 워크가 작동하도록하는 NSLog 문만 있습니다. UIActivityController에 사용자 정의 액티비티를 추가 할 때의 문제

다음

내 테스트 사용자 정의 작업 클래스에 대한 코드입니다

// PrintActivity.h 

#import <UIKit/UIKit.h> 

@interface PrintActivity : UIActivity 

@end 

그리고하는 .m

#import "PrintActivity.h" 

@interface PrintActivity() 
@property (nonatomic, strong) UIWebView *dummyWebView; 
@end 

@implementation PrintActivity 

- (NSString *)activityType { 
    NSLog(@"activityType"); 
    return @"MetriScan Print"; 
} 

- (NSString *)activityTitle { 
    NSLog(@"activityTitle"); 
    return @"MetriScan\nPrint"; 
} 

- (UIImage *)activityImage { 
    NSLog(@"activityImage"); 
    UIImage *icon = [UIImage imageNamed:@"metriscan_57_c2a_3.png"]; 
    return icon; 
} 

- (BOOL)canPerformWithActivityItems:(NSArray *)activityItems { 
    NSLog(@"canPerformWithActivityItems"); 
    return YES; 
} 

- (void)prepareWithActivityItems:(NSArray *)activityItems { 
    NSLog(@"prepareWithActivityItems"); 
} 

- (void)performActivity { 
    NSLog(@"Do the actual printing here"); 
// My custom code here 

} 

그리고 이것은 메인 루틴의 호출입니다 :

- (IBAction)printReport:(UIBarButtonItem *)sender { 
    NSLog(@"Print Report"); 

    PrintActivity *metriscanPrint = [[PrintActivity alloc] init]; 

    UIViewPrintFormatter *printFormatter = [self.webView viewPrintFormatter]; 

    NSArray *activityItems = [NSArray arrayWithObjects:printFormatter, nil]; 
    NSArray *appActivities = [NSArray arrayWithObjects:metriscanPrint, nil]; 
    UIActivityViewController *activityController = [[UIActivityViewController alloc] initWithActivityItems:activityItems applicationActivities:appActivities]; 
    //activityController.excludedActivityTypes = [NSArray arrayWithObjects:UIActivityTypePostToFacebook, UIActivityTypePostToTwitter, UIActivityTypePostToWeibo, UIActivityTypeMail, UIActivityTypeMessage, nil]; 
    activityController.completionHandler = ^(NSString *activityType, BOOL completed) { 
     sender.enabled = YES; 
    }; 

    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) { 
     [self presentViewController:activityController animated:YES completion:nil]; 
    } else { 
     sender.enabled = NO; 
     self.printPop = [[UIPopoverController alloc] initWithContentViewController:activityController]; 
     [self.printPop presentPopoverFromBarButtonItem:sender permittedArrowDirections:UIPopoverArrowDirectionDown animated:YES]; 
    } 

내가 말했듯이, 커스텀 클래스의 어떤 메소드도 호출되지 않지만 Mail, Message, Copy 아이콘 시스템은 인쇄 아이콘이 아니라 활동 시트. 나는 단지 시스템 인쇄 아이콘 (그리고 내 자신)을 기대했다.

NSArray * activityItems ... 구문을 주석 처리하고 NSArray * activityItems ...를 주석 처리하면 메일, 메시지, 인쇄 및 복사 아이콘이 표시됩니다. 이 실험에서 저는 자체 포맷터를 작성하여 여러 가지 방법을 혼합하고 있다고 생각하지만 WWDC 2012에서 제안한 것 같았습니까?

'excludeActivityTypes'로 줄의 주석을 제거하면 시스템 인쇄 아이콘 만 표시됩니다.

나는 이것을 이해하는 데 도움이되는 의견을 환영합니다.

그리고 누군가 내가 원하는 것을 수행 할 수있는 예제 코드를 알고 있다면 그것은 훌륭 할 것입니다.

편집 : 코드를 제 작업 코드로 업데이트했습니다.

답변

7

UIActivity에서 내 머리카락을 잡아 당겼다.이 트위크는 정말 더 잘 설명되어야하고 더 많은 기능이 추가되어야한다. 이 시도 :

PrintActivity.h

#import <UIKit/UIKit.h> 
@interface PrintActivity : UIActivity 
@end 

을 PrintActivity.m

#import "PrintActivity.h" 

@implementation PrintActivity 

- (NSString *)activityType 
{ 
    return @"MetriScan.Print"; 
} 

- (NSString *)activityTitle 
{ 
    return @"Print MtriScan"; 
} 

- (UIImage *)activityImage 
{ 
    //***** Note: I recommend using two sizes, as the iPad's UIActivity image size differs from 
    //***** the iPhone's. Also, create @2x sizes for Retina compatible devices. So you will  
    //***** have a total of 4 images. 
    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) 
{ 
    return [UIImage imageNamed:@"test_72.png"]; 
} 

    return [UIImage imageNamed:@"test_57.png"]; 
} 

- (BOOL)canPerformWithActivityItems:(NSArray *)activityItems 
{ 
    NSLog(@"%s", __FUNCTION__); 
    return YES; 
} 

- (void)prepareWithActivityItems:(NSArray *)activityItems 
{ 
    NSLog(@"%s",__FUNCTION__); 
} 

- (UIViewController *)activityViewController 
{ 
    NSLog(@"%s",__FUNCTION__); 
    return nil; 
} 

- (void)performActivity 
{ 
    // This is where your custom print code should go 

} 

@end 

뿐만 아니라이 두 파일을 잊지 마세요 :

PrintProvider.h을

#import <UIKit/UIKit.h> 

@interface PrintProvider : UIActivityItemProvider <UIActivityItemSource> 

@end 

PrintProvi der.m

#import "PrintProvider.h" 

@implementation PrintProvider 

#pragma mark - UIActivityItemSource 

- (id)activityViewController:(UIActivityViewController *)activityViewController itemForActivityType:(NSString *)activityType 
{ 
    NSLog(@"%s",__FUNCTION__); 
    NSLog(@"%@", activityType); 
    return [super activityViewController:activityViewController itemForActivityType:activityType]; 
} 

@end 

이제 우리는 마지막으로 호출 할 수 있습니다 : 당신의 도움에 대한

- (IBAction)printReport:(UIBarButtonItem *)sender { 


CustomProvider *customProvider = 
       [[CustomProvider alloc]init]; 
       NSArray *items = [NSArray arrayWithObjects:customProvider,nil]; 

       CustomActivity *ca = [[CustomActivity alloc]init]; 

       UIActivityViewController *activityVC = 
       [[UIActivityViewController alloc] initWithActivityItems:items 
                applicationActivities:[NSArray arrayWithObject:ca]]; 

       activityVC.excludedActivityTypes = @[UIActivityTypePostToWeibo, 
       UIActivityTypeAssignToContact,UIActivityTypeCopyToPasteboard, 
       UIActivityTypeSaveToCameraRoll,UIActivityTypeMail,UIActivityTypePostToTwitter, 
       UIActivityTypePostToFacebook,UIActivityTypeMessage]; 

       activityVC.completionHandler = ^(NSString *activityType, BOOL completed) 
       { 
        NSLog(@" activityType: %@", activityType); 
        NSLog(@" completed: %i", completed); 
       }; 

        self.popoverController = [[UIPopoverController alloc] initWithContentViewController:activityVC]; 

        CGRect rect = [[UIScreen mainScreen] bounds]; 

        [self.popoverController 
        presentPopoverFromRect:rect inView:self.view 
        permittedArrowDirections:0 
        animated:YES]; 
} 
+2

troop231 질문에 답변 해 주셔서 감사합니다. 내가 당신과 거의 똑같이 문제를 해결 했음이 밝혀졌습니다. 내 원래의 혼동은 각각 activityItems와 applicationActivities에 넣어야 할 것이었다. 완성을 위해 원래 질문에서 코드를 업데이트했습니다. – bjarne

+0

당신은 환영합니다 :) 나는 UIActivity의 잠재력이 크다고 생각합니다. – klcjr89

+0

감사합니다. 실제로 작동합니다. 그러나이 접근 방식이 시스템 서비스를 무시하지 말라는 경고와 모순되지 않습니까? 사용자에게 맞춤 서비스를 제공하려는 경우에만 UIActivity의 하위 클래스를 만들어야합니다. 이 시스템은 이미 많은 표준 서비스에 대한 지원을 제공하고 UIActivityViewController 객체를 통해 사용할 수 있도록합니다. 예를 들어, 표준 액티비티 뷰 컨트롤러는 데이터 이메일 전송, 사용자의 소셜 미디어 계정 중 하나에 항목 게시 및 기타 여러 옵션을 지원합니다. 당신은 기본 제공되는 유형에 대한 맞춤 서비스를 제공 할 필요가 없습니다. ' – Anastasia

-1

감사들!이미지의 알파 채널이 사용자에게 제공되는 최종 이미지를 생성하는 마스크로 사용된다

: 그리고, 활동 이미지, 우리가 애플 문서하여 다음과 같은 이미지를 제공해야 할 것 같다. 이미지의 모든 색상 데이터는 무시됩니다. 불투명 한 픽셀에는 그라디언트가 적용되고 이 그라디언트가 표준 배경 위에 배치됩니다. 따라서 완전히 불투명 한 이미지 은 그라데이션 채워진 사각형을 산출합니다. iPhone 및 iPod touch의 경우 이미지는 43x43 포인트 () 여야합니다. (Retina 디스플레이가있는 장치의 경우 86x86 픽셀에 해당합니다.) iPad의 경우 이미지는 55x55 포인트 ( ) Retina 디스플레이가 장착 된 iPads의 경우 110x110 픽셀에 해당합니다.)

3

@ troop231 - 훌륭한 답변이며 매우 유용합니다.

내가 추가 할 수있는 유일한 점은 작업 완료를 알리는 것입니다. 그렇지 않으면 완료 루틴이 호출되지 않고 팝 오버가 해제되지 않습니다. 다음과 같이 입력하십시오 :

- (void)performActivity { 
    NSLog(@"Do the actual activity here"); 
    // My custom code here 

    [self activityDidFinish:YES]; // indicate completion here!! 
} 
+0

이것을 추가해 주셔서 감사합니다. 나는 적절한 방법에 대해 궁금해하고있다. 그러면 activityViewController.completionHandler가 실행되고 avc를 해제해야합니다. – VaporwareWolf

+0

방금 ​​생각을했지만 테스트 할 시간이 없었습니다. 반환하기 전에'[super performActivity]'를 호출했을 경우 (위에서 보았 듯이) 완료 핸들러를 명시 적으로 호출 할 필요가 없다는 것은 사실 일 수 있습니다. 수퍼 클래스 메서드가 완료 핸들러를 호출 할 수 있습니까? 시도해 볼 시간이 있으면 알려주십시오. – jbbenni