I am a new in iOS Development and I canĀ“t move forwards... Is here somebody with experience, who can help me to solve my problem?
I use a Storyboard. First you see a ViewController with buttons. When you click on one of the button, informations about this button appear in a TableViewCell. - until now is it clear.
Than you click on a button "Continue" (than you come back to ViewController with buttons) and choose another button from ViewController.
HOW to do it, that informations from this button comes to a TableView as a second Cell? (so that when you click on for example three of the buttons, they appear as 3 cells under each other in this table?)
My Sample Code is here to download. - (on this website click on the smallest icon "Download").
Thank you very very much for your help!!!
Iva
You need a Model to store your selections/data.
For example: On MainViewController, when you click on button1, record that in the Model using array or just variable. Then, when you load SecondViewController, check the values in Model and load cells accordingly.
=> Example code for Model
// Header
#interface ModelData : NSObject
#property (nonatomic) NSMutableArray selectedProducts;
#property (nonatomic) NSInteger value1;
#property (nonatomic) NSInteger value2;
#property (nonatomic) NSInteger value3;
#end
// Implementation
#implementation ModelData
#synthesize selectedProducts = _selectedProducts;
#synthesize value1 = _value1;
#synthesize value2 = _value2;
#synthesize value3 = _value3;
#end
Various options:
Use NSUserDefaults to store information like settings
Use a Model class as described above - it could be a singleton class
Use CoreData to store and retrieve your data - complicated approach and suitable for dynamic things
Here is a reference to a good Data Model tutorial (reported by Iva)
Related
I have custom UIButton which programmatically interacts (triggers) with ViewController methods via protocol. But the behaviour of the button has to be dependent on the ViewController placed on. I do this to minimise amount of code in ViewControllers itself, as the button has to remain the same and bear the same functions (navigation).
Is there any way in UIButton's custom class to get the ViewController it is placed on?
I'd follow #rmaddy advice in a specific way, borrowing from the SDK's style
// MyCutomButton.h
#protocol MyCustomButtonDatasource;
#interface MyCustomButton : UIButton
#property(weak,nonatomic) IBOutlet id<MyCustomButtonDatasource>datasource;
// etc
#end
#protocol MyCustomButtonDatasource <NSObject>
#optional
- (NSString *)howShouldIBehave:(MyCustomButton *)button;
#end
Now the button can have it's datasource set in IB. View controllers that include it will need a little additional code (sorry, it's unavoidable in a good design). They will declare themselves as implementing MyCustomButtonDatasource.
When MyCustomButton needs to behave conditionally based on where it's placed, it can ask its datasource...
// MyCustomButton.m
NSString *string = #"defaultBehavior"; // per #RichardTopchiy's suggestion
if ([self.datasource respondsToSelector:#selector(howShouldIBehave:)])
string = [self.datasource howShouldIBehave:self];
// string is just made-up here, have it answer something simple (int, BOOL)
// that lets the button proceed with the right behavior. Don't ask for
// anything that relies on specific knowledge of how MyCustomButton
// is implemented
EDIT - To create the relationship, if you've decorated the property as an IBOutlet (as shown above), you should be able to setup the relationship in IB. Declare your view controller as implementing <MyCustomButtonDatasource>. Select your custom button, then the connections inspector, then drag to your view controller.
Alternatively, make the button itself an IBOutlet property in the view controller and, in viewDidLoad, do:
self.customButton.datasource = self;
The last way to do it is give your button a tag, say, 128, then:
MyCustomButton *customButton = (MyCustomButton *)[self.view viewWithTag:128];
self.customButton.datasource = self;
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
My View Controllers are holding my object properties and iVars etc. They shouldn't hold any at all.
** The rest of this post has been heavily edited for clarity as requested. **
My Class Object using the example given by NSBum that seeks to show data handled by one method, is able to continue being used in another.
#import <Foundation/Foundation.h>
#interface MYEmployee : NSObject
#property (nonatomic, strong) NSString *firstName;
#end
now for my VC interface file
#import <UIKit/UIKit.h>
#import "MYEmployee.h"
#interface MYEmployeeDetailViewController : UIViewController
#property ( nonatomic,strong) MYEmployee *employee; // as suggested
// UI elements
// a button that picks up from a textfield
- (IBAction)getName:(UIButton *)sender;
#property (strong, nonatomic) IBOutlet UITextField *inputField;
// a button that puts the names in a label
- (IBAction)showName:(UIButton *)sender;
#property (strong, nonatomic) IBOutlet UILabel *employeeNameLabel;
// a second label shows how i've been doing it so far
#property (strong, nonatomic) IBOutlet UILabel *contractorNameLabel;
#end
and the relevant essentials in my VC implementation file where i've used a private contractor property of the VC.
#import "MYEmployeeDetailViewController.h"
#interface MYEmployeeDetailViewController ()
#property (nonatomic, strong) NSString *contractor;
#end
#implementation MYEmployeeDetailViewController
// MYEmployee *employee; // use of an iVar has no effect
- (IBAction)getName:(UIButton *)sender {
// MYEmployee *employee = [[MYEmployee alloc] init]; // no effect except only within the method
// employee.firstName = self.inputField.text; //
self.employee.firstName = self.inputField.text; // class object picks up text from a textField
self.contractor = self.inputField.text; // self does exactly the same
}
- (IBAction)showName:(UIButton *)sender {
// MYEmployee *employee = [[MYEmployee alloc] init]; // resets contents of the iVar to nil
// self.employeeNameLabel.text = employee.firstName; //
self.employeeNameLabel.text = self.employee.firstName; // no joy using the property in .h file as suggested
self.contractorNameLabel.text = self.contractor; // this actually displays the text
}
#end
the employee is not to be seen while the contractor shows up for work (typical, we call them 'Blisters' they only show up when the work is done ;)
Back to serious stuff, the [alloc[init]] and iVar lines are commented out as they had no effect, but left in anyway for the sake of completeness. I didn't think I should edit the title, but my quandry is more or less the same in that "..why can't I use the model simply as a substitution of self?" After all, I outsourced the function
I might try to narrow the focus of the question somewhat; but I'll take a shot at what I think the issues are:
My View Controllers are holding my object properties and iVars etc.
They shouldn't hold any at all.
If you're following good MVC principles, then your view controllers should not have properties that would more correctly belong to the model layer. But given that view controllers are the conduit between the model and the view, certain exposed properties on the controller are essential.
Let's say you have a view controller that displays details about an employee - first name, last name, salary, department, etc. You'll probably want a model object that represents the employee. Let's call it MYEmployee. Next think about what other classes need to know about instances of MYEmployee. Those are the properties exposed in the class interface.
Now, how will our controller work with an instance of MYEmployee? Here, the view controller - let's call it MYEmployeeDetailViewController - needs to know what employee to display, so we need to expose the represented employee in the view controller's interface, e.g.
#property (nonatomic, strong) MYEmployee *employee;
Now MYEmployeeDetailViewController class users can pass an employee to display.
then how does one use Class Objects with the expectation i outlined?
I think your uncertainties revolve around questions like "who owns what data?" etc. My recommendation is to take a step back and really read the documentation on Apple's take on MVC and tap into some resources on object-oriented design. It always helps me to think first about interfaces (class interfaces, not UI) and less about implementation. Mapping out the relationships between classes before coding also helps.
You should be calling init on your new myClass object item instead of just alloc for starters. I doubt you really need to only allocate memory but not actually initialize the object.
Beyond that, your question is a bit hard to follow. You use objects to encapsulate data, and then you expose that data to other objects that might need it. Your view controllers will have objects that handle views, and objects that handle data. The controller will get what it needs from the data objects and pass it as needed to view objects. In this way, the controller will hold the data model itself (if you are doing a proper MVC design).
You say you want your class object to hold data between methods: well, that's what instance variables are for.
In my app I have a Done button.
Depending on which screen the user came from (namely a saved list screen or a new list screen) I'd like the Done button to use a different unwind segue.
Is this possible - if so how?
Thanks.
I am new to IOS, but as per my knowledge, the simplest thing you can do is to create macros in your AppDelegate with different states and set a property whose value will be set according to those states, so that you can perform segue depending on the current status of the property. You can do like this:
//in AppDelegate.h
#import <UIKit/UIKit.h>
#define SAVED_LIST_SCREEN 1
#define NEW_LIST_SCREEN 2
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (strong, nonatomic) int previousScreen;
#end
You can set the property "previousScreen" as SAVED_LIST_SCREEN or NEW_LIST_SCREEN depending on your current screen. And then you can check in "if codition" whether the previous state is Saved List or New List. And you can perform the segue operation accordingly.
if(app.previousScreen == SAVED_LIST_SCREEN)
{
//perform 1st segue
}
else
{
//perform 1st segue
}
Check it out and please let me know if it works.
So I have this little project in which the user goes from one view to another as they click buttons, and the text on the last button they've clicked should show up in a label in the top of the screen. I figured out how to have the variables accessible from anywhere in the app, and also how to change it as the user presses the buttons. Yet, I can only make the label's text change once a button is hit, and I wanted it to happen automatically (the view to appear with the label already containing the correct text).
For that I set the label in two different ways (which I found online):
#interface ViewMateria : UIViewController
{
IBOutlet UILabel *materiaLabel;
}
#end
and
#interface ViewMateria : UIViewController
#property (weak, nonatomic) IBOutput UILabel *materiaLabel;
#end
Still, for both of this I can not access the label by a simple materiaLabel.text or anything like that, and can't find a way to do it without the need for the press of a button.
I've been looking for an answer for this for a while now, and nothing that I found seemed to be of use for me (since most of the links I found taught how to change a label text with the press of a button).
This is my first project with Objective-C and Xcode, and I don't really know the answer, so maybe I am missing something quite obvious, but still, if anyone could point me in the right direction, that would be of much help.
Put this in your .h file for the view controller:
#property (weak, nonatomic) IBOutput UILabel *materiaLabel;
When you are about to present the view controller, access it like this:
your_ViewMateria_object.materiaLabel.text = #"";
Then present it..
Are you using segues?
If yes, its another story..
UPDATE:
For segues use this, with the .h property value I just mentioned:
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
ViewMateria *vm = [segue destinationViewController];
vm.materiaLabel.text = #"Whatever";
}
You should be good to go now ;D
Did it work?
UPDATE
In second view controller .h file
#property (strong, nonatomic) NSString *buttonName;
.m file
self.materiaLabel.text = self.buttonName;
In first view controller .m file
inside IBAction
secondviewcontrollerObject.buttonName = [(UIButton *)sender currentTitle];
I am not certain whether I need an IBAction for a UITableView, but what I am trying to do is have some sort of control that I can hide it during page load, and then populate its cells with data that I get from a remote server, and then display that UITableView.
How can I do that? When I currenly try to press control and drag the UITableView to the ViewController, it gives me optons of: dataSource or delegate. I chose dataSource, but then was not sure what to do next.
I tried to do something like this in the .h
#interface MyBusinessesController : UIViewController
- (IBAction)businessList:(id)sender;
#property (weak, nonatomic) IBOutlet UITableView *businessListProperty;
#end
and this in the .m
#import "MyBusinessesController.h"
#interface MyBusinessesController ()
#end
#implementation MyBusinessesController
#synthesize businessListProperty;
...
but it seems I am way off. What is the right way to do what I am trying to do?
Thank you!
If I understand your question correctly you want a UITableView to be hidden when the view loads and download some info from a server in the background then when all data is finished downloading display the table view? Why do you need an IBAction? In viewDidLoad set the "businessListProperty" table to hidden, self.businessListProperty.hidden=TRUE;
then use an NSURLConnection to download the info from the server and in connectionDidFinishLoading set the table view to whatever data you downloaded and then set its hidden value to false.
-(void)connectionDidFinishLoading:(NSURLConnection *)connection{
//set tableview to whatever you downloaded here
self.businessListProperty.hidden=FALSE;
}
-Shrdder2794