替换NSMutableattributedString上的NSTextattachement图像

时间:2014-02-20 14:15:21

标签: download uitextview textkit nstextstorage nstextattachment

我正在使用文本和图像构建UITextView(子类化NSTextstorage以显示我的内容)

我正在使用图片网址的文字内容。 所以我的问题是我需要下载所有图像,如果它们没有被缓存。

所以我想首先插入占位符图像,下载图像,然后用下载的图像替换占位符图像。

以下是我的工作方式。

首先,我用图片网址格式化我的文字,用这个标签替换所有网址:

[IMG]url[/IMG]

然后我使用正则表达式来获取所有这些标签。

我正在测试是否有缓存图像。如果没有,我提取所有网址,下载并缓存它们。

我已经创建了一个NSObject类ImageCachingManager,并声明了在下载图像时调用的委托方法:

@protocol ImageCachingManagerDelegate <NSObject>

- (void)managerDidCacheImage:(UIImage *)image forUrl:(NSString *)url;

@end

像这样,我很难说我可以使用委托方法获取的图像的url来搜索我的NSTextstorage attributionString中的匹配网址,并用下载的网格替换当前的NSTextattachement图像。

但我不知道该怎么做......

感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

我正在研究与此非常类似的事情,并认为这可能会有所帮助。代码是非常alpha的,但希望它能让你进入下一步 - 我将逐步完成:

整体周期 1.使用Reg Ex或XPath在全文中找到图像标签 - 我个人认为Hppl更强大,但如果您的内容结构合理且可靠,则正则表达式可能很好。

https://github.com/topfunky/hpple

  1. 将此匹配的空间减少为1个字符并存储该范围 - textAttachment在textview中仅占用1个字符的空间,因此最好将其减少为1,否则当您替换第一个字符匹配时在第一个textattachment范围内,下一个范围标记变得过时,这将导致问题。这取决于你在init期间需要多少处理这个文本输入,这是一个重要的步骤,我必须对文本进行大量处理,并且在解析过程中范围会发生变化,所以我创建了一个我知道的特殊字符数组永远不会进入输入并将这些单个字符推入保留空间,同时我将这个特殊字符和图像的src存储在一个非常简单的NSObject子类的数组中,该子类存储了SpecialChar,ImgSrc plus NSRange的空间,但我基本上再次在流程中找到特殊字符,因为它已经从这一点开始移动,然后在处理结束时设置nsrange - 这在你的情况下可能没有必要,但原则是相同;您需要一个带有NsRange(将成为文本附件)和imgSource的自定义对象。

  2. 循环遍历此数组,以将占位符imageAttachments添加到您的属性字符串。您可以通过添加透明图像或“加载”图像来完成此操作。您还可以在此期间检查缓存中是否有现有图像,如果缓存中存在占位符,则可以跳过它。

  3. 使用您的代理,成功下载图像后,您需要将新附件替换为新附件。通过替换已存储在对象中的范围中的占位符。使用NSTextAttachment创建占位符attributionString,然后替换该范围,如下所示。

  4. 一些示例代码:

    步骤1&amp; 2:

            specialCharsArray = [[NSArray alloc]initWithObjects:@"Û", @"±", @"¥", @"å", @"æ", @"Æ", @"Ç", @"Ø", @"õ", nil];
    

    //使用Hppl

    NSString *allImagesXpathQueryString = @"//img/@src";
    NSArray *imageArray = [bodyTextParser searchWithXPathQuery:allImagesXpathQueryString];
        //
    
        imageRanges = [[NSMutableArray alloc] init];
    
        if([imageArray count]){
            for (TFHppleElement *element in imageArray) {
                int i = 0;
                NSString *imgSource = [[[element children] objectAtIndex:0] content];
    
                NSString *replacementString = [specialCharsArray objectAtIndex:i];
                UIImage *srcUIImage = [UIImage imageNamed:imgSource];
    
                [srcUIImage setAccessibilityIdentifier:imgSource]; //only needed if you need to reference the image filename later as it's lost in a UIImage if stored directly
    

    // imagePlacement是NSObject子类,用于存储范围,替换和图像,如上所述

        imagePlacement *foundImage = [[imagePlacement alloc]init] ;
    
    
                [foundImage initWithSrc:srcUIImage replacement:replacementString];
                [imageRanges addObject:foundImage];
                i++;
            }
    

    第3步:

      -(void)insertImages{
    
        if ([imageRanges count]) {
            [self setScrollEnabled:NO]; //seems buggy with scrolling on
            int i = 0; //used to track the array placement for tag
    
            for(imagePlacement *myImagePlacement in imageRanges){
    
                // creates a text attachment with an image
    
                NSMutableAttributedString *placeholderAttString = [[NSMutableAttributedString alloc]initWithAttributedString:self.attributedText];
    
                NSTextAttachment *attachment = [[NSTextAttachment alloc] init];
    
                //scales image down to ration of width of view - you probably don't need this
                CGSize scaleToView = imagePlacement.imgSrc.size;
                scaleToView.width = self.frame.size.width;
                scaleToView.height = (self.frame.size.width/imagePlacement.imgSrc.size.width)*imagePlacement.imgSrc.size.height;
    
    
                attachment.image = [self imageWithColor:[UIColor clearColor] andSize:scaleToView];
                NSMutableAttributedString *imageAttrString = [[NSAttributedString attributedStringWithAttachment:attachment] mutableCopy];
    
                [self setAttributedText:placeholderAttString];
    
                i++;
    
            }
        }
        [self setScrollEnabled:YES];
    
    }
    
    
    - (UIImage *)imageWithColor:(UIColor *)color andSize:(CGSize) size {
        CGRect rect = CGRectMake(0.0f, 0.0f, size.width, size.height);
        UIGraphicsBeginImageContext(rect.size);
        CGContextRef context = UIGraphicsGetCurrentContext();
    
        CGContextSetFillColorWithColor(context, [color CGColor]);
        CGContextFillRect(context, rect);
    
        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
    
        return image;
    }