-(void)drawRect:(CGRect)rect { // NSLog(@"%@",rect); CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetTextMatrix(context, CGAffineTransformIdentity); CGContextConcatCTM(context, CGAffineTransformMake(1, 0, 0, -1, 0, self.bounds.size.height)); CGMutablePathRef path = CGPathCreateMutable(); CGPathAddRect(path, NULL, self.bounds); //文本 NSString * str = @"小戎俴收,五楘梁辀。游环胁驱,阴靷鋈续。文茵畅毂,驾我骐馵。言念君子,温其如玉。在其板屋,乱我心曲"; NSMutableAttributedString * attr = [[NSMutableAttributedString alloc]initWithString:str]; [attr addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:30] range:NSMakeRange(0, 6)]; // 两种方式皆可 [attr addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:NSMakeRange(3, 10)]; [attr addAttribute:(id)kCTForegroundColorAttributeName value:[UIColor greenColor] range:NSMakeRange(0, 2)]; #pragma mark -- 本地图片设置部分 NSString * imageHolder = @"xiaopang.jpg"; //代理结构体初始化 CTRunDelegateCallbacks imageCallbacks; imageCallbacks.version = kCTRunDelegateVersion1; imageCallbacks.dealloc = myRunDelegateDeallocCallback; imageCallbacks.getAscent = myRunDelegateGetAscentCallback; imageCallbacks.getDescent =myRunDelegateGetDscentCallback; imageCallbacks.getWidth = myRunDelegateGetWidthCallback; //构建CTRun的代理 CTRunDelegateRef delegate = CTRunDelegateCreate(&imageCallbacks, (__bridge void * _Nullable)(imageHolder)); //构建占位属性文本 NSMutableAttributedString * imgeAttr = [[NSMutableAttributedString alloc]initWithString:@" "]; //设置占位属性文本的代理为delegate [imgeAttr addAttribute:kCTRunDelegateAttributeName value:(__bridge id)delegate range:NSMakeRange(0,1)]; CFRelease(delegate); //这个是作为id选择器的 [imgeAttr addAttribute:@"imageName" value:imageHolder range:NSMakeRange(0, 1)]; //将占位属性文本插入到文本中去。 [attr insertAttributedString:imgeAttr atIndex:5]; // 图片信息字典 NSString *picURL =@"http://img3.imgtn.bdimg.com/it/u=1811953530,4106413237&fm=206&gp=0.jpg"; NSDictionary *imgInfoDic = @{@"width":@192,@"height":@277}; // 宽高跟具体图片有关 // 设置CTRun的代理 CTRunDelegateRef mydelegate = CTRunDelegateCreate(&imageCallbacks, (__bridge void *)imgInfoDic); // 使用0xFFFC作为空白的占位符 unichar objectReplacementChar = 0xFFFC; NSString *content = [NSString stringWithCharacters:&objectReplacementChar length:1]; NSMutableAttributedString *space = [[NSMutableAttributedString alloc] initWithString:content]; [space addAttribute:kCTRunDelegateAttributeName value:(__bridge id _Nonnull)(mydelegate) range:NSMakeRange(0, 1)]; [space addAttribute:@"imageName" value:picURL range:NSMakeRange(0, 1)]; [space addAttribute:@"dict" value:imgInfoDic range:NSMakeRange(0, 1)]; CFRelease(mydelegate); // 将创建的空白AttributedString插入进当前的attrString中,位置可以随便指定,不能越界 [attr insertAttributedString:space atIndex:10]; CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attr); _frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, [attr length]), path, NULL); CTFrameDraw(_frame, context); //图片绘制逻辑 [self drawAttachments]; // CFRelease(_frame); CFRelease(framesetter); CFRelease(path); }代理方法:
void myRunDelegateDeallocCallback(void *refCon) { NSLog(@"%@",@"Rundelegate dealloc"); } CGFloat myRunDelegateGetDscentCallback(void *refCon) { NSLog(@"%@",@"get descent"); return 0; } #pragma mark -- 获取宽度 CGFloat myRunDelegateGetWidthCallback(void *refCon) { NSLog(@"%@",@"get width"); // return 10; NSString *imageName = (__bridge NSString *)refCon; if ([imageName isKindOfClass:[NSString class]]) { // 本地图片 return [UIImage imageNamed:imageName].size.width; } // 对应网络图片 return [[(__bridge NSDictionary *)refCon objectForKey:@"width"] floatValue]; } #pragma mark -- 获取高度 CGFloat myRunDelegateGetAscentCallback(void *refCon) { NSLog(@"%@",@"get ascent"); // return 30; NSString *imageName = (__bridge NSString *)refCon; if ([imageName isKindOfClass:[NSString class]]) { // 对应本地图片 return [UIImage imageNamed:imageName].size.height; } // 对应网络图片 return [[(__bridge NSDictionary *)refCon objectForKey:@"height"] floatValue]; }
-(void)drawAttachments { CGContextRef context = UIGraphicsGetCurrentContext(); CFArrayRef lines = CTFrameGetLines(_frame); CFIndex lineCount = CFArrayGetCount(lines); CGPoint lineOrigins[lineCount]; CTFrameGetLineOrigins(_frame, CFRangeMake(0, 0), lineOrigins); for (CFIndex i = 0; i < lineCount; i ++) { CTLineRef line = CFArrayGetValueAtIndex(lines, i); CGPoint origin = lineOrigins[i]; CGFloat lineAscent; CGFloat lineDescent; CTLineGetTypographicBounds(line, &lineAscent, &lineDescent, NULL); CFArrayRef runs = CTLineGetGlyphRuns(line); for (int j = 0; j < CFArrayGetCount(runs); j ++) { //遍历run CGFloat runAscent; CGFloat runDescent; CTRunRef curRun = CFArrayGetValueAtIndex(runs, j); NSDictionary * attrs = (NSDictionary *)CTRunGetAttributes(curRun); CGRect runRect; runRect.size.width = CTRunGetTypographicBounds(curRun, CFRangeMake(0, 0), &lineAscent, &lineDescent, NULL); runRect = CGRectMake(origin.x + CTLineGetOffsetForStringIndex(line, CTRunGetStringRange(curRun).location, NULL), origin.y - runDescent, runRect.size.width, runAscent + runDescent); NSString * name = [attrs objectForKey:@"imageName"]; NSLog(@"name == %@",name); if ([name isKindOfClass:[NSString class]]) { if ([name isEqualToString:@"xiaopang.jpg"]) { //绘制本地图片 UIImage *img = [UIImage imageNamed:name]; CGRect imgDrawRect; imgDrawRect.size = img.size; imgDrawRect.origin.x = runRect.origin.x; imgDrawRect.origin.y = origin.y; CGContextDrawImage(context, imgDrawRect, img.CGImage); NSLog(@"%@",NSStringFromCGRect(imgDrawRect)); } else{ NSLog(@"绘制网络图片"); CTRunDelegateRef del = (__bridge CTRunDelegateRef)[attrs objectForKey:(__bridge id)kCTRunDelegateAttributeName]; if (!del) { break; } UIImage * image; if (!_myImage) { image = [UIImage imageNamed:@"xiaopang.jpg"]; [self downloadImageWithURL:[NSURL URLWithString:name]]; } else{ image = _myImage; } //网络图片 CGRect myRect; NSDictionary * dict = (NSDictionary *)[attrs objectForKey:@"dict"]; myRect.size.height =[[dict objectForKey:@"height"] floatValue]; myRect.size.width = [[dict objectForKey:@"width"]floatValue]; myRect.origin.x = runRect.origin.x; myRect.origin.y = origin.y; NSMutableArray * arr = [NSMutableArray array]; [arr addObject:[NSValue valueWithPointer:context]]; [arr addObject:image]; [arr addObject:NSStringFromCGRect(myRect)]; // [self performSelectorOnMainThread:@selector(drawImage:) withObject:arr waitUntilDone:NO]; CGContextDrawImage(context, myRect, image.CGImage); } } } } }
-(void)downloadImageWithURL:(NSURL *)url { __weak typeof(self) weakself = self; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSData * data = [NSData dataWithContentsOfURL:url]; _myImage = [UIImage imageWithData:data]; NSLog(@"%@",@"下载完毕 设置图片"); if (_myImage) { NSLog(@"%@",@"sadsga"); dispatch_async(dispatch_get_main_queue(), ^{ [weakself setNeedsDisplay]; }); } }); }