Add custom font - objective-c

Is it possible to apply custom (added to the app) font to UILabel text via UIBuilder or it can be done only programmatically ?
I have already added
Fonts provided by application
key in application plist

It can only be done programmaticaly, but it is simple: crate a subclass of UILabel and then overwrite the awakeFromNib method:
-(void)awakeFromNib{
[super awakeFromNib];
self.font = [UIFont fontWithName:#"MyFancyFont" size:self.font.pointSize];
}
(with this method you keep the font size you set in IB.)
In the Identity Inspector in IB you have to set the label to the class you created, in "Custom Class" (where it says "UILabel" now).

Related

Xcode: How to add Custom View from XIB File in a UIScrollView

Coming from an Android and Java background, I am relative new with Xcode Development.
I am using Xcode 5.0.2 and created my first IOS Application by selecting Create a New Xcode Project -> Single View Application. The initial project structure has been generated and I found that there is a Main_iphone.storyboard file which opens a UI Designer where I can drag and drop items to it. I selected UIScrollView and dragged it into the main window that has been generated.
Now in the Controller header file, I added #property (nonatomic, retain) IBOutlet UIScrollView *scrollView; so that i could access the scrollView from inside my controller code.
I wanted to add an item to the scrollView programatically so I created a template Custom View by adding new file -> Objective-C Class with XIB for User Interface, named it TSTFilesInfoController and designed the XIB by adding a View and a label inside the view. Same with the scrollView above, I created a property to expose the mainView in my controller class.
I hardcoded a loop of 10x inside the controller of the UIScrollView and inside the for loop I am instantiating TSTFilesInfoController and adding the view to the UIScrollView. But when i run the application, nothing is shown or added in the UIScrollView.
Heres the code for adding the CustomView:
- (void)viewDidLoad {
[super viewDidLoad];
for ( int i = 0; i < 10 ; i++) {
TSTFilesInfoController *info = [[TSTFilesInfoController alloc] init];
[self addChildViewController:info];
[self.scrollView addSubview:info.mainView];
NSLog(#"View has been added into the scrollView");
}
}
Can someone please tell me whats wrong with my codes and what would be the correct approach to achieve the output that i wanted? Thank you in advance for the help.
-- EDIT --
This code is auto-generated in TSTFilesInfoController.m
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
This is a misuse of a UIViewController subclass. Do not use a view controller just as a sort of fishing rod to hook a view that's inside a xib file. Simply load the xib file and grab the view yourself, and stuff it into your interface.
There are complex rules for how to put a view controller's view manually inside your interface, and in general it is something you should be reluctant to do. But making views come and go dynamically and directly is easy and common.
Let's suppose the .xib file is called TSTFilesInfo.xib and it has a top-level UIView subclass object, class MyView, which is the one you want. Then:
MyView* v = (MyView*)
([[UINib nibWithNibName:#"TSTFilesInfo" bundle:nil]
instantiateWithOwner:nil options:nil][0]);
This loads the nib once, instantiating its contents, and handing you a reference to that instance (the UIView in this case). Now plunk v into your interface. Keep that reference in an instance variable (probably weak, since it is retained by its superview) so that you can subsequently configure and communicate with any subviews of MyView to which you have created outlets.
NOTE: However, I must say from the example so far that it sounds to me like what you really want here is a UITableView, not a simple UIScrollView. It comes all set to do just the kind of thing you seem to up to here.

ObjectiveC UISwitch set default to OFF

How can I set the default value of my UISwitch object to Off? I am probably missing something obvious?
As mmccomb and Bruno Koga mentioned, this can be done programmatically. In this case, though--assuming that your UISwitch is getting unpacked from a nib--it may be more convenient to simply configure your UISwitch in Interface Builder.
To do this, open the xib that your switch is in, select your switch and open the Attributes Inspector (†) and within the "Switch" section, change the value of "State" from "On" to "Off":
† To open the Attributes inspector, first depress the right-end item ("Utilities") in the "View" segmented control at the far right of Xcode's toolbar
Once the Utilities Area appears with the Inspector Pane above the Library Pane, and select the Attributes Inspector item from the Inspector selector bar
All of this terminology comes from this image from Apple's Xcode documentation.
Assuming tha you have a reference for your UISwitch, you could simply override the -viewDidLoad method on your controller:
- (void)viewDidLoad
{
[super viewDidLoad];
[yourSwitch setOn:NO animated:NO];
}
Use the setOn:animated: method...
- (void)setOn:(BOOL)on animated:(BOOL)animated
e.g.
[someSwitch setOn:NO animated:YES];
UISwitch Documentation

Highlighting selected item in a NSCollectionView using NSBox

How do I make the NSCollectionView update to show the currently selected item using an NSBox? Displaying selection in a list seems like a basic thing, but I'm having all kinds of trouble with this.
I've read this question and also looked at the sample code from Apple. There seems to be several ways to do this.
Using a subclasses of NSCollectionViewItem and special "prototype view".
Using a NSBox.
I wish to use the NSBox way since it seems simples and is also used in the official code sample.
It's apparently done as described in the following quote by alternegro:
If a different background color will suffice as a highlight, you could
simply use an NSBox as the root item for you collection item view.
Fill the NSBox with the highlight color of your choice. Set the NSBox
to Custom so the fill will work. Set the NSBox to transparent.
Bind the transparency attribute of the NSBox to the selected attribute
of File Owner(Collection Item) Set the value transformer for the
transparent binding to NSNegateBoolean.
I'm stuck at the very first part: "use an NSBox as the root item for you (sic) collection item view". I've tried to change the "Custom Class" to a FoobarBox that inherits from NSBox, but it doesnt seems to help as I cannot change the background color to blue nor can I bind the transparency. Any pointers on how to make the selection display in my NSCollectionVuew would be appreciated.
First, create a class for your ListView that inherits from NSBox
#interface MyListViewBox : NSBox
#property (unsafe_unretained) IBOutlet NSCollectionViewItem *controller;
#end
Then, in Interface Builder, specify your class name as "Custom class" property as shown on my screenshot
Then you will realize IB does not show NSBox properties or binding in the GUI (at least with version 4.5.2), so I decided to change the properties programmatically.
Create an outlet for NSCollectionViewItem in your NSBox subclass (as seen above)
Use IB to link the outlet to your NSCollectionItemView
in -(void)awakeFromNib for your NSBox subclass, add the following code
-(void)awakeFromNib {
//properties are not showing up in XCode Inspector IB view
//configuring the box here :-(
self.boxType = NSBoxCustom;
self.borderType = NSLineBorder;
self.fillColor = [NSColor selectedControlColor];
//bind the "transparent" property of NSBox to the "selected" property of NSCollectionViewItem controller
//controller is bound as IBOutlet in IB
NSValueTransformer* transformer = [NSValueTransformer valueTransformerForName:NSNegateBooleanTransformerName];
[self bind:#"transparent"
toObject:self.controller
withKeyPath:#"selected"
options:[NSDictionary dictionaryWithObjectsAndKeys:transformer, NSValueTransformerBindingOption, nil]];
}
In XCode 4.5.2, you can just delete the NSView that comes automatically with the NSColletionView and drag in an NSBox (which will have all the appropriate bindings available). Make sure you re-bind the CollectionView to your new Box.

How do I modify the automatically generated About window in my Cocoa app?

A menu item for "About MyApp" was automatically created for me and it displays an about window. How do I edit this window? I'd like to add some extra stuff there but I can't find the xib anywhere.
Thanks!
Modify the contents of Credits.rtf file located inside the 'supporting files' group of your project.
A menu item for "About MyApp" was automatically created for me and it
displays an about window.
This is standard with Xcode templates for Cocoa apps. Keep reading to see how it is wired.
How do I edit this window? I'd like to add some extra stuff there but
I can't find the xib anywhere.
There is no xib: This window is created at runtime by the application object ([NSApplication sharedApplication]), when it receives the message orderFrontStandardAboutPanelWithOptions:, which that menu item sends when selected (as you an verify in the Connections Inspector in Interface Builder).
By default (as others have mentioned), it loads the contents to display from a file named "Credits.rtf" if such file exists within your app bundle's resources; otherwise it grabs basic info from your app's Info.plist entries:
App name
Bundle version
Copyright notice
What you can do is override this behaviour as follows:
Create a custom "About" window in Interface builder, with all the subviews and labels you want. Name the file "AboutWindow.xib".
Create a custom NSWindowController subclass, initialized with your custom window's nib name and set as the nib's owner:
- (instancetype) init {
if(self = [super initWithWindowNibName:#"AboutWindow" owner:self]){
// (other initialization...)
}
return self;
}
Connect your About window's subviews to outlets in the window controller class.
Also, specify the class for File Owner as your custom NSWindowController subclass and connect the window's "New Referencing Outlet" to File Owner's window property.
Go to MainMenu.xib in Interface Builder. Remove the action that is wired to the menu item "About ...", and re-wire a new one to the about: method of the placeholder object "First Responder".
In your app delegate, add an instance variable to hold your window controller so it does not get deallocated right away (alternatively, make your window controller class a singleton and use the shared instance):
#implementation AppDelegate {
AboutWindowController *_aboutwindowController;
}
Still in AppDelegate, implement the method about: that you wired in step 3, like this:
- (IBAction)about:(id)sender {
if (_aboutwindowController == nil) {
_aboutwindowController = [AboutWindowController new];
}
[_aboutwindowController.window orderFront:self];
}
...or, if your view controller is implemented as a singleton, like this:
- (IBAction)about:(id)sender {
[[AboutWindowController defaultController].window orderFront:self];
}
Finally, in order for your window controller to correctly display your app's information, read the relevant keys from the Info.plist file, like this (actual outlet ivars will be different in you case):
- (void)windowDidLoad {
[super windowDidLoad];
// Implement this method to handle any initialization after your window
// controller's window has been loaded from its nib file.
NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];
self.appNameLabel.stringValue = [infoDictionary objectForKey:#"CFBundleName"];
self.appVersionLabel.stringValue = [infoDictionary objectForKey:#"CFBundleShortVersionString"];
self.appCopyrightLabel.stringValue = [infoDictionary objectForKey:#"NSHumanReadableCopyright"];
}
You might be tempted to read the app icon from the bundled resources too, but there's a more elegant way that works even if you didn't specify an icon and are stuck with the default "Ruler + Pencil + Brush over a Sheet" app icon: Grab the runtime icon image using the following code:
self.appIconImageView.image = [NSApp applicationIconImage];
I have put together a demo project on Github that shows this and further customizations of the About window.
UPDATE: I have added a Swift version of the demo project to the Github repository.
It features:
Swift 4 (now that Xcode 9 is official)
Storyboards instead of xibs
Moved all the outlets to the new view controller, kept window appearance code in the window controller.

How to programmatically change label in UIView created in a nib file?

I have trouble changing the text in a label programmatically.
When I run the following code, NSLog does display "Setting myLabel to = Hello World!", but the label on the screen is not changed.
UIViewOverlay *overlayWindow;
overlayWindow = [[[NSBundle mainBundle] loadNibNamed:#"UIViewOverlay" owner:self options:nil] objectAtIndex:0];
[self addSubview:overlayWindow];
[overlayWindow setMyLabel:#"Hello World!"];
My NIB file has a 300x300 window with some labels and buttons.
There is a label, which is connected to myLabel in the outlet. The UIView does display, just that the text cannot be changed programmatically.
UIViewOverlay.h
#import <UIKit/UIKit.h>
#interface UIViewOverlay : UIView {
IBOutlet UILabel *myLabel;
}
- (void)setMyLabel:(NSString *) label;
#end
UIViewOverlay.m
#import "UIViewOverlay.h"
#implementation UIViewOverlay
- (void)setMyLabel:(NSString *) label {
myLabel.text = label; // THIS LINE IS NOT WORKING! :-(
NSLog(#"Setting myLabel to = %#", label); // This line is working.
}
#end
Thanks in advance..
You are using an incorrect accessor name for your method to set the label string.
In cocoa, setFoo is the method by which an instance variable called foo is assigned. This isn't just a convention, many areas of functionality depend on it, for example the use of properties, key value coding etc.
In your code, your label is called myLabel. Your method to set the text of that label is called setMyLabel. Either this is causing your outlet to not be connected when the nib is loaded, as the runtime may be trying to use that method to assign the label to your instance variable in the first place, or all of the above has no effect and you have just not connected your outlet.
Make sure you have an object in your code for the label, like this example:
IBOutlet UILabel* aLabel;
And in interface builder (you may have already done this): Connect the aLabel (or whatever name you use) outlet to the actual label. This can be done by control clicking and dragging from the File’s Owner object, in the document window, to the label, in the view. A small, gray window will appear with at least two options, one will be the aLabel defined earlier, and the other will be the view (this is a default outlet required for viewcontrollers, it will have a dash to indicate it is already connected to something). Click on the aLabel option to select it. (I'll be honest, without my mac in front of me I copied most of this paragraph's instructions from this link.)
You have an object called aLabel that you can now treat like any other variable. If you want to change the text value, try this:
aLable.text = #"some text";
Maybe you did not make the connection. Can you try the following?
#import "UIViewOverlay.h"
#implementation UIViewOverlay
- (void)showMyLabel:(NSString *) label {
NSLog(#"My current label contents (myLabel) = %#", myLabel.text); // ** changed to myLabel.text
}
#end
If you aren't able to print the original value, then you aren't connected.
I hope that helps.