2012-09-26 19 views
8

¿Cómo copiar un NSAttributedString en la mesa de trabajo, para permitir al usuario para pegar o para pegar mediante programación (con - (void)paste:(id)sender, del protocolo de UIResponderStandardEditActions).Copia NSAttributedString en UIPasteBoard

me trataron:

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

pero este accidente con:

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

que es de esperar, porque NSAttributedString no es un valor de lista de propiedades.

Si el usuario pega el contenido del portapapeles en mi aplicación, me gustaría mantener todos los estándares y atributos personalizados de la cadena atribuida.

+0

hecho algunas ideas en UIPasteBoard y NSAttributedString, podría ser valiosa: http://stackoverflow.com/a/38211885/1054573 –

Respuesta

9

He encontrado que cuando (como usuario de la aplicación) Copia de texto enriquecido de un UITextView en la mesa de trabajo, la mesa de trabajo contiene dos tipos:

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

Basado en esto, he creado una categoría conveniente en UIPasteboard.
(con un uso intensivo del código de this answer).

Funciona, pero:
La conversión al formato html significa que perderé atributos personalizados. Cualquier solución limpia será aceptada con mucho gusto.

Archivo UIPasteboard + AttributedString.h:

@interface UIPasteboard (AttributedString) 

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

@end 

Archivo 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 

colocador Sólo implementado. Si desea escribir el getter, y/o ponerlo en GitHub, sea mi invitado :)

+0

+1, pero este es el colocador, no el captador;) –

+0

@ H2CO3 Gracias :) Actualizado el e respuesta. – Guillaume

+0

@ThomasTempelmann gracias, editado! – Guillaume

-1

El administrador de pasteboard en OSX puede convertir automáticamente entre una gran cantidad de tipos textuales y de imágenes.

Para los tipos de texto enriquecido, suele colocar RTF en el marco. Puede crear una representación RTF a partir de una cadena atribuida, y viceversa. Consulte "Referencia de NSAttributedString Application Kit Additions".

Si también tiene imágenes incluidas, utilice el RTFd en lugar del sabor RTF.

No conozco los tipos MIME para estos (estoy acostumbrado a la API de Carbon Pasteboard, no al Cocoa), pero puede realizar conversiones entre UTI, Pboard y tipos MIME utilizando la API UTType.

UTI para RTF es "public.rtf", para RTFd es "com.apple.flat-rtfd".

+0

Esta es una pregunta de iOS. – Guillaume

+0

Vaya, esa pequeña etiqueta "ios" es fácil pasar por alto. Y iOS no parece tener una conversión RTF integrada. Bummer. –

+0

De acuerdo. Por lo general, cuando la etiqueta es la única forma de verlo, lo explico en la pregunta. No lo hice porque pensé que UIPasteboard sería suficiente. Perdón por no ser más claro. – Guillaume

8

@ El enfoque de Guillaume al usar HTML no funciona para mí (al menos en iOS 7.1 beta 5).

La solución más limpia es insertar NSAttributedStrings como RTF (más de repliegue de texto claro) en la placa de 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

Es bastante simple:

#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]; 
Cuestiones relacionadas