0

I use this code to draw an NSString on a UILabel(which i have subclassed already) with Core Graphics from a queue but nothing shows on screen. I get no error.

I call the function like this from a queue.

[label1 createtext];

-(void)createtext
{          
    UIFont *font=[UIFont fontWithName:@"Times New Roman" size:15.0];
    //Core Text (Create Attributed String)

    NSMutableArray *Text=[globaltextarray Text];
    CGSize size=[[Text objectAtIndex:0] sizeWithFont:font];

    if (UIGraphicsBeginImageContextWithOptions != NULL)
        UIGraphicsBeginImageContextWithOptions(size,NO,0.0);
    else
        // iOS is < 4.0
        UIGraphicsBeginImageContext(size);

    CGContextRef ctx = UIGraphicsGetCurrentContext();

    if (ctx != NULL)
        NSLog(@"not null context");
    UIColor *textColor = [UIColor blackColor];
    CGColorRef color = textColor.CGColor;

    CTFontRef font = CTFontCreateWithName((CFStringRef) @"TimesNewRomanPSMT", 15.0, NULL);

    CTTextAlignment theAlignment = kCTLeftTextAlignment;

    CFIndex theNumberOfSettings = 1;
    CTParagraphStyleSetting theSettings[1] = {
        { kCTParagraphStyleSpecifierAlignment, sizeof(CTTextAlignment),
            &theAlignment }
    };

    CTParagraphStyleRef paragraphStyle = CTParagraphStyleCreate(theSettings, theNumberOfSettings);

    NSDictionary *attributesDict = [NSDictionary dictionaryWithObjectsAndKeys:(id)font, (NSString *)kCTFontAttributeName,color, (NSString *)kCTForegroundColorAttributeName,paragraphStyle, (NSString *) kCTParagraphStyleAttributeName,nil];

    NSAttributedString *stringToDraw = [[NSAttributedString alloc] initWithString:[NSString stringWithCString:[[Text objectAtIndex:indexpath1.row] cStringUsingEncoding:NSISOLatin1StringEncoding] encoding:NSUTF8StringEncoding] attributes:attributesDict];

    CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)stringToDraw);

    //Prepare our view for drawing

    CGContextSetTextMatrix(ctx, CGAffineTransformIdentity);
    CGContextTranslateCTM(ctx, 0, ([self bounds]).size.height );
    CGContextScaleCTM(ctx, 1.0, -1.0);

    //Create Frame
    CGMutablePathRef path = CGPathCreateMutable();
    CGRect rect  = self.frame;
    CGPathAddRect(path, NULL, rect);

    CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL);

    //Draw Frame
    CTFrameDraw(frame, ctx);

    UIGraphicsEndImageContext();
    //Release all retained objects
    CFRelease(framesetter);
    CFRelease(path);
    [stringToDraw release];
}

Any help appreciated!

Kurt Revis
  • 27,695
  • 5
  • 68
  • 74
stefanosn
  • 3,264
  • 10
  • 53
  • 79

2 Answers2

1

You are creating a temporary graphics context, drawing into it, then discarding it. You never tell UIKit to put anything on the screen.

You need to also:

For instance:

// In your class's declaration, define an image view to show your drawing.
// Make sure that this view is created (either as part of a storyboard/nib, or with explicit code)
@property (nonatomic) UIImageView *imageView;

- (void)createText
{
    CGSize size = /* you decide */;
    UIGraphicsBeginImageContext(size);

    // draw into the graphics context
    // after you're done:

    UIImage* image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    dispatch_async(dispatch_get_main_queue(), ^{
        self.imageView.image = image;
    });
}
Kurt Revis
  • 27,695
  • 5
  • 68
  • 74
-2

You are not drawing with the CoreGraphics framework, you are drawing with UIKit and that is not allowed in a background thread. You must only call UIKit methods from the main thread. For example, you are calling UIGraphicsBeginImageContext() but that is part of UIKit. You are unlikely to get any benefit from rendering widget code in a background thread anyway, unless you are doing some truly disconnected offline rendering (like creating a PDF or something) then you should just render your widgets in the main thread.

MoDJ
  • 4,309
  • 2
  • 30
  • 65
  • 1
    [You are allowed to use `UIGraphicsBeginImageContext` in non-main threads.](http://stackoverflow.com/questions/11528803/is-uigraphicsbeginimagecontext-thread-safe) – Kurt Revis Jun 29 '13 at 03:37
  • The docs for UIGraphicsBeginImageContext() state "In iOS 4 and later, you may call this function from any thread of your app.". Your code calls this method for systems < ios 4. That means your code could crash on earlier devices. You could write code directly to CoreGraphics APIs and it would work on all devices. But, the basic problem with your approach is that it solves nothing and will not speed up rendering in the main thread. You need to rethink your basic approach. Also, you forgot to call CFRelease(frame) so your code is going to leak memory. – MoDJ Jun 29 '13 at 05:53