UILabel *templabel = [self.wallBoxArray objectAtIndex:i];
for( int i = 0 ; i < [self.wallBoxArray count]; i++)
{
if(templabel.backgroundColor == [UIColor greenColor])
{
NSLog(#"the color isn green");
}
}
There are many label's in my array. They all initialized with green color. But i judged that way ,why cant print " the color isn't green.
The UIColor class cluster implements -isEqual:, so you could just use
if([templabel.backgroundColor isEqual:[UIColor greenColor]])
...
You are performing a pointer comparision there, so if the color's are both green, but different instances of UIColor, this will fail. And they are because UIView's backgroundColor property is a copy property.
#property(nonatomic, copy) UIColor *backgroundColor
I'm sort of surprised this is that convoluted, but to check for equality, try the following:
CGColorEqualToColor([templabel.backgroundColor CGColor], [[UIColor greenColor] CGColor])
This is checking equality of the color value, not just a pointer comparison. Also remember to do [str compare:otherString] == NSOrderSame when checking strings!
Related
I'm trying to add some different text colors to my app to be fused to an image. I've got alot of input that my users would like a rainbow text color and repeat. So for instance the word: stackoverflow would look like this: s=red t=orange a=yellow c=green k=blue o=purple v=pink e=red r=orange f=yellow l=green o=blue w=purple
I can't even begin to think how I can do this in one single UITextView
Does anyone know how I could achieve this as the user is typing? Tips? Example?
I didn't see any other posts on SO regarding rainbow text for iOS. (correct me if im wrong)
You can do using NSAttributedString:
To make it a general method to support OSX and iOS. Now no need to change NSColor to UIColor, use this on both the operating systems.
#if TARGET_OS_IPHONE
typedef UIColor Color;
#elif TARGET_OS_MAC
typedef NSColor Color;
#endif
-(NSAttributedString *)colorfulStringFrom:(NSString *)string{
NSArray *colors = #[[Color redColor],
[Color yellowColor],
[Color greenColor],
[Color blueColor],
[Color purpleColor],
[Color magentaColor]
];
NSMutableAttributedString *attribString = [[NSMutableAttributedString alloc]initWithString:string];
for (NSInteger location=0; location<string.length; location++) {
NSRange range = NSMakeRange(location, 1);
Color *color = colors[location%colors.count];
[attribString addAttribute:NSForegroundColorAttributeName value:color range:range];
}
return attribString;
}
Output:
I currently have a Core Data database that stores data and I wish to also store an NSColor into it but It does not accept NSColor as an object. My solution would be to store it as a string in the database and have it read into a NSColor when loaded. How would I do this?
For example, If I had a colour like [NSColor redColor] how would I store it in a database (as a string) and then retrieve it. This is a basic example and it would be more complicated RGB colors in the end.
Thanks.
You should consider using NSData as container for storing unsupported data types in Core Data. To access NSColor as NSData you will need to mark attribute as transformable and create reversible NSValueTransformer class to transform NSColor as NSData.
Useful Link: Non-Standard Persistent Attributes
I agree with the answers that recommend using NSData for storing colors in a Core Data store. That said, there may be times when it might be useful to store a color in a string, and it's certainly not difficult to do. I'd suggest creating a category on NSColor:
#interface NSColor (NSString)
- (NSString*)stringRepresentation;
+ (NSColor*)colorFromString:(NSString*)string forColorSpace:(NSColorSpace*)colorSpace;
#end
#implementation NSColor (NSString)
- (NSString*)stringRepresentation
{
CGFloat components[10];
[self getComponents:components];
NSMutableString *string = [NSMutableString string];
for (int i = 0; i < [self numberOfComponents]; i++) {
[string appendFormat:#"%f ", components[i]];
}
[string deleteCharactersInRange:NSMakeRange([string length]-1, 1)]; // trim the trailing space
return string;
}
+ (NSColor*)colorFromString:(NSString*)string forColorSpace:(NSColorSpace*)colorSpace
{
CGFloat components[10]; // doubt any color spaces need more than 10 components
NSArray *componentStrings = [string componentsSeparatedByString:#" "];
int count = [componentStrings count];
NSColor *color = nil;
if (count <= 10) {
for (int i = 0; i < count; i++) {
components[i] = [[componentStrings objectAtIndex:i] floatValue];
}
color = [NSColor colorWithColorSpace:colorSpace components:components count:count];
}
return color;
}
#end
I've checked that the code above compiles and works about as advertised. A small sample program produces appropriate output:
int main(int argc, const char * argv[])
{
#autoreleasepool {
NSLog(#"Red is: %#", [[NSColor redColor] stringRepresentation]);
NSLog(#"Cyan is: %#", [[NSColor cyanColor] stringRepresentation]);
NSLog(#"Read in: %#", [NSColor colorFromString:[[NSColor redColor] stringRepresentation]
forColorSpace:[NSColorSpace deviceRGBColorSpace]]);
}
return 0;
}
Output:
Red is: 1.000000 0.000000 0.000000 1.000000
Cyan is: 0.000000 1.000000 1.000000 1.000000
Read in: NSCustomColorSpace Generic RGB colorspace 1 0 0 1
It might make sense to store the color space in the string so you don't have to specify it when you go from string to color. Then again, if you're just going to store these strings and read them again, you should be using NSData anyway. Using strings makes more sense if you need to write colors into some sort of human-readable file, or perhaps as a debugging aid.
NSColor supports the NSCoding protocol, so you can use the -encodeWithCoder: method to save it to an archive, and you can use -initWithCoder: to load it from an archive.
Property lists do not store colors and Apple recommends you store them as NSData not as NSString, you should probably do the same. See Apple's instructions here.
Here are simple functions for converting an NSColor to and from an NSString. This example assumes we're using an RGB color space, but
it can be easily adapted for others. For example, NSStringFromColor() could include the color space in the string and use that information when converting back to a color in NSColorFromString().
Usage:
NSString *theColorString = NSStringFromColor(theColor);
NSColor *theColor = NSColorFromString(theColorString);
The functions:
NSString *NSStringFromColor(NSColor *theColor)
{
CGFloat red, green, blue, alpha;
[theColor getRed:&red green:&green blue:&blue alpha:&alpha]; // assumes RGB color space
NSString *theColorString = [NSString stringWithFormat:#"%f %f %f %f",red,green,blue,alpha];
return theColorString;
}
NSColor *NSColorFromString(NSString *theColorString)
{
if ( theColorString.length == 0 ) {
theColorString = #"0.9 0.9 0.95 1.0"; // a default color
}
NSArray <NSString *> *theColors = [theColorString componentsSeparatedByString:#" "];
if ( theColors.count == 4 ) { // sanity
// unpack the color
NSColor *theColor = [NSColor colorWithSRGBRed:theColors[0].floatValue
green:theColors[1].floatValue
blue:theColors[2].floatValue
alpha:theColors[3].floatValue];
return theColor;
}
return nil; // theColorString format error
}
I am using a textview in which I have passed an array of objects. In that array I have taken a list of messages that would be passed to the textview, but I have changed the size of textview font so. give any suggestion and source code which is apply in my application.
Below my code in that I have apply the UIFont but that is not use in font.
msgtxtView.text=selectedmsg;
[msgtxtView setFont:[UIFont fontWithName:#"Arial" size:10]]
selectedmsg is array of object in that message list that would be pass to textview's object but output font size and arialfont not work give any.
Use this :
msgtxtView.text=selectedmsg;
[msgtxtView setFont:[UIFont fontWithName:#"ArialMT" size:10]]
Look at his example how to add text from array and change size (You changing size correctly):
NSMutableArray *array = [NSMutableArray arrayWithObjects:#"message1", #"message2", #"message3", #"message4", #"message5", nil];
for (int i=0; i<[array count]; i++) {
msgtxtView.text = [NSString stringWithFormat:#"%#%#\n",msgtxtView.text,[array objectAtIndex:i]];
}
[msgtxtView setFont:[UIFont fontWithName:#"Arial" size:10]];
Don't forget to IBOutlet msgtxtView.
Result:
And for example using this: [UIFont fontWithName:#"Chalkduster" size:25]:
I've got an NSTask (with an NSPipe set up) running in the background and I want to output the contents, as they're coming in, in an NSTextView (output).
The code I'm using is :
NSMutableAttributedString* str = [[NSMutableAttributedString alloc] initWithString:s];
//[str addAttribute:NSForegroundColorAttributeName value:[NSColor whiteColor] range:NSMakeRange(0, [str length])];
[[output textStorage] appendAttributedString:str];
[output scrollRangeToVisible:NSMakeRange([[output string] length], 0)];
Issues :
When there is a lot of data appending, the view seems like "flashing"... and not working properly.
Given that the NSTextView is on a Sheet, NO CONTENTS seem to be appearing when the mouse pointer is elsewhere other than hovering above the NSTextView
Why is that, although I've set the color/insertion color/etc of the NSTextView, this doesn't seem to apply to newly inserted text?
What's the suggested way of appending (+scrolling) on an NSTextView?
Thanks!
Remember that user interface elements, and this includes NSTextView, do their magic on the main thread. If you're attempting to add information to the text view, that's where you'd best be doing it. Here's how:
[[output textStorage] performSelectorOnMainThread:#selector(appendAttributedString:)
withObject:str
waitUntilDone:YES];
I'd address your third point, but frankly, that's a thing of which I'm still very much a student.
To address your fourth point, it would appear you've got that figured out; just combine your append and scroll actions. But just like changing the contents of textStorage, you want to be sure you're doing this on the main thread. Since -scrollRangeToVisible: doesn't take an object for its argument, you have to do this a bit differently:
dispatch_async(dispatch_get_main_queue(), ^{
[output scrollRangeToVisible:NSMakeRange([[output string] length], 0)];
});
My first example notwithstanding, you could place your call to -appendAttributedString: inside that block as well:
dispatch_async(dispatch_get_main_queue(), ^{
[[output textStorage] appendAttributedString:str];
[output scrollRangeToVisible:NSMakeRange([[output string] length], 0)];
});
Regarding the recommended way of appending to the NSTextView: You're doing quite well with appendAttributedString:, but it's recommended to shield it inside shouldChangeTextInRange, then a beginEditing, appendAttributedString, and finally endEditing:
textStorage = [textView textStorage];
if([textView shouldChangeTextInRange:range replacementString:string])
{
[textStorage beginEditing];
[textStorage replaceCharactersInRange:range withAttributedString:attrStr];
// or if you've already set up the attributes (see below)...
// [textStorage replaceCharactersInRange:range withString:str];
[textStorage endEditing];
}
I'd strongly suggest replacing scrollRangeToVisible: by scrollToPoint:, as scrollRangeToVisible: will cause a lot of flickering and it will also gradually become slower as you move 'down the range'.
A quick-and-dirty way could be something like this:
- (void)scrollToBottom
{
NSPoint pt;
id scrollView;
id clipView;
pt.x = 0;
pt.y = 100000000000.0;
scrollView = [self enclosingScrollView];
clipView = [scrollView contentView];
pt = [clipView constrainScrollPoint:pt];
[clipView scrollToPoint:pt];
[scrollView reflectScrolledClipView:clipView];
}
I let constrainScrollPoint do all the calculation work.
I do this, because my calculations failed anyway (those suggested by Apple and others, that used visRect/docRect coordinates, produced unreliable results).
reflectScrolledClipView is also important; it updates the scroll bar so it has the correct proportion and position.
You might also find it interesting to know when scrolling has occurred. If so, subscribe to both NSViewBoundsDidChangeNotification and NSViewFrameDidChangeNotification. When one of them occurs, the scroll bar position most likely changed (investigate [textView visibleRect] and [textView bounds]).
I see you also have trouble with the text-attributes. So did I for a long time.
I found that appending an attributed string would help quite a lot, but it still wasn't enough for the text being typed.
..Then I found out about typingAttributes.
When setting up your NSTextView, for instance in an -awakeFromNib, you can pick what you like from the following...
NSMutableParagraphStyle *paragraphStyle;
float characterWidth;
NSFont *font;
uint32_t tabWidth;
NSMutableDictionary *typingAttributes;
tabWidth = 4;
font = [NSFont fontWithName:#"Monaco" size:9.0];
paragraphStyle = [[textView defaultParagraphStyle] mutableCopy];
if(NULL == paragraphStyle)
{
paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
// or maybe:
// paragraphStyle = [NSParagraphStyle new];
}
characterWidth = [[font screenFontWithRenderingMode:NSFontDefaultRenderingMode] advancementForGlyph:(NSGlyph)' '].width;
[paragraphStyle setDefaultTabInterval:(characterWidth * (float) tabWidth];
[paragraphStyle setTabStops:[NSArray array]];
typingAttributes = [[textView typingAttributes] mutableCopy];
if(NULL == typingAttributes)
{
typingAttributes = [NSMutableDictionary new];
}
[typingAttributes setObject:paragraphStyle forKey:NSParagraphStyleAttributeName];
[typingAttributes setObject:font forKey:NSFontAttributeName];
[textView setTypingAttributes:attributes];
...It's way more than you probably need, but it shows how you can set the font, the tab width and the typing attributes.
NSForegroundColorAttributeName might also be interesting for you (as well as some other attributes, type NSForegroundColorAttributeName in Xcode and option-double-click on it, then you'll see some more attributes (you can command-double-click as well; this takes you to the definition in the header file).
ok I have a press basic application with the following code in newAppViewController.m
When I run my app, the label i have called myLabel changes the text but the color of the view ALWAYS becomes blue not red. For some reason its always the else case!
Any Ideas?
-(IBAction)click:(id)sender{
NSString *mystr = [[NSString alloc]initWithFormat:#"%#",[[sender titleLabel] text] ];
myLabel.text = mystr;
if(myLabel.text == #"RED")
self.view.backgroundColor = [UIColor redColor];
else self.view.backgroundColor = [UIColor blueColor];
}
Why don't you try with
if([myLabel.text isEqualToString:#"RED"])
You can't compare two string with "==" operator. Use the -isEqualToString: method for this.
To compare two scalars you have to use the == operator; When you are comparing objects you have to use the -isEqual: method, and when you are comparing strings you have to use the --isEqualToString: method.