2012-09-26 18 views
8

Come si copia un NSAttributedString nel tavolo di montaggio, per consentire all'utente di pasta, o per incollare di programmazione (con - (void)paste:(id)sender, dal protocollo UIResponderStandardEditActions).Copia NSAttributedString in UIPasteBoard

ho provato:

UIPasteboard *pasteBoard = [UIPasteboard generalPasteboard]; 
[pasteBoard setValue:attributedString forPasteboardType:(NSString *)kUTTypeRTF]; 

ma questo incidente con:

-[UIPasteboard setValue:forPasteboardType:]: value is not a valid property list type' 

che è da aspettarselo, perché NSAttributedString non è un valore elenco di proprietà.

Se l'utente incolla il contenuto del pannello di montaggio nella mia app, vorrei conservare tutti gli standard e gli attributi personalizzati della stringa attribuita.

+0

fatto alcuni approfondimenti in UIPasteBoard e NSAttributedString, potrebbe essere prezioso: http://stackoverflow.com/a/38211885/1054573 –

risposta

9

Ho scoperto che quando (come utente dell'applicazione) copiare il testo ricco da un UITextView nel tavolo di montaggio, il tavolo di montaggio contiene due tipi:

"public.text", 
"Apple Web Archive pasteboard type 

Sulla base di questo, ho creato una categoria di comodo su UIPasteboard.
(con uso intensivo del codice da this answer).

Funziona, ma:
La conversione in formato html significa che perderò attributi personalizzati. Qualsiasi soluzione pulita sarà accettata volentieri.

File UIPasteboard + AttributedString.h:

@interface UIPasteboard (AttributedString) 

- (void) setAttributedString:(NSAttributedString *)attributedString; 

@end 

File UIPasteboard + AttributedString.m:

#import <MobileCoreServices/UTCoreTypes.h> 

#import "UIPasteboard+AttributedString.h" 

@implementation UIPasteboard (AttributedString) 

- (void) setAttributedString:(NSAttributedString *)attributedString { 
    NSString *htmlString = [attributedString htmlString]; // This uses DTCoreText category NSAttributedString+HTML - https://github.com/Cocoanetics/DTCoreText 
    NSDictionary *resourceDictionary = @{ @"WebResourceData" : [htmlString dataUsingEncoding:NSUTF8StringEncoding], 
    @"WebResourceFrameName": @"", 
    @"WebResourceMIMEType" : @"text/html", 
    @"WebResourceTextEncodingName" : @"UTF-8", 
    @"WebResourceURL" : @"about:blank" }; 



    NSDictionary *htmlItem = @{ (NSString *)kUTTypeText : [attributedString string], 
     @"Apple Web Archive pasteboard type" : @{ @"WebMainResource" : resourceDictionary } }; 

    [self setItems:@[ htmlItem ]]; 
} 


@end 

Solo implementato setter. Se vuoi scrivere il getter e/o metterlo su GitHub, sii mio ospite :)

+0

+1, ma questo è il setter, non il getter;) –

+0

@ H2CO3 Grazie :) Aggiornato e risposta. – Guillaume

+0

@ThomasTempelmann grazie, modificato! – Guillaume

-1

Il gestore del pannello di montaggio in OSX può convertire automaticamente tra molti tipi di testo e di immagine.

Per i tipi di testo avanzato, in genere si inserisce RTF nel tavolo di montaggio. È possibile creare la rappresentazione RTF da una stringa attribuita e viceversa. Vedere "Riferimento alle aggiunte del kit di applicazioni NSAttributedString".

Se si dispone anche di immagini, quindi utilizzare RTFd invece di sapore RTF.

Non conosco i tipi MIME per questi (sono abituato all'API Carbon Pasteboard, non a quello Cocoa), ma è possibile convertire tra UTI, Pboard e tipi MIME utilizzando l'API UTType.

UTI per RTF è "public.rtf", per RTFd è "com.apple.flat-rtfd".

+0

Questa è una domanda iOS. – Guillaume

+0

Oops: quel piccolo tag "ios" è facile da trascurare. E iOS non sembra avere una conversione RTF integrata. Bummer. –

+0

concordato. Di solito, quando il tag è l'unico modo per vederlo, lo esplicito nella domanda. Non l'ho fatto perché pensavo che UIPasteboard sarebbe stato abbastanza. Scusa per non essere più chiaro. – Guillaume

8

@ L'approccio di Guillaume tramite HTML non funziona per me (almeno in iOS 7.1 beta 5).

La soluzione più pulita è quella di inserire NSAttributedStrings come RTF (più fallback testo in chiaro) nella scheda di pasta:

- (void)setAttributedString:(NSAttributedString *)attributedString { 
    NSData *rtf = [attributedString dataFromRange:NSMakeRange(0, attributedString.length) 
           documentAttributes:@{NSDocumentTypeDocumentAttribute: NSRTFTextDocumentType} 
              error:nil]; 
    self.items = @[@{(id)kUTTypeRTF: [[NSString alloc] initWithData:rtf encoding:NSUTF8StringEncoding], 
        (id)kUTTypeUTF8PlainText: attributedString.string}]; 
} 

Swift 2.3

public extension UIPasteboard { 
    public func set(attributedString: NSAttributedString?) { 

    guard let attributedString = attributedString else { 
     return 
    } 

    do { 
     let rtf = try attributedString.dataFromRange(NSMakeRange(0, attributedString.length), documentAttributes: [NSDocumentTypeDocumentAttribute: NSRTFTextDocumentType]) 
     items = [[kUTTypeRTF as String: NSString(data: rtf, encoding: NSUTF8StringEncoding)!, kUTTypeUTF8PlainText as String: attributedString.string]] 

    } catch { 

    } 
    } 
} 

Swift 3

import MobileCoreServices 
public extension UIPasteboard { 
    public func set(attributedString: NSAttributedString?) { 

    guard let attributedString = attributedString else { 
     return 
    } 

    do { 
     let rtf = try attributedString.data(from: NSMakeRange(0, attributedString.length), documentAttributes: [NSDocumentTypeDocumentAttribute: NSRTFTextDocumentType]) 
     items = [[kUTTypeRTF as String: NSString(data: rtf, encoding: String.Encoding.utf8.rawValue)!, kUTTypeUTF8PlainText as String: attributedString.string]] 

    } catch { 

    } 
    } 
} 
0

E 'molto semplice:

#import <MobileCoreServices/UTCoreTypes.h> 

    NSMutableDictionary *item = [[NSMutableDictionary alloc] init]; 

    NSData *rtf = [attributedString dataFromRange:NSMakeRange(0, attributedString.length) 
          documentAttributes:@{NSDocumentTypeDocumentAttribute: NSRTFDTextDocumentType} 
              error:nil]; 

    if (rtf) { 
    [item setObject:rtf forKey:(id)kUTTypeFlatRTFD]; 
    } 

    [item setObject:attributedString.string forKey:(id)kUTTypeUTF8PlainText]; 

    UIPasteboard *pasteboard = [UIPasteboard generalPasteboard]; 
    pasteboard.items = @[item]; 
Problemi correlati