Delegates in Xcode 7, iOS9 - ios

First of all, I am not Objective-c developer, however I have 4 years of experience in C and C++.
I am trying to make a few demo programs for an (iPad) app camp. For one of these programs I want to pass data between two UIViewControllers.
I have tried various examples, among the example below.
Passing Data between View Controllers
The code is written in an older version of Xcode so I took a bit of tweaking to get it through the compiler. Now I am facing the following problems:
It seems the prepareForSegue is not being called when I open a new view? (Or am I doing something wrong?) I have tried various ways.
In the same post there is a way to pass a delegate to a new class and back to the calling class. When I run this all goes good but there is the last part:
In ViewControllerA.m implement the following method from our protocol
(void)addItemViewController:(ViewControllerB *)controller didFinishEnteringItem:(NSString *)item
{
NSLog(#"This was returned from ViewControllerB %#",item);
}
Does net execute... I have no idea what is wrong. I followed the example exactly. I can see the second view opening and closing, only the delegate code won't run. Do I have to do this in a different way in Xcode 7?
P.S. I know this is a basic question but I cant seem to find the answer or a good Xcode 7 guide anywhere.

following method from our protocol.. Does net execute...
Are you sure that you assign your first view controller's reference to your target view controller's delegate property like,
secondViewController.delegate = self;
You can do this in where you create the second view controller, e.g prepareForSegue method. If you forgot this your delegate method simply not work, because your second view controller doesn't know who's its delegate.

Related

iOS Delegates instead of passing data through a segue

I'm trying to learn how delegates work and wrap my head around the concept. I'm finding I get some of the ideas. I understand you use it to pass data from one view controller to another, however wouldn't it work the same if I just sent data from a segue and every time the 1st view controller would appear, it would use that data?
So for example I have 2 view controllers.
1 is homeViewController and
2 is editViewController.
I have a variable titled "addressOfHome" which is a string in homeViewController(1).
In homeViewController under the method "viewDidAppear"
I also set the addressLabel = addressOfHome.
Then I just pass the data from editViewController(2) to homeViewController(1)
when the segue's destination vc is homeViewController ?
I'm terrible at explaining things so I apologize for that, but I gave it my best shot. Thanks for your time!
Delegates are mainly used to "trigger action" on an object from another one.
An object delegates a way to handle something to someone else, for example when you click on an UIAlertView button, if its delegate is set on a viewController, alertView:clickedButtonAtIndex will be executed on the VC, which can so react as it want
I'm terrible at explaining things
Haha, yes, you are !
A delegate isn't for that - a delegate is a way to over-ride the default behaviour of some feature(s) of a class, without creating your own sub-class. See this post : How does a delegate work in objective-C?
Are you trying to understand how delegates work (in which case, I don't think your example is one that requires a delegate) or are you trying to implement the functionality you describe, and think that a delegate is the way to do it? (I think you actually want a data source).

Is it a MUST for viewWillAppear to have [super viewWillAppear] method as well

I placed my code for iAd/AdMob ads in...
-(void)viewWillAppear:(BOOL)animated{}
Ads work perfectly fine the way I have them now on all iOS devices.
When I connected my iPhone to Xcode and clicked on Product -->Analyze a message states...
The viewWillAppear:instance method in UIViewController subclass 'iPhoneSIX' is missing a [super viewWillAppear:] call
I just accidentally stumbled upon this Product-->Analyze thing. Do I really need to add [super viewWillAppear] even though everything works perfectly fine on all devices as it currently is. Will Apple reject my app if I don't pay attention to the Product-->Analyze issue navigator?
Also, what does ...
[super viewWillAppear:YES];
What does calling this do?
According to Apple: (emphasis mine)
This method is called before the receiver's view is about to be
added to a view hierarchy and before any animations are configured for
showing the view. You can override this method to perform custom tasks
associated with displaying the view. For example, you might use this
method to change the orientation or style of the status bar to
coordinate with the orientation or style of the view being presented.
If you override this method, you must call super at some point in your
implementation.
Apple doesn't gets that specific when deciding to Accept or Reject your app. It only follows the guidelines, which doesn't get that much into the weeds of your specific methods.
Calling [super viewWillAppear:YES] is a best practice, and I would recommend it. Always including super ensures that any code in the super classes get called before executing any additional code. So if you or someone else coded a super class that expected some code to be executed, you are guaranteed to still execute it, rather than just overwriting the whole method in the subclass.
Say you have a view controller of type MyViewController which is a subclass of UIViewController. Then say you have another view controller of type MyOtherViewController, which is a subclass of MyViewController. Say you're coding now some things in viewWillAppear in MyOtherViewController. If you call super first, it will call viewWillAppear in MyViewController before executing any code. If viewWillAppear in MyViewController calls super first, then it will call viewWillAppear in UIViewController before executing any code.
I'm quite certain Apple will not reject your app for failing to call super on an overridden method, primarily because there are cases where you may specifically want to avoid calling super.
That said, as Josh Gafni mentions it is definitely a best practice to do so, unless you have a very good reason for not. Also bear in mind some view controller subclasses (can't recall specifically which ones, but maybe UICollectionViewController) will only work properly if their view lifecycle methods get called appropriately, so not calling super can definitely break some classes (sometimes in subtle ways you may not realize).
Therefore my suggestion is add the call to super (generally as the first line in the method) and see if things continue to work fine. If not, spend a bit of time trying to understand what is happening differently and see if you can solve it in a different way. In general you should always (as a force of habit) provide calls to super on any view lifecycle methods you override whenever possible.

WKInterface button doesn't change title

I'm trying to change the title of a button after I call back from a notification but it doesn't respond at all. I checked it's not nil and checked the text Im' assigning and all is good. I made the property type strong instead of weak but no success.
- (void) setButtonTitleFromSelectedSearchResult:(NSNotification *)notif
{
[self popController];
self.sourceMapItem = [[notif userInfo] valueForKey:#"SelectedResult"];
NSLog(#"The Selected Result is: %#", self.sourceMapItem.name);
//Testing
NSLog(#"%#", self.fromButton); // check it's not nil
[self.fromButton setTitle:self.sourceMapItem.name];
}
With WatchKit, if a user interface element isn't currently visible, it cannot be updated. So, if you've presented another interface controller "on top", you can't update any of the presenting controller's interface elements until you've dismissed the presented controller. At that point, you can safely update the presenting controller in its willActivate method.
SushiGrass' method of passing blocks is certainly one valid approach. In my testing, however, I ended up having to manage multiple blocks, and many of the subsequent blocks reversed what earlier queued blocks had accomplished (for example, first changing a label's text to "foo", then "bar", then "foo" again. While this can work, it isn't optimal.
I'd suggest that anyone who is working on a WatchKit app takes a moment to consider how they want to account for off-screen (i.e. not-currently-visible) interface elements. willActivate is your friend, and coming up with a way to manage updates in that method is worthwhile if you're moving from controller to controller.
For what it's worth, I've encapsulated a lot of this logic in a JBInterfaceController subclass that handles a lot of this for you. By using this as a base class for your own interface controller, you can simply update your elements in the added didUpdateInterface method. Unfortunately, I haven't yet had the time to write proper documentation, but the header files and sample project should get you going: https://github.com/mikeswanson/JBInterfaceController
I'm using latest XCode 6.3 and below code working with me.
self.testBtn is bind with Storyboard and its WKInterfaceButton
I also have attached screenshot with affected result.
I'm setting initial text in - (void)willActivate
- (void)willActivate {
[super willActivate];
[self.testBtn setTitle:#"Test"];
[self performSelector:#selector(justDelayed) withObject:nil afterDelay:5.0]
}
-(void)justDelayed
{
[self.testBtn setTitle:#"Testing completed...!!"];
}
If you're using an IBOutlet for the property fromButton be sure that is connected to WKInteface on the storyboard, like below:
I solved this kind of issue by creating a model object that has a property that is a block of type () -> (Void) (in swift). I create the model object, set the action in the block that I'd like the pushing WKInterfaceController to do on completion, and finally pass that model object in the context to the pushed WKInterfaceController. The pushed WKInterfaceController holds a reference to the model object as a property and calls it's completion block when it's done with whatever it needs to do and after func popController().
This worked for me for patterns like what you are describing along with removing rows on detail controller deletion, network calls, location fetches and other tasks.
You can see what I'm talking about here: https://gist.github.com/jacobvanorder/9bf5ada8a7ce93317170

One delegate, Two UIViewCotrollers okay?

As the title implies, I'm asking if it would be okay to link a single delegate to two different UIViewControllers in my project. I'm trying to link to two different VCs in my project but it's making the first VC's act weird so I'm wondering if I'm doing it wrong?
Sorry if this is a noob question, still new to this.
Nothing wrong with this at all.
A delegate protocol is just a protocol. An object can conform to multiple protocols at the same time (e.g. UITableViewDelegate and UITableViewDatasource).
You might have two view controllers like MyPersonViewController and MyAnimalViewController and they will have delegate protocols like MyPersonViewControllerDelegate and MyAnimalViewControllerDelegate.
You can then just do...
self.personViewController.delegate = self;
self.animalViewController.delegate = self;
The only thing to make sure of is that when you get the call backs from each VC that you don't confuse them. The best way to do this is to use the same pattern as UITableViewDatasource and prefix the methods like...
- (void)personViewController:(MyPersonViewController *)controller gotSomeResults:(NSArray *)results
Or something. Anyway, then you have a completely different set of delegate methods for each controller.

Who calls the private method during unwinding in Xcode?

For implementing unwind segue we need make control-drag in the storyboard and
create private method in the destination view controller.
I don't understand : if method is private, how it works? Because in the implementation file of my view controller this NOT calling.
When executed, your application parses the .storyboard file at first, getting to know what classes it needs to instantiate and other important information, like segue connections. Then, it creates class instances (and manages them later). Then, when requested (e.g. after a button press), it attempts to find a method unwindToList: in the controller instance. If there is one, it would execute. If not, an exception would be thrown.
However, that method is not exactly hidden. Basically, there is no such thing as a private method in Objective-C; at least not in the same way as some other languages have. Every method is accessible by the runtime. If you're interested in how Objective-C works exactly, take a look at these pages, for example:
How does objective-c handle method resolution at run-time?
http://cocoasamurai.blogspot.ru/2010/01/understanding-objective-c-runtime.html

Resources