I am trying to get started with UI programming in iOS, my first mobile application I mainly used story boards so going forward I would like my UI's to be more flexible. I have followed a couple tutorials online, word for word and line by line, I still can not get my views and subviews to show up when running the Xcode Simulator. I created a Single View Application with one viewController. Here is my code in my "ViewController.h" and "ViewController.m" file. What am I doing wrong here folks? My simulator is not displaying anything and according to the tutorials I have been following it should be.
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#property(strong, nonatomic) UILabel *label1;
#property(strong, nonatomic) UIButton *someButton;
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// Create the label
self.label1 = [[UILabel alloc] initWithFrame:CGRectMake(10, 10, 200, 25)];
self.label1.text = #"I am a label";
// Create the button
self.someButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
self.someButton.frame = CGRectMake(10, 50, 100, 37);
[self.someButton setTitle:#"Example Button" forState:UIControlStateNormal];
// Add them to the main view
[self.view addSubview:self.label1];
[self.view addSubview:self.someButton];
}
#end
Create a new project without the storyboard and put following code, it will work..
UILabel *testLabel;
testLabel=[[UILabel alloc]init];
testLabel.text=#"Hello World!";
testLabel.frame = CGRectMake(10, 50, 100, 37);
[self.view addSubview:testLabel];
Well your code is working fine in my xcode i created new single view based application and deleted the storyboard and copy pasted your code
When you programmatically create a UIView, UIButton or UILable, there aren't any layout constraints defined. You have to add them manually. If you do have some layoutconstraints configured for a certain view, they can be removed like so:
[view removeConstraints:view.constraints]
Make sure you are showing the ViewController first.
Related
How can I add padding to the UIlabel text that created programmatically?
NSArray *collectionViewArrayTitle = _titleArray[collectionView.index];
NSString *title= collectionViewArrayTitle[indexPath.item];
newslabel =[[UILabel alloc] initWithFrame:CGRectMake(0, 80, 130, 50)];
_newslabel.textColor=[UIColor whiteColor];
_newslabel.backgroundColor=[UIColor blackColor] ;
_newslabel.alpha=1.0f;
_newslabel.text=title;
_newslabel.tag=collectionView.index;
_newslabel.lineBreakMode=NSLineBreakByTruncatingTail;
_newslabel.numberOfLines=4;
The best way to add 'padding' to your labels is to make a subclass of UILabel and add the edgeInsets property.
CustomLabel.h
#import <UIKit/UIKit.h>
#interface CustomLabel : UILabel
#property (nonatomic, assign) UIEdgeInsets edgeInsets;
#end
CustomLabel.m
#import "CustomLabel.h"
#implementation CustomLabel
- (id)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if (self) {
self.edgeInsets = UIEdgeInsetsMake(0, 10, 0, 0); //customize padding here
}
return self;
}
- (void)drawTextInRect:(CGRect)rect {
[super drawTextInRect:UIEdgeInsetsInsetRect(rect, self.edgeInsets)];
}
#end
Another way of adding padding is to use a second layer. This may be a lot easier to accomplish but is imo not the most clean way to deal with it. You can add a UIView with the size of the label and then adjust that frame with some padding. Then you can add the intended UILabel to this view and play with the origins to get the right padding this way.
NSLayoutConstrains are Obj-C objects. You can also create them programatically. Or you can also create them in the Storyboard and drag an outlet to your controller and manipulate them on code.
On code you can handle that with the NSConstrain class or you can use the VFL (visual format language). In any case, check Apple's documentation for it. Once you get the handle of it, it's quite straightforward.
iOS newb here but after some googling and tutorial watching I can't seem to figure out where I've messed up. I'll try to provide as much info as possible, I've code monkeyed some code for the UIMotionEffect in my UIViewController subclass (root controller). My storyboard contains a UIViewcontroller subclass (below) with a view that contains a UIImageView that is the IBOutlet in the code. Everything runs and my debugger hits the viewDidLoad: method but moving my phone around doesn't move the image at all. Any help would be appreciated! Thanks for reading.
- (void)viewDidLoad
{
[super viewDidLoad];
CGFloat leftRightMin = -55.0f;
CGFloat leftRightMax = 55.0f;
UIInterpolatingMotionEffect *leftRight = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:#"center.x" type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis];
leftRight.minimumRelativeValue = #(leftRightMin);
leftRight.maximumRelativeValue = #(leftRightMax);
UIMotionEffectGroup *moGroup = [[UIMotionEffectGroup alloc] init];
moGroup.motionEffects = #[leftRight];
[bgImageView addMotionEffect:moGroup];
}
In my header file for the same class...
#interface TabletMenuViewController : UIViewController
#property (weak, nonatomic) IBOutlet UIImageView *bgImageView;
#end
Ahah, per the release notes the parallax and some other similar features aren't available on the iPhone 4. Looks like my dev phone is too old and busted.
I want to make an Advertising banner in my app. A bit like iAd's.
I was going to make it by having a UIImage on the view then assigning the banner image. I would then add a touch gesture so the user could click it and go to another view in my app. I Know That I can do this on one view quite easily but I want this to be on most views in the app. Whats the best way for adding the banner to more than one view with out writing the same code more that once?
The below design shows the sort of banner im after.
Thanks
#import <UIKit/UIKit.h>
#class custom;
#protocol adDelegate
- (void)viewAd:(NSString *)adRate;
#end
#interface custom : UIView
#property (strong, nonatomic) UIImage *viewImage;
#property (assign) id <adDelegate> delegate;
#end
// Main class
#import "custom.h"
#implementation custom
#synthesize viewImage;
#synthesize delegate;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
UIImageView *imageView = [[UIImageView alloc] initWithFrame:frame];
imageView.image = viewImage;
[self addSubview:imageView];
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
if ((self = [super initWithCoder:aDecoder]))
{
}
return self;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self.delegate viewAd:#"view"];
}
You can Create a UIView Class and call it BannerView for instance.
// in the bannerView.h
#import <UIKit/UIKit.h>
#interface BannerView : UIView{
UIImageView* bannerImage;
}
#property(nonatomic,retain) UIImageView* bannerImage;
#end
//in the bannerView.m
#import "BannerView.h"
#implementation BannerView
#synthesize bannerImage;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
bannerImage=[[UIImageView alloc]initWithImage:[UIImage imageNamed:#"banner-image.png"]];
bannerImage.frame=CGRectMake(0, 0, 320, 100);
[self addSubview:bannerImage];
// add a uibutton on top of the uiimageview and assign an action for it
// better than creating an action recogniser
UIButton* actionButton=[UIButton buttonWithType:UIButtonTypeCustom];
actionButton.frame=CGRectMake(0, 0, 320, 100);
[actionButton addTarget:self action:#selector(yourAction) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:actionButton];
}
-(void) yourAction{
// do what ever here like going to an other uiviewController as you mentionned
}
#end
Now you can call this view from any View Controller this way
BannerView* banner=[[BannerView alloc] initWithFrame:CGRectMake(0, 300, 320, 100)];
[self.view addSubview:banner];
Try creating a parent class from UIView where you do all the display and handling of the banner using your UIImageView and gesture recognizers. Then whichever views need this functionality, derive them from this parent class, and override default handling in method so that you can customize the behavior in your child class.
A few suggestions:
First, why not just use a UIButton instead of a UIImage with a Gesture? All you're really doing is replicating button functionality after all...
Second, I'd probably tackle the overall problem by creating a class that includes the UIButton, like so:
#interface YourSuperViewController : UIViewController
#property (nonatomic, strong) IBOutlet UIButton *adButton;
- (IBAction)adTouched:(id)sender;
#end
In the viewDidLoad for this class, create the button, and add it to the view, and add your ad-specific logic to the adTouched action.
Then create the rest of the views in your app as an instance of YourSuperViewController. Like so:
#interface SomeOtherViewController : YourSuperViewController
Now the SomeOtherViewController will auto-magically have the ad button and respond to a touch on it properly. Done!
What everyone else has said is the best way. If you need custom functionality, subclassing is probably the way to go.
I just wanted to add one pedantic thing. Its important to remember that a UIImage is not a view. There has never been a UIImage on the screen, ever. A UIImage is a model object. It is just a collection of data. A UIImageView is a view object and as such, a UIImageView can display itself on the screen.
This might seem overly pedantic and nitpicky, but its important to have these things sorted out in our heads in order to effectively use MVC (model, view, controller)
having a little issue in an ARC environment. Creating an NSObject that adds a view to a parent view - it's basically a 'popup class' that can handle some text and display it.
In a view controller it's instantiated..
CBHintPopup *popup = [[CBHintPopup alloc]init];
[popup showPopupWithText:#"test text" inView:self.view];
And the actual class files..
CBHintPopup.h
#interface CBHintPopup : NSObject {
}
-(void)showPopupWithText:(NSString *)text inView:(UIView *)view;
-(IBAction)closePopup;
#property (nonatomic, strong) UIView *popupView;
#property (nonatomic, strong) UIImageView *blackImageView;
#property (nonatomic, strong) UIButton *closeButton;
#end
CBHintPopup.m
#implementation CBHintPopup
#synthesize popupView,blackImageView, closeButton;
-(void)showPopupWithText:(NSString *)text inView:(UIView *)view {
//CREATE CONTAINER VIEW
self.popupView = [[UIView alloc]initWithFrame:CGRectMake((view.frame.size.width/2)-(225/2),-146,225,146)];
self.popupView.alpha = 0;
self.popupView.backgroundColor = [UIColor clearColor];
//CREATE AND ADD BACKGROUND
UIImageView *popupBackground = [[UIImageView alloc]initWithFrame:CGRectMake(0,0,225,146)];
popupBackground.image = [UIImage imageNamed:#"hintbackground.png"];
[self.popupView addSubview:popupBackground];
//CREATE AND ADD BUTTON
self.closeButton = [UIButton buttonWithType:UIButtonTypeCustom];
[self.closeButton addTarget:self action:#selector(closePopup) forControlEvents:UIControlEventTouchUpInside];
[self.popupView addSubview:self.closeButton];
//CREATE AND ADD LABEL
UILabel *popupTextLabel = [[UILabel alloc]initWithFrame:CGRectMake(22,25,176,93)];
popupTextLabel.text = text;
[self.popupView addSubview:popupTextLabel];
[view addSubview:self.popupView];
}
-(void)closePopup {
NSLog(#"HI");
}
Recieving the following once closePopup is called via pressing the button ('HI' is not printed)..
-[CBHintPopup performSelector:withObject:withObject:]: message sent to deallocated instance 0x246b2fe0
I've tried retaining the button in non-ARC and a load of other methods but simply having no luck. Probably something real simple but i can't nail it. I've removed all the setting up of the labels and images etc to save some space, so ignore alpha's etc.
Any help will be much appreciated, thanks for your time.
Have you implemented the constructor for CBHintPopup,since you have called the constructor
[[CBHintPopup alloc]init];
you have to implement the constructor method like this
in .m file of CBHintPopup
-(id)init{
if(self == [super init]){
// do some initialization here
}
return self;
}
I tried your code and found the crash you mentioned. I found a solution for fixing the crash.
I declared the CBHintPopup *popup; in the viewController's interface. And changed this line
CBHintPopup *popup = [[CBHintPopup alloc]init];
to
popup = [[CBHintPopup alloc]init];
Everything worked fine for me. But I couldn't find the reason behind this. Hope this will help you.
Found a fix for it - instead of CBHintPopup being an NSObject, i simply made it a sub-class of UIView and added self to the parent view (instead of self.popupView). I wouldn't really call this a 'fix' though - more of an alternative method. Surely an NSObject can add a UIView (with a UIBUtton) to a parent view with no problems? Is this a bug?
Make sure you are retaining the object for class CBHintPopup.
I think the crash is coming because object of CBHintPopup deallocates. And hence the action method is not found.
I'd like to be able to create new UI elements (a UIProgressView bar) in a separate UIViewController every time a user taps on a button.
How would I go about doing this?
To create a UIProgressView programmatically, it is simply a matter of using alloc and init, setting a frame, and adding a subview, like so:
//.h
#import <UIKit/UIKit.h>
#interface ExampleViewController : UIViewController {
//create the ivar
UIProgressView *_progressView;
}
/*I like to back up my iVars with properties. If you aren't using ARC, use retain instead of strong*/
#property (nonatomic, strong) UIProgressView *progressView;
#end
//.m
#implementation
#synthesize progressView = _progressView;
-(void)viewDidLoad {
/* it isn't necessary to create the progressView here, after all you could call this code from any method you wanted to and it would still work*/
//allocate and initialize the progressView with the bar style
self.progressView = [[UIProgressView alloc]initWithProgressViewStyle:UIProgressViewStyleBar];
//add the progressView to our main view.
[self.view addSubview: self.progressView];
//if you ever want to remove it, call [self.progressView removeFromSuperView];
}
Read this guide https://developer.apple.com/library/ios/#DOCUMENTATION/WindowsViews/Conceptual/ViewPG_iPhoneOS/CreatingViews/CreatingViews.html
Most of the UI elements create like this:
UIView *view = [[UIView alloc] initWithFrame:CGRect];
// set the property of the view here
// ...
// finally add your view
[ViewController.view addSubView:view];