I am started learning objective c again, and I am trying to access a variable from my main view controller in my NSObject class.
How would I do that?
For example I have declared
UITextField *name;
and I want to use it in my NSObject.
The best practise would be implement delegate pattern here. Suppose you want to change the value/content of UITextField, then fire the delegate with the value. And in ViewController class, set the delegate and implement that delegate method. In that delegate method, update value/content of UITextField.
One more thing, Please make sure to update UITextField's content/value in main thread. UI related changes should be always done in main thread.
You can refer to the NSObject class via a method with the plus sign '+' +(type)anyMethod; to get the variable. If I correctly understood what you mean
Related
I think the solution to this is going to need to use delegation, but I'm unfamiliar with how to use them.
So in my project, I have my main viewcontroller/storyboard that contains a UIScrollView. That UIScrollview calls another storyboard (xib file) as a subview. The other storyboard (which is an xib file) is controlled with another swift file.
My question is, when I call an action inside of my other storyboard, how can I call a function from the main viewcontroller. Like say the viewdidload from the first viewcontroller.
I can't make the whole thing a global function, it needs to stay inside its class. So if I try to do ViewController.viewDidLoad() it needs (I think) an instance variable or something.
Thanks.
You can try:
Using weak variable (property) in the other class with type UIViewController
Assign the parent view controller to that property after the other view is initialized
Good reads about weak, strong, unowned references Here And Here
Firstly, if you want to call it with class name as you said above declare your method with "class". So its just like static in Java. It makes it generic to call it anywhere in your project. Make a separate extension.
class func myfunc(){
}
if you want to send data from B to A controller. You use what is called delegation. You give the work of B to A. Make a protocol above B for functions that you want to do or send with them. Call them in B. And then in A write code for those functions. So that you have the data from B to A
Else you demand something like common data. Create a singleton class and initialize properties methods there. You can use objects for that and call it in other controller to modify or make different instances.
You dont call viewDidLoad(). As the name says it loads once. If you want something that modify everytime you screen appears, use viewWillAppear
I have tried to make a location autocomplete text view class by subclassing UITextField and use Google Place Autocomplete API. This works great, but I have a design error due to the implementation. To observe when the user types text, I set the UITextFieldDelegate to self in the custom subclass and track changes to the typed text in textView:shouldChangeTextInRange:replacementText:. This works, but here is the design error: If someone now wants to check what is typed into the custom subclass by setting the delegate to something new, the delegate of my class is not set to the object of the class itself anymore. Now the custom class is useless. Is there any way to either get the text as it is typed without the delegate, prevent the delegate from being changed, or in any other way fix my problem?
A few options I have though about that could work, but in a bad way:
Check regularly what the text property is: Should be obvious why busy waiting is a stupid idea
Override the delegate property and set it to private: Not sure if this will even work, but if it did, the class is no longer a proper subclass of UITextField and all delegate methods are unavailable when implementing my subclass.
Provide a new delegate for further use of the delegate: Allows someone to get the same things as the UITextFieldDelegate provides, but it still messes up the documentation and proper implementation of UITextField
Delegates in UIKit I normally one to one connections. Which can cause the problem you have described.
If you want multiple delegates of a UITextField I would derive a class from UITextField for example MYTextField and add a method to addDelegate and removeDelegate that maintains a list of delegates. The sent the MYTextField's delegate to itself and broadcast any delegate method to all listeners in the delegate array.
this post shows example code on how do maintain a list of multiple delegates.
Delegation to multiple objects
Right now I have a view controller that handles a lot of network requests. They are each a subclass of a NetworkRequest class and this view controller is the delegate of all of them. It implements one callback function, networkRequestDidFinish.
The problem is that all these network requests are separate objects, and they will all call that same function. What is the proper way to design this? Right now I go through a bunch of if statements in networkRequestDidFinish to see what kind of network request returned. It feels wrong though, but I am not sure what is conventional to do in this case.
Thanks.
One useful pattern here is to be sure that the delegate methods pass self to the view controller. It sounds like you might already be doing this - if you're using a series of if statements, you probably have a pointer to the relevant NetworkRequest. If you aren't, or are not sure, read on.
You see this pattern pretty much wherever delegation is used. As an arbitrary example, take the UITableViewDelegate protocol. The first argument of each of the delegate methods is a UITableView. For example:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
When a UITableView instance calls this delegate method, it passes self as that first argument. It does something like:
[self.delegate tableView:self heightForRowAtIndexPath:0];
Then, the delegate knows which UITableView it's dealing with, because it has a pointer dropped in its lap, as the argument tableView.
In your case, I would start by adding a parameter to the delegate method networkRequestDidFinish, changing its signature to:
- (void)networkRequestDidFinish:(NetworkRequest *)networkRequest
That way you can tell which instance of NetworkRequest has called the delegate method.
Already had that, or that's not good enough? Well, the next thing I'd say would be to consider whether you really need to perform different actions based on the actual class of the NetworkRequest instance that's calling the delegate method. If you're just passing along the data, the answer is probably no. For example:
- (void)networkRequestDidFinish:(NetworkRequest *)networkRequest {
[self processData:networkRequest.data];
}
That method doesn't care what class networkRequest really is. But you seem to care, since you're doing "a bunch of if statements." Then I would say that it might be a mistake to have them all hitting one delegate method. Instead, you might want to get rid of a delegate on NetworkRequest, and instead add a protocol to each of the subclasses of that class, specific to the subclass.
What?
Let's look at an example.
Imagine that one of the subclasses of NetworkRequest is FooNetworkRequest which, of course, requests foos. Its header might look like this:
// stuff...
#protocol FooNetworkRequestDelegate
- (void)fooNetworkRequestDidFinish:(FooNetworkRequest *)fooNetworkRequest;
#end
#interface FooNetworkRequest : NetworkRequest
#property (weak, nonatomic) id<FooNetworkRequestDelegate> delegate;
// stuff...
#end
You apply a similar treatment to all the other subclasses of NetworkRequest. Then, your view controller would adopt each of these protocols, and have a separate method for each subclass of NetworkRequest.
That still seems kind of dirty, right? It does to me. Maybe this is a hint that your view controller is trying to handle too many things at once. You should consider trying to spread out the responsibility for all these NetworkRequest subclasses to multiple view controller or model classes.
If that's not an option, you can at least make your view controller's source a little easier to read by using one or more categories. Put your view controller's main behavior in its .m file, as usual, and then create a category on that view controller that adopts the proper protocol(s) and handles the requests.
There are generally 2 nice procedures.
You can use block instead of the delegate. That means you can send a block to your request class either when instancing it or when you make the request.
Use a target/selector pair system to make it look kind of like adding a target to an UIButton. NSInvocation should do the trick.
I have a ViewController.m with a UIButton and a UIWebView on it.
I've subclassed UIWebView to a class that is now called MyWebView.m.
What is the most efficient way to change the UIButton outlet location value from a method that is inside MyWebView.m
I thought about NSUserDefaults but it feels to me like it's the worst way to go.
Another thought was to copy the next line and also add it inside MyWebView.h:
#property (weak, nonatomic) IBOutlet UIButton *myButton;
and connect it to the button from ViewController.m but I'm also not sure if that's a right thing to do.
What does the button title represent, conceptually? Decide that, and expose it as a string property of your web view and then have your view controller observe the property with key value observing. Or alternatively, extend UIWebViewDelegate with your own protocol, and have the view controller set itself as the web view's delegate. Then have the web view notify its delegate that this value changed.
You can use the app delegate class for persisting the data through the application but this is also not recommended by the good programmers.
One other way is to use Singleton class . This creates only one object per application session so you can use the the value throughout the application also you can modify and access the value. This is the pure approach to go .You can take a look at http://www.galloway.me.uk/tutorials/singleton-classes/
Whenever I create a UI object such as UITextField programmatically, I do this:
txt.delegate = self;
A compiler warning appears and asks me to add UITextFieldDelegate in the .h file.
I noticed though that it makes no difference with or without, the code works fine either way.
But the compiler warning disappears. Why is this?
You don't actually need to set the delegate property on your objects unless you are actually using the delegate methods. For example, if you need to know when the UITextField is about to begin editing. If you don't need to know when these things occur, you don't need to set the delegate.
Looking at it the other way, if you make your class conform to a delegate method (by adding <SomeClassDelegate> in the .h file), and then forget to implement required delegate methods, you'll get a warning from the compiler, and a crash when the app runs (and sends a required delegate message to your object).
To answer your question about not adding UITextFieldDelegate to your .h file, imagine your friend is looking for a French translator. You find a foreign looking man and introduce him. Your friend asks "But can he speak French?" You reply "I don't know". This is your warning.