I'm basically an Android programmer and on my way to learning some skills on iOS platform.
I have an Android application, which has a custom UI component which looks like
.
I want to create a similar re-usable UI component for my sample iOS application. I'm not able to get any lead on how to do this in iOS.
On Android I can create a composite UI element using a layout file but in iOS i'm not sure if i can create a composite UI element or extend UIView and then somehow layout Text and image components inside it.
I'm looking for some leads on implementing this. I plan to have a multiple instances of these component on screen & the values gets updated from a web service.
I recommend something called interface builder in iOS.
It is a place where you can visually place elements that the user interacts with and you can see how the design looks as you layout your structure.
For tutorials, you can look at http://mobile.tutsplus.com/tutorials/iphone/interface-builder/
or search up "ios xib tutorial"
Hope this helped!
If you want it to be a simple view, then you could create a UIView sub-class with a few UITextFields's and probably an UIImageView or two that all have outlets so that your controller can make changes to it. For instance:
#interface StockInfo <UIView>
#property (nonatomic, strong, readonly) UITextField *ticker;
// You may want to make these numbers so that you can do calculations with them, and then update the text field automatically
#property (nonatomic, strong, readonly) UITextField *price;
#property (nonatomic, strong, readonly) UITextField *priceChange;
// This could be automatically calculated based on the price and priceChange if appropriate
// It could also automatically show the Up or Down indicator
#property (nonatomic, strong, readonly) UITextField *percentChange;
#end
Then, your controller could create an instance and set the various properties:
StockInfo *djia = [[StockInfo alloc] init];
djia.ticker = #"DJIA";
djia.price = #"14550.35" ;
djia.priceChange = #"-111.66";
// ...
You can create the actual UI elements within the view either in Interface Builder, or do it in code. Which to do is kind of a personal preference. There are plusses and minuses to both, and building the view in code in this case would be pretty easy and not require you to have two files in order to use the control.
Related
There are at least 3 methods of creating an IBOutlet in Objective-C, for making iOS 10 App, in Xcode 8.
Method 1: in ViewController.h
#interface ViewController : UIViewController
#property (nonatomic, strong) UILabel *textLabel;
#end
Method 2: in the interface of ViewController.m
#interface ViewController () {
IBOutlet UILabel *textLabel;
}
#end
Method 3: in the interface of ViewController.m, using #property
#interface ViewController ()
#property (nonatomic, strong) UILabel *textLabel;
#end
Given that the textLabel has to be accessed & its text is needed to be updated frequently, which method is the correct way to do so?
That all depends on whether you need your outlet to be accessible to classes outside of the containing one; generally I would discourage this because it is good practice to keep your view controllers responsible for updating your UI and not pass this task around to other classes. With this being said, Method 3 would be the best option, however, if you do have to access your object from another class, then simply use Method 1 so it is exposed in your class header.
Method 2 utilises iVars rather than object properties and is not the proper way to declare outlets, it may even cause unexpected behaviour so it is best to avoid this method.
Your code contains no proper IBOutlet. Outlets are connections to Storyboard.
Method 1
This is a property. As it is in .h file, it can be reached from outside. The Objective-C pattern for public.
Method 2
This is an iVar. Do not use iVars if you do not have to.
Method 3
This is a property. As it is in .m file, it can not be reached from outside. The Objective-C pattern for private.
Method 4
A proper IBOutlet looks like this:
#interface ViewController ()
#property (nonatomic, weak) IBOutlet UILabel *label;
#end
It is a simple property. You have to decide if you put it in .h or .m file depending on whether or not you want to publish it.
The IBOutlet simply makes the property connect-able to Storyboard. It's an annotation for Xcode and does not alter the semantic of your code.
Edit 1:
As Sulthan correctly mentions in the comments:
In most situations the correct design pattern is to hide outlets because it's an implementation detail. External classes should not set data directly using views.
Edit 2:
Why "not to use iVars if you do not have to" (2)
Opinion based:
I consider it as good OOP practice to use getters & setters (and thus not to access the variables directly). Also code is easier to read as you know while reading what x = self.variable (property) and x = variable (local variable) are.
If you have to use iVars for some reason, it is common to (and I would recommend to) prefix the name with _. x = _variable (iVar).
as i see the answer Visit IBOutlet and IBAction
the highest voted answer said “If you're not going to be using Interface Builder at all, then you don't need them in your code”
i fill confused when i see somebody's code like this
#import <UIKit/UIKit.h>
#interface ParallaxHeaderView : UIView
#property (nonatomic) IBOutlet UILabel *headerTitleLabel;
#property (nonatomic) IBOutlet UIImageView *headerImageView;
#end
are there any tips beyond my shallow knowledge?
Sometimes when the code might be used in other projects, the developer will provide the ability for the end user to choose the default programmatic interface, or design her own interface in IB.
Since distinct initialization methods (initWithFrame:, initWithCoder: etc..) will be triggered based on whether the code is called programmatically or through IB, one can provide such options.
But I agree that it's a rather special use case.
I'm trying to create an iPad/iPhone app that dynamically creates menus depending on a JSON object that is returned from a RESTful API. Specifically I'm trying to show/hide a UIPickerView that I created using the interface builder. In the properties menu in the interface builder I checked the box "hidden" for that UIPickerView. I used this tutorial to create to UIPickerView. I've set the delegate and data source to the View Controller using the interface builder. I'd like to unhide/show the UIPickerView when a certain condition is met. So far I've tried the following code:
[self.choicePicker setHidden:NO];
self.choicePicker.hidden = NO;
I usually build such object programmatically but I thought I'd try it this way. I've looking through various stackoverflow posts and doing research but I can't seem to find something that works. I'm new to programming in Objective C. Thanks in advance any help is greatly appreciated.
.h file code
#interface slrpViewController : UIViewController<UITextFieldDelegate, UIPickerViewDelegate, UIPickerViewDataSource>
{
IBOutlet UIPickerView *picker_choice;
NSMutableArray *dataArray;
NSMutableData *receivedData;
}
#property(nonatomic, strong) UILabel *nameLabel;
#property(nonatomic, retain) UIPickerView *choicePicker;
.m file code
-(void)buildChoicesMenu:(NSDictionary *)choiceDict{
//in this method we build the choices menu
[self.choicePicker setHidden:NO];
self.choicePicker.hidden = NO;
if (self.choicePicker) self.choicePicker.hidden = !self.choicePicker.hidden;
}
You have two different picker views defined. One a property choicePicker (and an implicit _choicePicker instance variable), and another instance variable picker_choice. It seems you have connected your picker_choice in interface builder, but are trying to modify the property. In fact, if you try to print po self.choicePicker in the debugger, you would get nil, because there is nothing filling it.
Either remove the instance variable, and connect your property in interface builder, or synthesize your property with your instance variable by doing so:
#syntesize choicePicker=picker_choice
I've got a handful of UIViews subclasses as a part of my interface and I'm looking for an easy human readable way to differentiate them in the code -- like the label you set in the "Document" section of the UI editor.
I believe the "Accessibility Label" is exposed, but that doesn't seem like the correct use of that variable.
Am I stuck documenting which Object ID each object has or is there a more intelligible way?
There are lots of ways to do what you want to be done. Here are several of them:
#properties
The first thing that came to my mind are properties. Use your view controller as a storage class by adding following property declarations in your header file:
#property (nonatomic, weak) IBOutlet UIView *myFantasticView;
#property (nonatomic, weak) IBOutlet UIView *myGorgeousView;
...
Then, just simply connect your views to specific outlets in Interface Builder.
The only drawback is that you will have to declare a lot of properties which can become a little confusing.
Custom runtime attributes (another use of #properties)
If you're using UIView's subclasses (I assume you do), you can use your UIView subclass and declare an "identifier" property:
#interface MyView : UIView
#property (nonatomic, strong) NSString *myViewID;
...
#end
Then, assign this value using code (simple property setting) or in Interface Builder:
Now you can identify your views using one of those method. But remember that you can come up with a better, more suitable solution! :)
How can I control the number of multiple UITableView's at build-time, using a single #define number?
My app presently needs 4 UITableView's. Later, the number will increase, so I want to control this at build-time with a single #define of how many.
But I get an error when I use an array in the #property declaration:
#define TOTAL_TX_CHANNELS 4
#interface blah() <UITableViewDataSource, UITableViewDelegate CBPeripheralDelegate>
{
}
#property (strong, nonatomic) UITableView* channel_tableView[ TOTAL_TX_CHANNELS ] ;
What's the trick? Should I use an NSArray or something?
Yes, use NSArray.
If it's configured in Interface Builder you could use:
#property (weak, nonatomic) IBOutletCollection (UITableView) NSArray * tableViews;
Why exactly do you need to control the # of UITableViews?
If you must do this, you could do some mathematical operation.
int adder = 4;
int currentNumberOfTvs = 4;
//Do some logic, that will add the number of current table views
if (...) //Test if user has added, or however, if another table view was added,
{
adder++;//now adder = 5. So you have a current count of how many table views there are
}
Hope that helps:)
I agree with the others that this is a terrible implementation. Wain's answer is very good.
However, still it is possible to implement it this way, just make sure to declare the property as
#property (assign, nonatomic) UITableView** channel_tableView;
Reference counting works only on Obj-C objects but you are creating a C array here.
Note that you have to use malloc to allocate the storage.
If you don't want to malloc, implement it as an ivar:
#interface Blah {
UITableView* channel_tableView[4];
}
#end
The solution was not to use an a property array, but to use an UITextView array at implementation scope, the .m...
UITextView* channel_pipe_textview[ TOTAL_TX_CHANNELS ];
Then, in function viewDidLayoutSubviews I created a UITableView for each channel, and added the standard functions for initializing the cells, all by following Apple's excellent UITableView programming guide.
It worked perfectly, completely independent of storyboard: I get four vertical side-by-side columns displaying any kind of images and text details regarding every device on the channel, with the ability to scroll, which allows any number of devices per channel.
The Apple UITableView Programming Guide also has tutorial and sample code for programmatically generating UITableViews solely at run-time.