Can't Change NSButton Font - objective-c

I'm trying to change the font of a NSButton subclass I've created. I'm able to set the font up when I set up the the actual button using the following code:
[button setFont:[NSFont fontWithName:#"Courier" size:15]];
However, when I'm trying to do it later on in my application, it doesn't work.
I'm trying to get the user to select a new font; once they've done this, I want to update this button to use the selected font.
I know my font-selection process isn't the issue, as I can change the font of other UI items to what the user's chosen.
Additionally, I thought the problem was due to the fact that my subclass is going through a CABasicAnimation, but when I remove animations, it still doesn't work. Furthermore, I can even change the button's font color while the animation is running.
Finally, I'm certain my outlets are connected right.
So where could the problem be coming from? Has anyone experienced a similar issue in the past?

I would recommend you check your IB connections cause setFont: should work.
Or you could try using:
(void)setAttributedTitle:(NSAttributedString *)aString
where an NSAttributedString can be created from:
- (id)initWithString:(NSString *)aString attributes:(NSDictionary *)attributes
where attributes can be created as:
NSDictionary * attributes = [NSDictionary dictionaryWithObject:[NSFont fontWithName:#"Courier" size:15] forKey:NSFontAttributeName];

Related

After creating an NSTextField with editable area, not able to type anything

I can't seem to get this working, which is a bit interesting to say the least.
So, I have a couple friends and we have an example set of code we're supposed to use and expand upon for a project. The problem? It only appears to work properly on Windows-based machines. The entire project is a java to objective c server/client relationship. We previously did Java to Java, and are now having to get the Objective C portion working.
The code is here(Please note, this is just a very small snippet of the code in comparison to the whole project):
- (NSTextField*) addFieldWithTitle:(NSString*) aTitle at: (NSRect) aRect {
NSTextField* label =[[[NSTextField alloc] initWithFrame: aRect] autorelease];
[label setSelectable: YES];
[label setEditable: YES];
[label setBezeled: YES];
[label setDrawsBackground: YES];
[label setStringValue: aTitle];
[[window contentView] addSubview: label];
return label;
}
On my Mac it shows up properly, and allows each field to be selected (each field that NEEDS to be selected, that is). But the problem is as follows: After selecting the field, you cannot type anything. Whatever is typed is then received by the previous program / application you had open just prior to selecting this "program" that shows up. It appears to not register it properly at all, because it doesn't type at all.
What makes it even more interesting is that I can right click (or control click) the editable fields, and then select "paste" and it will paste the strings that I had previously copied to the clip board...
So that's my interesting issue, and I can't seem to find any answers and my classmates cannot find answers either.
Any assistance would be greatly appreciated!
Regards,
Michael
P.S. If you would like the full code we are running, I can provide that as well.

Keep NSTextView's Font From Changing

I thought this would be straight forward, but it looks like I was wrong. Basically, all I'm trying to do is keep the font from changing to the Apple default: Helvetica Regular 12pt.
I've made a subclass of NSDocument and in my implementation file I have the following method:
- (void)windowControllerDidLoadNib:(NSWindowController*)aController
{
[super windowControllerDidLoadNib:aController];
if(attrString)
{
[[textView textStorage] setAttributedString:attrString];
[[textView textStorage] setFont:[NSFont fontWithName:#"Menlo Bold" size:24]];
}
This method works all right when I open a file, but if I delete all of the text and then type again, the font resets to... Helvetica Regular 12pt... All I want is to keep the font and size as I specified it for the entire life of the program.
You need to set the typing attributes of the text view to contain your font for the key NSFontAttributeName.
However, I would go a step further. If you know you NEVER want a certain font in your model (NSTextStorage -- the backing store for NSTextView), simply subclass NSTextStorage and override the attribute setters and getters. NSTextView gives the user access to font menus and copy/paste will still allow certain fonts in. The only way to truly guarantee it never enters your text view is to never allow it into the model.

How to create Multiple Themes/Skins for iphone apps? [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 11 years ago.
I have an iphone app ready and approved by the app store. Now I want to create different themes for my app. Can someone please help me out, with info/links/steps on how to create themes for my app?
I want to create a Metal theme for the Boys and a Pink theme for the Girls. Again by theme I mean, the whole app(features and functionality) is gonna stay the same, but depending on who the user is(boy or girl), he/she can choose the theme they wish to see. And when the theme changes, only the images/Background/music will change according to the applied theme.
Thanks a lot!
This is quite difficult as apps don't have the equivalent of a css stylesheet.
First you need to work out what parts of the app you want to skin, and when you want to allow the user to swap skins.
I'm going to assume that you want to change images and font colours, and that it's okay if the user has to relaunch the app to change the skin (that will make things simpler for now).
Create a plist containing all your skinnable images and colours. The plist will be a dictionary with sensible, theme neutral key names for the images and colours (e.g. don't have a colour called "red", call it "primaryHeadingColor"). Images will be file names, and colours can be hex strings, e.g. FF0000 for red.
You'll have one plist for each theme.
Create a new class called ThemeManager and make it a singleton by adding the following method:
+ (ThemeManager *)sharedManager
{
static ThemeManager *sharedManager = nil;
if (sharedManager == nil)
{
sharedManager = [[ThemeManager alloc] init];
}
return sharedManager;
}
The ThemeManager class will have an NSDictionary property called "styles", and in the init method you will load the theme into your styles dictionary like this:
- (id)init
{
if ((self = [super init]))
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *themeName = [defaults objectForKey:#"theme"] ?: #"default";
NSString *path = [[NSBundle mainBundle] pathForResource:themeName ofType:#"plist"];
self.styles = [NSDictionary dictionaryWithContentsOfFile:path];
}
return self;
}
(Note: some people don't like doing a lot of work inside an init method. I've never found it to be an issue, but if you prefer, create a separate method to load the themes dictionary and call it from your app's setup code).
Notice how I'm getting the name for the theme plist from user defaults. That means the user can select a theme in your preferences and save it and the app will load that theme next time it is launched. I've put in a default theme name of "default" if no theme is selected, so make sure you have a default.plist theme file (or change the #"default" in the code to whatever your default theme plist is actually called).
Now that you've loaded your theme you need to use it; I'm assuming your app has various images and text labels. If you're loading and laying those out in code then this part is easy. If you are doing it in nibs then it's a bit trickier but I'll explain how to handle that later.
Now normally you would load an image by saying:
UIImage *image = [UIImage imageNamed:#"myImage.png"];
But if you want that image to be themable, you'll now need to load it by saying
NSDictionary *styles = [ThemeManager sharedManager].styles;
NSString *imageName = [styles objectForKey:#"myImageKey"];
UIImage *image = [UIImage imageNamed:imageName];
That will look in your theme file for the themed image that matches the key "myImageKey" and will load it. Depending on which theme file you've loaded you'll get a different style.
You'll be using those three lines a lot so you may want to wrap them up in a function. A great idea would be to create a category on UIImage that declares a method called something like:
+ (UIImage *)themeImageNamed:(NSString *)key;
Then to use it you can just replace any calls to [UIImage imageNamed:#"foo.png"]; with [UIImage themeImageNamed:#"foo"]; where foo is now the theme key instead of the actual image name.
Okay, so that's it for theming your images. To theme your label colours, suppose you're currently setting your label colours by saying:
someLabel.color = [UIColor redColor];
You would now replace that with:
NSDictionary *styles = [ThemeManager sharedManager].styles;
NSString *labelColor = [styles objectForKey:#"myLabelColor"];
someLabel.color = [UIColor colorWithHexString:labelColor];
Now you may have noticed that UIColor doesn't have a method "colorWithHexString:" - you'll have to add that using a category. You can Google for "UIColor with hex string" solutions to find code to do that, or I've written a handy category that does that and a bit more here: https://github.com/nicklockwood/ColorUtils
If you've been paying attention you'll also be thinking that instead of writing those three lines over and over, why not add a method to UIColor called:
+ (UIColor *)themeColorNamed:(NSString *)key;
Just like we did with UIImage? Great idea!
So that's it. Now you can theme any image or label in your app. You could use the same trick to set the font name, or any number of other potentially themable visual properties.
There's just one tiny thing we've forgotten...
If you've built most of your views as nibs (and I see no reason why you wouldn't) then these techniques aren't going to work because your image names and font colours are buried inside impenetrable nib data and aren't being set in your source code.
There are a few approaches to solve this:
1) You could make duplicate themed copies of your nibs and then put the nib names in your theme plist and load them from your theme manager. That's not too bad, just implement the nibName method of your view controllers like this:
- (NSString *)nibName
{
NSDictionary *styles = [ThemeManager sharedManager].styles;
return [styles objectForKey:NSStringFromClass([self class])];
}
Notice my neat trick of using the class name of the view controller as the key - that will save you some typing because you can just make a base ThemeViewController with that method and have all your themable view controllers inherit from it.
This approach does mean maintaining multiple copies of each nib though, which is a maintenance nightmare if you need to change any screens later.
2) You could make IBOutlets for all of the imageViews and labels in your nibs, then set their images and colors in code in your viewDidLoad method. That's probably the most cumbersome approach, but at least you don't have duplicate nibs to maintain (this is essentially the same problem as localising nibs btw, and pretty much the same solution options).
3) You could create a custom subclass of UILabel called ThemeLabel that automatically sets the font color using the code above when the label is instantiated, then use those ThemeLabels in your nib files instead of regular UILabels by setting the class of the label to ThemeLabel in Interface Builder. Unfortunately if you have more than one font or font colour, you'll need to create a different UILabel subclass for each different style.
Or you could be devious and use something like the view tag or accessibilityLabel property as the style dictionary key so that you can have a single ThemeLabel class and set the accessibility label in Interface Builder to select the style.
The same trick could work for ImageViews - create a UIImageView subclass called ThemeImageView that, in the awakeFromNib method replaces the image with a theme image based on the tag or accessibilityLabel property.
Personally I like option 3 best because it saves on coding. Another advantage of option 3 is that if you wanted to be able to swap themes at runtime, you could implement a mechanism where your theme manager reloads the theme dictionary, then broadcasts an NSNotification to all the ThemeLabels and ThemeImageViews telling them to redraw themselves. That would probably only take about an extra 15 lines of code.
Anyway, there you have a complete iOS app theming solution. You're welcome!
UPDATE:
As of iOS 5, it's now possible to set custom attributes by keyPath in Interface Builder, meaning that it's no longer necessary to create a view subclass for each themable property, or abuse the tag or accessibilityLabel for selecting styles. Just give your UILabel or UIImageView subclass a string property to indicate which theme key it should use from the plist, and then set that value in IB.
UPDATE 2:
As of iOS 6, there is now a limited skinning system built into iOS that allows you to use a property called the UIAppearance proxy to skin all instances of a given control class at once (there's a good tutorial about the UIAppearance APIs here). It's worth checking if this is sufficient for your skinning needs, but if not, the solution I outlined above still works well, and can be used instead, or in combination with UIAppearance.

Problems with NSTextView where NSTextField worked

I'm just starting out with obj-c, I'm trying to build an importer to fetch a couple numbers from a piece of formatted text. I started with a wrapping TextField and was able to both get the text into a string and search it as I wanted with
NSString *varImport = [NSString stringWithString:[importTextView stringValue]];
When I switch over to the TextView in the Interface Builder I get there error
-[NSScrollView string]: unrecognized selector sent to instance 0x100429160
I think this may be the root of my problem, although I am dragging over a TextView when I look in the inspector panel its labeled as a ScrollView which I'm not familure with yet.
Through my research I came across two different sites saying that TextView wont directly feed into a string but it was for odd reasons, IE TextView stored the data as a MutableString that was constantly updating and to access it you had to copy the original (Second example) Anyways I'm turning to the experts because I'm clearly doing something wrong and I can't make sense of the answers on the web.
NSString *varImport = [NSString stringWithString:[[import textStorage] string]];
NSString *varImport = [[import string] copy];
Don't worry so much about the other stuff if you don't have the time to explain what's going in the web examples, I mainly want to know about the ScrollView stuff and how to get a string out of it to be able to search it.
Thanks in advance!
Graham
Simply because you are using the wrong method.
NSString *varImport = [NSString stringWithFormat:[importTextView string];
Also, you might have connected the importTextView instance variable to the wrong connection. A NSTextView is always in a NSScrollView. Simply just right-click your object from interface builder and drag the instances to the top of the textview (Where it should show "NSTextView").
Save the nib and try run it again. It should work.
To get text value from a text field or text view you should use - (NSString *)string method.

Changing an NSImage in XCode - this line of code not working

I am having a problem that is eating me alive. I really hope I am just missing something small here. It appears to be a rather "n00b" issue.
I have a blank NSImageView that I want to display a picture when a button is pressed — simple as that.
Here is my line of coding
NSBundle *mb = [NSBundle mainBundle];
NSString *fp = [mb pathForResource:#"tiles" ofType:#"PNG"];
NSImage *image = [[NSImage alloc] initWithContentsOfFile:fp];
if ( [image isValid] ) {
[selection setImage:image];
[selection setImageScaling:NSScaleProportionally];
}
Whereas,
tiles.PNG is a resource in my bundle
and if [image isValid] is satisfied, because I've inserted dummy code into the clause and had that work
selection is defined in my header file as follows
IBOutlet NSImageView *selection;
It is also linked up to the application delegate in IB.
I have a feeling I might not be linking it properly?
WHy wouldn't the image display? If anyone can see an error - or provide me with working code - I would be soooooo thankful
Brian
It's not a linking issue—your app wouldn't even launch (assuming it even links successfully) if you'd failed to link against Cocoa or AppKit.
More probably, either you haven't connected the outlet to your image view in your nib, or you haven't loaded the nib yet. The way to check this would be to NSLog the value of the imageView pointer, using the %p formatter.
I had a similar issue where my view wasn't displaying, and it turned out that the view was hidden. This was a setting in the view properties in Interface Builder. Just a punt, but give it a go.
You need to use the debugger and see what's going on as it runs. Is fp nil? Is image nil? Is selection nil? The debugger is your friend.
did you remember to send -setNeedsDisplay to the NSImageView after you set the image?