2012-10-05 9 views
8

Sto cercando di implementare un'attività personalizzata per le attività standard (Stampa, Mail, FaceBook, ecc.) Ma per ora voglio solo la Stampa standard (per AirPrint) e la mia stampa personalizzata da un metodo diretto. Ovviamente mi manca qualcosa di fondamentale in quanto nessuno dei metodi nella mia classe personalizzata viene mai chiamato. Per ora ho solo alcune istruzioni NSLog per capire la sequenza di chiamata e per far funzionare il framework.Problemi nell'aggiungere attività personalizzate a UIActivityController

Quello che segue è il mio codice di prova per la classe di attività personalizzata:

// PrintActivity.h 

#import <UIKit/UIKit.h> 

@interface PrintActivity : UIActivity 

@end 

E il .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 

} 

E questo è l'invocazione nella routine principale:

- (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]; 
    } 

Come ho detto, nessuno dei metodi nella classe personalizzata viene chiamato, ma le icone di sistema Mail, Message e Copy mostrano nel foglio di attività e non l'icona Stampa. Mi aspettavo solo l'icona Stampa di sistema (e la mia).

Se annullo il primo blocco di istruzioni (e commenta l'oggetto NSArray * activityItems ...........) più in basso, le icone di posta, messaggio, stampa e copia del systme. In questo esperimento penso di mescolare diversi metodi creando il mio formattatore, ma quello è sembrato essere il suggerimento al WWDC 2012?

Se si annulla la riga con "excludeActivityTypes", viene visualizzata solo l'icona Stampa di sistema.

Gradirei qualsiasi input per aiutarmi a capirlo.

E se qualcuno sa di codice di esempio per fare quello che voglio, sarebbe fantastico.

Modifica: Codice aggiornato al mio codice di lavoro.

risposta

7

Mi stavo strappando i capelli per UIActivity e questo passato, ha davvero bisogno di essere spiegato meglio da Apple e ha aggiunto più funzionalità; Prova questo:

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 

Non dimenticate di fare questi due file così:

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 

Ora possiamo finalmente chiamare:

- (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 grazie per aver risposto alla domanda. Risulta che ho risolto il problema in modo quasi identico a te. La mia confusione originale era cosa mettere in attività, rispettivamente, Item e ApplicationActivities. Per completezza ho aggiornato il codice nella mia domanda originale. – bjarne

+0

Prego :) Penso che il potenziale di UIActivity sia enorme. – klcjr89

+0

Grazie, funziona davvero. Ma questo approccio non contraddice l'avvertimento di Apple riguardo al non sovrascrivere i servizi di sistema? 'Dovresti sottoclasse UIActivity solo se desideri fornire servizi personalizzati all'utente. Il sistema fornisce già il supporto per molti servizi standard e li rende disponibili tramite l'oggetto UIActivityViewController. Ad esempio, il controller di visualizzazione attività standard supporta i dati via e-mail, la pubblicazione di elementi in uno degli account di social media dell'utente e diverse altre opzioni. Non è necessario fornire servizi personalizzati per nessuno dei tipi predefiniti. – Anastasia

-1

grazie per il vostro aiuto, ragazzi!E, per l'immagine di attività, sembra che abbiamo per fornire immagine seguendo questo dai documenti di Apple:

Il canale alfa dell'immagine viene usato come maschera per generare l' immagine finale che viene presentato all'utente. Qualsiasi dato di colore nell'immagine viene ignorato. Ai pixel opachi viene applicata una sfumatura e questa sfumatura viene quindi posizionata su uno sfondo standard. Pertanto, un'immagine completamente opaca di produce un rettangolo pieno di gradiente. Per iPhone e iPod touch, le immagini non devono essere maggiori di 43 per 43 punti (che equivale a 86 per 86 pixel per i dispositivi con display Retina.) Per iPad, le immagini non devono superare i 55 x 55 punti (che equivale a 110 per 110 pixel per iPad con display Retina.)

3

@ troop231 - ottima risposta e molto utile.

L'unica cosa che aggiungo è di essere sicuri di segnalare il completamento dell'operazione o la routine di completamento non verrà chiamata e il popover non verrà eliminato. Qualcosa del tipo:

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

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

Grazie per aver aggiunto questo. Mi sono chiesto il modo giusto. Ciò causerà l'attivazione di activityViewController.completionHandler, in cui è necessario respingere avc. – VaporwareWolf

+0

Ho solo pensato, ma non ho avuto il tempo di testarlo. Potrebbe essere vero che non è necessario chiamare esplicitamente il gestore di completamento (come ho mostrato sopra) se uno (invece) ha chiamato '[super performActivity]' prima di tornare. È possibile che il metodo di super classe invochi il gestore di completamento? Fammi sapere se hai tempo per provarlo. – jbbenni

Problemi correlati