简体   繁体   中英

Altering Ray Wenderlich's Parser not working with UITextView

I have tried to lift the parser in Ray Wenderlich's simple magazine tutorial into my project. His parser code is here: how to create a simple magazine app with core text

The main controller passes a text string to the parser, which dissects it, adds attributes and then returns the attributed string, using the following code in viewDidLoad:

 - (void)viewDidLoad
{
    [super viewDidLoad];

    NSString *path = [[NSBundle mainBundle] pathForResource:@"zombies" ofType:@"txt"];
    NSString* text = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:NULL];
MarkupParser* p = [[[MarkupParser alloc] init] autorelease];
NSAttributedString* attString = [p attrStringFromMarkup: text];
[(CTView *)[self view] setAttString:attString withImages: p.images];
[(CTView *)[self view] buildFrames];
}

As I am using Ios6 im thinking that the attributed string passed back from the parser can simply be added to a UITextView instead of having to mess around with CoreText. With this in mind ive altered the above code to the following:

    - (void)viewDidLoad
{
    [super viewDidLoad];

    NSString *path = [[NSBundle mainBundle] pathForResource:@"zombies" ofType:@"txt"];
    NSString* text = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:NULL];
    MarkupParser* p = [[[MarkupParser alloc] init] autorelease];
    NSAttributedString* attString = [p attrStringFromMarkup: text];

    UITextView *view = [[UITextView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height)];

    view.attributedText = attString;
    [self.view addSubview:view];
}

However this now produces an error saying 'unknown selector sent to instance' on the line which sets the view.attributedText to attString. Im certain the attributed string returned from the parser is to blame, but cant for the life of my figure out why! any ideas out there?


Here is a screenshot of the console during runtime:

在此输入图像描述

在此输入图像描述


The next image is a screenshot of the details in the AttributedString named attString which is causing the problem

在此输入图像描述

And finally the following section of the code is where the parser gets its attributes set, and which could possibly causing the pointSize error shown in the debugger above.

 CTFontRef fontRef = CTFontCreateWithName((CFStringRef)CFBridgingRetain(self.font),
                                             24.0f, NULL);

 //apply the current text style
 NSDictionary* attrs = [NSDictionary dictionaryWithObjectsAndKeys:
                       (id)self.color.CGColor, kCTForegroundColorAttributeName,
                       (id)CFBridgingRelease(fontRef), kCTFontAttributeName,
                       (id)self.strokeColor.CGColor, (NSString *) kCTStrokeColorAttributeName,
                       (id)[NSNumber numberWithFloat: self.strokeWidth], (NSString *)kCTStrokeWidthAttributeName,
                       nil];

 [aString appendAttributedString:[[NSAttributedString alloc] initWithString:[parts objectAtIndex:0] attributes:attrs] ];

The "bridging" commands above were added automatically by Xcode, I know its something to do with ARC, but I dont really understand them and so dont know if these are causing the problem!

It looks to me like you must be running in a pre-iOS6 environment - while you might be using the iOS6 SDK, you could be running in the iOS5 simulator. You definitely have a UITextView , if it was iOS6 then setAttributedText: would be fine. Before iOS6 UITextView did not have the attributedText property and so trying to set it would result in 'unknown selector sent to instance'.

If you find this isn't the case check your console output. It probably says just what the unknown selector is...

3 whole days later its sorted!!

My solution (thanks to @Adam Eberbach for pointing me towards the parser!) is a fairly major overhaul of the parser code used by Ray Wenderlich. Basically the problem was that I was lifting CoreText coding from his example and trying to use those attributes in the UITextView attributed string - so UITextView wasnt understanding what was being passed to it.

By replacing his parser with basic NS attributes rather than CG attributes (thus changing the majority of his code!) the UITextView was then able to understand what was being passed to it. I was able to keep the same regex's he created which is a god-send because try as i might, I cant understand what all those symbols mean!

My replacement code for the final snippet of code in the original post is as follows:

    for (NSTextCheckingResult* b in chunks) {
    NSArray* parts = [[markup substringWithRange:b.range]
                      componentsSeparatedByString:@"<"]; //1

    NSMutableAttributedString *temp = [[NSMutableAttributedString alloc] initWithString:[parts objectAtIndex:0]];
    [temp addAttribute:NSFontAttributeName value:[UIFont fontWithName:self.font size:20] range:NSMakeRange(0, [temp length])];
    [temp addAttribute:NSForegroundColorAttributeName value:self.color range:NSMakeRange(0, [temp length])];

    [aString appendAttributedString:temp];

Note that this doesnt include the stroke color and width attributes which Ray had in his original because these arent supported by UITextView, only by CoreText. However any other attributes can now be set in the same way with just a simple addition of another regex and another add:Attribute.

All in all I now have a very simple way of converting a long .txt file into attributed text just by adding a couple of tags in the text where I want the format to change. My gratitude to Ray and Alan!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM