What's the best way to have a list of text items, tap on one and be able to edit it? How about going to a detail view? But then how do you get your change back into the UITableView?
I suppose this could all be done with SQL or CoreData but since the UITableView is based on an array, can we just edit that element of the array and reset the table view?
Eventually I want the data to be persistent so I'll probably go with CoreData or SQL but for now I just want to go from a list to details, edit the details, and go back to the list.
"But then how do you get your change back into the UITableView?"
Both the table view and the detail view should be accessing a common model object. In other words, the detail view that's changing data doesn't have to even know the table view exists.
Look up protocols. Basically you have a class that has information to share. In this case it will be your detail controller or some sort of data object as mentioned above. Have this class (with the info to share) declare a protocol that uses that information. The method should use parameters to sneak out your information. The class also declares a
id (less than)protocol(greater than) delegate
where "protocol" is what you declared above.
Now in this class when you obtain the information that you want to share (however you do it) send the delegate method message to your delegate. [delegate informationObtained:newInfo].
For the class or classes that need this information, implement the protocol method(s). The information you need is being passed by the parameters to the method. It's the same way you use TextFieldDelegate and UIPickerFieldDelegate, only you decide the protocol and you decide how to implement them. Here's a code example
In SpeakHereController.h
#protocol SpeakHereControllerDelegate
-(void)newSoundCreated:(NSString *)newSoundName savedFile:(BOOL)savedFile element: (id)element;
-(void)cancelNewSound;
-(void)soundEdited;
#end
in the interface:
id delegate;
don't forget the #property, make it (non atomic, assign)
In the implementation file,
once I have the information I want to share:
[self.delegate newSoundCreated:myFileName savedFile:self.savedFile element:self];
Now for the tableview controller that wants to use this information:
in the .h file declare that you are going to implement the protocol
#interface AlarmSoundsTableViewController : UITableViewController <SpeakHereControllerDelegate, UITableViewDataSource, UITableViewDelegate>
Then in the implementation file implement the method:
-(void)newSoundCreated:(NSString *)soundName savedFile:(BOOL)savedFile element:(id)element
{
[self setSoundFileName:soundName];
...
Related
Let's say I have a simple app that is loading data into a table view. It then allows you to view details (etc).
My table view controller on first load looks something like this below.
Notice I am not using an "property" declarations for these variables. Is this OK? Are there any disadvantages regarding the way memory is then handled?
#interface TblVC ()
{
MBProgressHUD *hudLoad; // new up loading while I go get data
NSMutableArray *results; // set to results after loading data
CLLocationManager *locManager; // get location in view load
}
#end
#implementation TblVC
{
}
- (void)viewDidLoad
{
// spin up the above variables here which can then be used in other methods inside view controller
}
Just use properties. There is absolutely no reason to use the old-style instance variables anymore.
Apple's documentation on properties goes into detail about the benefits. https://developer.apple.com/library/ios/documentation/cocoa/Conceptual/ProgrammingWithObjectiveC/EncapsulatingData/EncapsulatingData.html
An instance variable is unique to a class. By default, only the class and subclasses can access it. Therefore, as a fundamental principal of object-oriented programming, instance variables (ivars) are private—they are encapsulated by the class.
By contrast, a property is a public value that may or may not correspond to an instance variable. If you want to make an ivar public, you'd probably make a corresponding property. But at the same time, instance variables that you wish to keep private do not have corresponding properties, and so they cannot be accessed from outside of the class. You can also have a calculated property that does not correspond to an ivar…
Without a property, ivars can be kept hidden. In fact, unless an ivar is declared in a public header it is difficult to even determine that such an ivar exists.
A simple analogy would be a shrink-wrapped book. A property might be the title, author or hardcover vs. softcover. The "ivars" would be the actual contents of the book. You don't have access to the actual text until you own the book; you don't have access to the ivars unless you own the class.
In this app I'm working on, I use core data to store content. I populate the database in the AppDelegate's didFinishLaunchingWithOptionsmethod. And in the view controller, I'm extracting the required data using a NSFetchRequest.
My question is, is the code related to extracting data should be in the view controller? Or should I create separate methods in the NSManagedObject subclasses generated for those entities and call them from the view controller?
Can someone please shed some light on this?
Thank you.
You should create a model class, which means something like:
#interface DataImporter : NSObject
#property(nonatomic, readonly) CoreDataManager *coreDataManager;
- (id)initWithCoreDataManager:(CoreDataManager *)coreDataManager;
- (void)importDataWithCompletionCallback:(void (^)())completionBlock;
#end
It's not a NSManagedObject subclass, but it's an object responsible for importing data into your CoreData store. importDataWithCompletionCallback can e.g. create all necessary NSManagendObject objects (depending on some JSON) and save them, do it in background, call callback block after completion.
Subclassing NSManagendObject is not a good way to follow.
In my app I have a storyboard with two scenes. The first one is a Summary-View-Controller and just shows some data. But you can tap on it and switch to a Edit-View-Controller scene where you can make changes. To report the changes back to the Summary-View-Controller the Edit-View-Controller will get a reference to his parent. When editing is done he will call a method in his Parent-View-Controller.
The property in the Edit-View-Controller looks like that:
#property (weak, nonatomic) id <NameEditViewChangedProtocol> parentController;
My app works fine. That is not my problem. But in many tutorials I read a property like this is just called delegate.
#property (weak, nonatomic) id <NameEditViewChangedProtocol> delegate;
I know what delegation is and how it works but for me parentController is a more meaningful name. delegate, that could just be anything. So my question is: When should I call a property like this delegate? Are there any rule how to use this name?
I know what delegation is and how it works but for me parentController
is a more meaningful name. delegate, that could just be anything.
I think you've answered your own question here. A delegate is a helper object that "could just be anything" as far as the delegating class is concerned. The name parentController assumes something specific about the relationship between the two objects. If you know that that relationship will always exist, then it's appropriate to use that name. On the other hand, if the two objects only happen to have that relationship, but the relationship isn't important to the fact that one object is using the other as a helper, then use delegate (or something similar).
So, is it necessary that the objects in question have a parent/child relationship? Are you sending messages to parentViewController specifically because it's the parent? Or is it conceivable that some other object could respond to the same messages?
Usually names of properties of type id<some protocol> are the same as the last part of the protocol name, e.g. the 'delegate' property of a UITableView is a property of type id<UITableViewDelegate>, and the 'dataSource' property is of type id<UITableViewDataSource>. If you name your protocols by their purpose, the name of a property of type id<some protocol> should come naturally from the protocol name. For what it's worth, protocol names don't usually include the word 'Protocol'.
Andrew's answer about how to name the property could help you make a better name for the protocol as well, if you follow the protocol/property name correspondence which I explained.
Edit: Fix formatting throwing away <protocol names>
Call it a delegate when it will be used to make decisions at runtime about how the edit view controller should behave, or is to be notified of events, incoming data, etc. Call it delegate if the edit view controller is to be reused in multiple contexts, and the delegate's class can be anything (possibly conforming to a delegate protocol).
It may make sense to call it parentController if you know that the relationship between the two is always going to be a parent-child relationship with the parent 'owning' the child, rather than the more abstract delegate relationship.
I followed John Wordsworth tutorial (http://www.johnwordsworth.com/2011/10/adding-charts-to-your-iphone-ipad-app-using-core-plot/) to produce a line graph with CorePlot.
Later I decided to get some JSON data from a website so that I can use it for my graph.
All the url connection methods are performed in my ViewController.m file. And there I created an NSArray called indicator containing all the JSON data.
My problem is that all of the graph's parameters are defined in a separate NSObject class called SimpleScatterPlot.m where I would like to use the array of strings "indicator" (defined in ViewController.m) to customize the x-Axis labels.
What do I have to do so that I can use this JSON data array in SimpleScatterPlot.m?
I tried #import "ViewController.h" but it did not solve it.
Thanks in advance for any guidance you can give me.
Not sure if I am understanding it correctly, but I think you have not try to access the indicator nsarray from SimpleScatterView.m but to set there the value from ViewController.m.
1) Define a public NSArray in SimpleScatterView.m and synthesize it.
2) Instead of trying to gain access, use "prepareForSegue" in ViewControler.m to set indicator in the destinationSegueController.
3) In SimpleScatterView.m implement "-(void)setIndicator:(NSArray *)indicator" and update the GUI as needed.
Although the "Model - View - Controller" paradigm recommends not to use ViewControllers to perform communications and so on, but that is for another thread.
Create a property in Viewcontroller and synthesize it. Then pass the JSON data to the property.
To access the array in SimpleScatterView.m:
Viewcontroller *viewcontrol = [[ViewController alloc] init];
You can then access the array by using viewcontrol.indicator.
NSLog(#"%#",viewcontrol.indicator);
If I do not read incorrectly what you are trying to do, my guess is that you could appropriately use SimpleScatterView from within your UIViewController view (this is, assuming that SimpleScatterView is actually a UIView).
In this case, when your controller has downloaded its data, you could instantiate SimpleScatterView and display it by adding it to your view controller view.
... <data has been downloaded> ...
SimpleScatterView* scatterView = [[SimpleScatterView alloc] initWithFrame:...];
[self.view addSubview:scatterView];
When you initialize your SimpleScatterView, you could pass it a reference to the data array (say, in its custom init method, or using a property). e.g.:
SimpleScatterView* scatterView = [[SimpleScatterView alloc] initWithFrame:... andData:(NSArray*)...];
or:
scatterView.dataSet = <your_json_array>;
Of course, you have plenty of alternatives to this design. Specifically, I would mention:
the possibility of using a model class to handle all of your data, such that the controller writes the data to the model, while the plot view reads the data from it. The model could be implemented though a singleton in this case for ease of access;
the possibility of using a "dataSource" for your plot view: this would entail defining a protocol between the view and its datasource (e.g., a getData method); your view controller would play the role of the data source (in other words, instead of passing the array to the plot view as in above example, you would pass a reference to the controller and the view would access its data).
I understand what a delegate does in iOS, and I've looked at sample code, but I'm just wondering about the advantages of this type of encapsulation (as opposed to including delegate methods in the primary object).
The advantage of the delegate design pattern is loose coupling. It enables class A (the delegate) to depend on class B (the delegating class) without class B having to have any knowledge of class A. This ensures that the dependency relationship is one-way only, rather than being circular.
It also forms the foundation (lower case "f") of Apple's frameworks because it allows them to invoke your code as appropriate when functionality specific to your application is required. For example, responding to a button tap or telling a table view how many sections there should be.
Delegation is a design pattern not only used in iOS but many other languages. It enables you to hand values and messages over in your class hierarchy.
In iOS, delegation requires the "delegate" class to implement a protocol which contain methods that the "delegating" knows about. Still following?
The delegating class's implementation will call these protocol methods, but the delegate class will implement these methods in their class.
This keeps your Classes clean.
In reality, you don't really need delegation if you can add new methods to a single class. But for UIKIT's UIView class, Apple will not allow you to add new implementations to their class.
correct me if I'm wrong.
The most common use of a delegate in iOS is to establish communication within modules that are unrelated or partially related to each other. For example, passing data forward in a UINavigationController is very easy, we can just use segue. However, sending data backwards is little tricky. In this case, we can use delegate to send the data backward.
Let's call, the class, associated with the first Controller ClassA and the class, associated with the second Controller ClassB. The first Controller is connected to the second controller with a forward segue. We can pass data from ClassA to ClassB through this segue. Now, we need to pass some data to ClassA from ClassB for which we can use delegates.
The sender class(ClassB) needs to have a protocol in its header file(.h) and also a reference of it as delegate inside the block, #interface ClassB .... #end. This reference let's the ClassB know that it has a delegate. Any class that wants to use this ClassB will have to implement all of this protocol's required methods(if any). So, the receiver class,ClassA will implement the method but the call will be made by the sender class, ClassB.
This way, receiver class doesn't need to worry about the sender class' internal structure, and can receive the required information.
Delegation as I understand it is when an object will pass the responsibility of handeling an event to another object thus "delegating" the responsibility to that object.
For example if you have an NSButton in iOs you generally assign the Delegate to be the parent view controller. This means instead of handeling touchUp events in the definition of the button it is instead handled in the view controller.
The main advantage of delegation over simply implementing methods in the "primary object" (by which I assume you mean the object doing the delegating) is that delegation takes advantage of dynamic binding. At compile time, the class of the delegate object does not need to be known. For example, you might have a class that delegates the windowDidMove: method. In this class, you'd probably see some bit of code like
if([[self delegate] respondsToSelector:#selector(windowDidMove:)]) {
[[self delegate] windowDidMove:notification];
}
Here, the delegating class is checking at runtime whether its delegate responds to the given method selector. This illustrates a powerful concept: the delegating class doesn't need to know anything about the delegate other than whether it responds to certain methods. This is a powerful form of encapsulation, and it is arguably more flexible than the superclass-subclass relationship, since the delegator and the delegate are so loosely coupled. It is also preferable to simply implementing methods in the "primary object" (delegating object), since it allows runtime alteration of the method's implementation. It's also arguable that this dynamic runtime makes code inherently more dangerous.
Delegate is an important design pattern for iOS app.All apps directly or behind the hood use this delegate pattern.
Delegate design pattern allows an object to act on behalf of another.
If we are working with tableview then there are "tableViewDelegate" and "tableViewDataSource". But what this means
Suppose you have a tableview.
now some major concern for this.
1.what is the datasource(the data that will appear in table view) for this tableview?
2.How many row for table view etc.
delegate design pattern solve these question using another object as the provider or the solver of these question.
An object mark himself to the table view and ensure the table view that "Yes i am the man who can assist you" by marking himself as the delegate to the table view .Thanks
The class marked as delegate takes the responsibilities to handle the callbacks sent while some event occurs. For example, in case of UITextField, there are some methods called when some events occurs like editing started, editing ended, character typed etc. These methods will already be defined in the protocol. We will have to assign delegate for that i.e. which class is going to handle these events.
With the help of a delegate, two-way communication can be achieved. A delegate might be used to make an object reusable, to provide a flexible way to send messages, or to implement customization.
In iOS ecosystem especially UIKit Framework which consists of UIApplication, UITableView, UICollectionView, UITextfield & so on uses delegate & datasource design pattern intensively to communicate data to and fro.
Delegate design pattern is used to pass/communicate data from FirstVC(Delegator) to SecondVC(Delegate) to complete a task.
Here, SecondVC(Delegate) conforms to a protocol delegate & implements all its requirements like methods by providing body to complete that task given by FirstVC(Delegator).
Also, FirstVC(Delegator) object will be having a optional property of protocol delegate type i.e delegate which must be assigned by SecondVC(Delegate).
Now, FirstVC(Delegator) can call that method residing in SecondVC(Delegate) by passing data from its delegate property.
EX: CEO(FirstVC) which passes data i.e "confidential data" to Secretary(SecondVC) to do further processes using that data.
Datasource design pattern is part of Delegate pattern which is used to pass/communicate data from SecondVC(Delegate) to FirstVC(Delegator) when a task is assigned to SecondVC(Delegate).
Here, SecondVC(Delegate) conforms to a protocol datasource & implements all its requirements like methods with return type by providing body to talk back to FirstVC(Delegator) after the task is given by FirstVC(Delegator).
Also, FirstVC(Delegator) object will be having an optional property of protocol dataSource type i.e dataSource which must be assigned by SecondVC(Delegate).
Now, FirstVC(Delegator) can call that method with a return type residing in SecondVC(Delegate) by passing data from its dataSource property.
EX: Secretary(SecondVC) replies back with a data i.e "Sir, I am already having too much work to do. Please, can you assign that data to others" to CEO(FirstVC). Now, CEO(FirstVC) will analyse that data to do further processes.
Delegation means one object passes behaviour to another object..