1

我正在构建一个带有文本和图像的 UITextView(子类化 NSTextstorage 以显示我的内容)

我有带有图像 URL 的文本内容。所以我的问题是,如果没有缓存,我需要下载所有图像。

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

这就是我的工作方式。

首先,我通过用这个标签替换所有 url 来用图像 url 格式化我的文本:

[IMG]url[/IMG]

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

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

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

@protocol ImageCachingManagerDelegate <NSObject>

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

@end

像这样,我很难使用委托方法获得的图像的 url 在我的 NSTextstorage 属性字符串中搜索匹配的 url,并用下载的图像替换当前的 NSTextattachement 图像。

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

感谢帮助 !

4

1 回答 1

1

我目前正在研究与此非常相似的东西,并认为这可能会有所帮助。该代码非常 alpha,但希望它能让您进入下一步 - 我将逐步完成:

总体周期 1. 使用 Reg Ex 或 XPath 在全文中查找图像标签 - 我个人认为 Hppl 更强大,但如果您的内容结构良好且可靠,那么 regex 可能就可以了。

https://github.com/topfunky/hpple

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

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

  3. 使用您的委托,成功下载图像后,您需要将当前附件替换为新附件。通过替换您已经存储在对象中的范围内的占位符。使用 NSTextAttachment 创建一个占位符属性字符串,然后替换该范围,如下所示。

一些示例代码:

步骤 1 和 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;
}
于 2014-03-01T19:25:11.773 回答