Setting up layout/events on iPhone - iphone

I am using Open Source toolchain to compile my iPhone apps. So I have no Interface Builder or XCode. How would I setup the layout of widgets like UIButton, UITextView, etc. Also, how would I add an event handler to those UI widgets? Please remember that I don't have Interface Builder or XCode.

I suspect you're going to run into trouble eventually if you're not using Xcode. However, it is definitely possible to do everything iPhone without using Interface Builder. You just end up defining a lot of rectangles and pixel constants in your code, and calling (e.g.) addTarget to hook actions up to methods.
UIButton *myButton = [[UIButton alloc] initWithFrame:CGRectMake(MYBUTTON_X, MYBUTTON_Y, MYBUTTON_WIDTH, MYBUTTON_HEIGHT)];
[myButton addTarget:self action:#selector(foo) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:myButton];
[myButton release];
That creates a button and has it call your "foo" method when pushed. Anything that can be done in IB can be done in plain code (though it's often more tedious to do it that way.)

Related

iPhone the beginner's application [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 10 years ago.
Short pre-introduction to a problem:
I applied to a position of iOS developer. For this position they don't require knowledge of Objective-C or iOS development. The requisites are a good experience with C/C++ and development for Linux platform.
Problem:
After the end of interview I got a task (with words that it's easy to impelement, is it?) and I can't understand whether it's so.
Interviewer has showed me an application on his iPhone that looked like:
Pressing/dragging that button leads to appearance of such bar:
He could scroll it and drag on the screen. When he had pressed the control button, bar disappeared.
I want to ask for excuse in advance, because I feel myself like a person who wants his job to be done by others. But I just want understand how I can approach to this problem. Cocoa library is a big and a new beast to me. Which classes/elements from it is it better to use to reach this aim? I programmed before with Qt, Tkinter, WinAPI (gui programming) for desktop but it doesn't help me a lot here.
I need to code something similar like the interviewer has showed me. I tried to find something in the internet similar to this, but without success.
So, I just want to know for which classes it's better to look for in Cocoa library.
And, if I failed to take something into consideration I would be glad (happy) to hear your notes.
Thanks in advance for any replies!
SOLVED
I want to thank everyone who replied and didn't leave me to sink into this unknown sea.
After a week of exploring I got what I wanted:
Source code: (I apologize, but I can't copy-paste code from virtual mac os machine)
Now I understand how too-wide and silly is my question, but anyway perhaps it helps someone to start out. Also one book helped me a lot.
There is no required understanding of Objective-C, but the interviewer wants you to create a simple application and return it to him? Interesting interview.
As for your question. The classes I see being needed here (aside the AppDelegate and a UIViewController of your choice) are:
UIButton
UIScrollView
UIImageView
The button's use here is obvious. The scrollview is again obvious. The imageview would be the icons inside the scrollview.
Allright - just to give you some guidance on what to start with and how to proceed so that you don't get lost in the great wide world of cocoa ...
And assuming that you are familiar with programming and have some decent experience in the c++ and java worlds ...
Open xcode.
Go for blank view based app. Single view application would do. Go for Automatic Reference Counting (ARC).
xcode creates a template for you with an application delegate (which you would not need for this task)
A view controller is created and a xib/nib file for an iPhone view. (ignore the ipad view if any).
Add to your view controllers so called IBAction methods. One for the top button and one for the others. An action is supposed to be called when a button is pressed (and other events which you don't need).
Properly defined you will see that action in the interface builde when editing the xib file. Add a button and connect it with this action (touch up inside would be best I think).
Compile this. When your button is pressed the action is executed. Set a breakpoint there to make sure that it got called.
Now, in this action, you either call a newly created method showScroller and hideScroller. And create those methods.
Now it gets a bit more complicated.
In showScroller you would have to ...
create a UIScrollView. (alloc it and init it)
create a number of UIButtons. (no alloc withot its init in objective-c)
set your second IBAction method as target for the buttons.
Position the buttons within the UIScrollView accordingly.
Position the UIScrollView nicely under the top button.
add the UIButtons as subview to the contentview of the Scroll view.
add the scroll view as subview to self.view (that is the underlying view, the grey thing in the interface builder).
In hideScroller you would have to ...
remove the UIScrolView from the view. For that you could either remove all subviews from self.view or you would have to keep a reference to the scroll view within your view controller in some instance variable. Pretty similar to C++ and Java which you know already.
Alternative to the scenario described above you could create all views within interface builder and pre-define the scroll view as hidden in IB (interface builder) and in showScroller and hideScroller you would just have to set its .hidden property to YES or NO. But I've got a guts feelting that with your background you should and could do this programmatically instead of hasseling with how IB connects into your code.
In the event that you really run into that trap and don't get the top most button properly connected to your code, then create that button programmatically too.
Ah, I forgot. The right place to create all those UI elements would be the viewDidLoad method of the ViewController class. There is an empty one generated already in your empty xcode template. Just enance it following the [super viewDidLoad]; call.
Have a look at this:
http://www.cocoacontrols.com/platforms/ios/controls/aurosetteview
When you press a button, the items show up and when you press again, it closes.
The source code is within the library. Use it to read up.
For your case, you need to include the scrollview as well.
Here you go:
Open XCode and create a new project. Choose iOS Empty Application template.
Go to menu, choose File, New File, Objective-C class. Name it RootViewController and choose a subclass to be UIViewController
Go to your app delegate .m file (If your project name was Test, this file is TestAppDelegate.m). At the top of the file, below the line where it says #import "TestAppDelegate.h" add another line that says #import "RootViewController.h"
In the same file there is a method named:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
at the end of the method but before return YES; statement add the following line:
self.window.rootViewController = [[RootViewController alloc] init];
Now go to your RootViewController.m file that you created in the step 2. and at the top of the file edit the interface to have this one instance variable:
#interface RootViewController ()
{
UIView *menuView;
}
#end
In the same file locate the method named - (void)viewDidLoad and add the following code in it: - (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor =[UIColor blackColor];
UIButton *menuButton = [UIButton buttonWithType:UIButtonTypeCustom];
menuButton.frame = CGRectMake(100, 60, 50, 50);
[menuButton setBackgroundImage:[UIImage imageNamed:#"menu.png"] forState:UIControlStateNormal];
[menuButton addTarget:self action:#selector(menuButtonTapped:) forControlEvents:UIControlEventTouchDown];
CGRect menuFrame = CGRectMake(20, menuButton.frame.origin.y + 50, 300, 60);
menuView = [[UIView alloc] initWithFrame:menuFrame];
menuView.backgroundColor = [UIColor purpleColor];
menuView.hidden = YES;
UIButton *menuButtonA = [UIButton buttonWithType:UIButtonTypeRoundedRect];
menuButtonA.frame = CGRectMake(5, 5, 50, 50);
[menuButtonA setTitle:#"A" forState:UIControlStateNormal];
[menuView addSubview:menuButtonA];
UIButton *menuButtonB = [UIButton buttonWithType:UIButtonTypeRoundedRect];
menuButtonB.frame = CGRectMake(65, 5, 50, 50);
[menuButtonB setTitle:#"B" forState:UIControlStateNormal];
[menuView addSubview:menuButtonB];
UIButton *menuButtonC = [UIButton buttonWithType:UIButtonTypeRoundedRect];
menuButtonC.frame = CGRectMake(125, 5, 50, 50);
[menuButtonC setTitle:#"C" forState:UIControlStateNormal];
[menuView addSubview:menuButtonC];
UIButton *menuButtonD = [UIButton buttonWithType:UIButtonTypeRoundedRect];
menuButtonD.frame = CGRectMake(185, 5, 50, 50);
[menuButtonD setTitle:#"D" forState:UIControlStateNormal];
[menuView addSubview:menuButtonD];
UIButton *menuButtonE = [UIButton buttonWithType:UIButtonTypeRoundedRect];
menuButtonE.frame = CGRectMake(245, 5, 50, 50);
[menuButtonE setTitle:#"E" forState:UIControlStateNormal];
[menuView addSubview:menuButtonE];
[self.view addSubview:menuButton];
[self.view addSubview:menuView];
}
Below that method add a new method:- (void)menuButtonTapped:(id)sender
{
if (menuView.hidden)
menuView.hidden = NO;
else
menuView.hidden = YES;
}
Find some nice png image on the internet that will represent your menu button. Name it menu.png and drag and drop it in your project(inside the "file" menu on the left side)
That's it run the project ;)
just read the iphone's beginner book. you have to read some book first. first try to understand basic controls in iphone & basic manipulation in objective c
your above work is very basic.now just you are away from one step and that is read a book, you will get lots of free pdf on net

UIButton setImage not working

I'm losing my mind over this one. I have UIButton connected as Outlet. I want to change it's image. In the viewDidLoad function, I try to set the image like so:
[button1 setImage:[UIImage imageNamed:#"house.png"] forState:UIControlStateNormal];
Nothing happens. However, if I use ImagePicker, it somehow works. In the ImagePickers function "didFinishPickingImage", I repeat the exactly same command as above for setting image and it works, the image is displayed normally.
I've been thinking that maybe the button's image is not refreshing itself, but trying to call [button1 setNeedsDisplay], or [button1.imageView setNeedsDisplay] or even [button1.imageView.image setNeedsDisplay] does nothing.
Does anyone have any idea about this? I've wasted two hours by now and I'm really getting frustrated, because I'm certain that the reason must be so stupid it's unbelivable.
Please check your button type.
If your button type is "System" you should change it to "Custom"
Two things to do here:
#1, change your code to:
[button1 setImage:[UIImage imageNamed:#"house.png"] forState:UIControlStateNormal];
and #2
make sure your UIImage returns a valid image.
In other words,
UIImage * imageToSet = [UIImage imageNamed: #"house.png"];
if(imageToSet)
{
[button1 setImage:[UIImage imageNamed:#"house.png"] forState:UIControlStateNormal];
} else {
// if you see this line in your console, then you know where to look for a problem
NSLog( #"why is my image object nil?");
}
For anyone who will find themselves in a similar situation; I was using the mentioned button inside a custom cell for table view. However, the cells aren't loaded right away (i.e. inside viewDidLoad/viewWillAppear etc.), but inside the tableView:cellForRowAtIndexPath function. All my button variables were nil at that point. My solution was to load the image after the cell has been created and it has worked straight away afterwards.
Here are a couple additional notes. UIButton setImage: forState: is the correct method:
[button1 setImage:[UIImage imageNamed:#"house.png"] forState:UIControlStateNormal];
imageNamed is a great convenience method for grabbing the image, but make sure it returns an object. Forgetting to include the image file in the current target gets me all of the time.
[UIImage imageNamed:#"house.png"]
You also don't need the extension. The SDK works this out.
[UIImage imageNamed:#"house"]
And even though UIControlState is a bit mask, you cannot OR the values together. This does not not not work and I must must must remember this because it gets me every time I use the call.
// NO NO NO
[button1 setImage:[UIImage imageNamed:#"house"] forState:UIControlStateNormal|UIControlStateSelected];
// YES
[button1 setImage:[UIImage imageNamed:#"house"] forState:UIControlStateNormal];
[button1 setImage:[UIImage imageNamed:#"house"] forState:UIControlStateSelected];
Was getting the same problem when UIbutton was in UITableViewCell.
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setImage:[UIImage imageNamed:#"detail.png"] forState:UIControlStateNormal];
should work in UITableViewCell
Glad to know that the problem is solved but none of the answers actually addresses the problem.
Generally, if the code is correct, then the error shifts from "syntax error" to the "logical error" category. There is no definite guide to handle it but here is a small checklist that can help anyone to troubleshoot their code.
1) The IBOutlet is not connected or renamed.
2) Make sure that the UIButton type is custom.
3) The image is set (more than once), somewhere else in the code.
4) You are trying to set the Image through any sync method which is not using the main thread. (There are several threads on that alone).
5) If you are nesting the images as subviews, make sure the problem isn't with their parent view.
6) If it is appearing in Simulator but not in the device, It's a lettercase (Uppercase, lowercase difference in the code and the filename.
7) Modern simulators works with very low GPU memory on older machines. You can tweak the simlator options to make it appear. E.g (Command + Right Arrow) twice to change the simulator orientation and your changes will appear.
There are few other but common pitfalls where developers usually overlook
1) The image doesn't exist OR you are making a spelling mistake.
2) The filetype is different than mentioned. (JPG, PNG).
Last thing you'll want to check - make sure you're setting the image on the main thread! Just ran into an issue where I was setting a button image in a callback from ALAssetLibrary (fetching images from photo library). The image wouldn't update until I tapped the button. Turns out the callback was happening off main...
for those having issues with system images not appearing, just use systemName: instead of named
if let starImg = UIImage(systemName: "star.fill") {
button.setImage(starImg, for: .normal)
}
It's for ios13 and later...
For me it was to move the line:
[button1 setImage:[UIImage imageNamed:#"house.png"] forState:UIControlStateNormal];
from awakeFromNib method
to viewDidLoad method
I guess,
don't create like this
UIButton *nextButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
by this create method ,UIButton is create by use default type,so your background image is not work.
try this,
UIButton *nextButton = [[UIButton alloc] initWithFrame:CGRectMake(9, 154, 300, 48)];
or other,except buttonWithType
This is happening because the state of the Button doesn't stays selected once clicked by default.
I solved it by making an IBaction on that button click and toggling the selected state.
-(IBAction) checkButtonClicked:(id)sender{
checkButton.selected = !checkButton.selected;
}
In my case, it is drawn by custom animation code and not set by the image, so it doesn't work by setting any image, it has to change the animation code.
With images, you have to import them into the project not as references but as copies. So when you go to add files to project, choose "Create groups" instead of "Create folder references". Also make sure "Copy items if needed" is checked.
This is confusing because importing as references works when you are using images as textures (e.g. for Sprites). However, it doesn't work when you want to use images for buttons (e.g. for using image name in [UIImage imageNamed:#"house.png"]
I faced this same issue of the image not being shown on the UIButton.
I had to change this line -
myButton.setImage(<my_UIImage_object>, for: [.normal, .focused])
to this -
myButton.setImage(<my_UIImage_object>, for: .normal)

Detecting when a custom UIButton has been pressed

I have created a custom UIButton (UIButton subclass) for my application. Within this button's implementation, how would I alter the background color when it is pressed? (It should revert to it's normal background when depressed. I am currently using Core Graphics to draw a gradient background.)
I have tried branching in drawRect: (checking for self.selected and self.highlighted, but no change occurs because drawRect is not being called on the touch event.
Any suggestions or code samples are appreciated.
Try calling [self setNeedsRedraw] in your touch event.
Asker provided a solution based on this answer and the comments below.
Solution
Used:
[self addTarget:self action:#selector(buttonPressed) forControlEvents:UIControlEventTouchDown];
[self addTarget:self action:#selector(buttonDepressed) forControlEvents:UIControlEventTouchUpInside | UIControlEventTouchUpOutside | UIControlEventTouchCancel];
Where the selectors are custom functions that perform the background change.

Two Problems I'm having with UIButton and UIView

I haven't been programming on the iPhone for very long, but I'm picking it up slowly by googling problems I get. Unfortunately I haven't been able to find an answer for these.
I have started a new View-based application in Xcode 3.2.2 and immediately added the following files: myUIView.m and myUIView.h, which are subclasses of UIView. In Interface Builder, I set the subclass of the default UIView to be myUIView.
I made a button in the drawRect method.
Problem one: The title of the button only appears AFTER I click the screen, why?
Problem two: I want the button to produce the modalview - is this possible?
The code is as follow:
#import "myUIView.h"
#implementation myUIView
- (void)drawRect:(CGRect)rect {
// Drawing code
button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.frame = CGRectMake(0,0,100,100);
[button setTitle:#"butty" forState:UIControlStateNormal];
[button addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:button];
}
-(void)buttonPressed:(id)sender{
NSLog(#"Button pressed");
//present modal view somehow..?
}
I can't see how to post attachments, but if anyone thinks it will help I can upload the source.
Many thanks,
Andy
drawRect: is for custom drawing. You won't often need to do that. Your button won't be drawn until it gets sent drawRect:, probably in the next iteration of the run loop (ie, when you click on the view).
If you want a button on your view, either drag it there using IB, or move the code from drawRect: to viewDidLoad.
You present a modal view from a view controller by:
[self presentModalViewController:viewController animated:YES];
Do this in the action method your button sends to your view controller. This should indicate to you that you need to take a look at your application design.

iPhone + UIControls

It is a very generic question (not related to any application). Just my quest to know more.
While creating any iPhone application, we see that there few UIControls available in Library of Interface Builder. Using those we can create all basic application and designs, and also we can't customize those to much extent
But if we see on App Store, thousands of applications are available, where there many UIControls which are either not available in Library or might be they customized to much extent.
I want to know that:
Can we use controls other than available in Library (if yes than how and from where to get that).
If we can't than how do we modify (customize) the available UIControls to such an extent that they look totally different from their original primary look.
Regards,
Pratik
For a start, it is possible to set an image (including transparency) for most controllers. Many controller that look like different controls may actually be the same controls, just reskinned. Many controllers allow subviews - it is amazing how much can be achieved just using the table controller.
It is also worth knowing that any control you place using the GUI can also be set to a subclass where you override behaviour. Simply select the control, hit Shift-Apple i and change the class in Class Identity.
For customised controllers you can check the Three20 Project by Joe Hewitt.
take a look at the three20 library. It include custom styled button, labels and text. It should give you the general idea, how to customize your own UI elements.
Often, you don't use images like casebash mentioned, instead your drawing your elements with graphical methods.
Another possible solution is to override your
- (void)drawRect:(CGRect)rect
of your UIView
Edit:
Source Code taken from
Custom UIButton for Iphone
INDEX_OFFSET = 82753; // random
UIButton *sampleButton = [UIButton buttonWithType:UIButtonTypeCustom];
[sampleButton setFrame:CGRectMake(kLeftMargin, 10, self.view.bounds.size.width - kLeftMargin - kRightMargin, 52)];
[sampleButton setTitle:#"Button Title" forState:UIControlStateNormal];
[sampleButton setFont:[UIFont boldSystemFontOfSize:20]];
[sampleButton setTag:<INDEX>+INDEX_OFFSET];
[sampleButton setBackgroundImage:[[UIImage imageNamed:#"redButton.png"] stretchableImageWithLeftCapWidth:10.0 topCapHeight:0.0] forState:UIControlStateNormal];
[sampleButton addTarget:self action:#selector(buttonPressed) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:sampleButton];