Having a UISwitch respond to method defined as a protocol - protocols

I have a UISwitch that is in side my UIView. I would like the UISwitch to use a method that I defined in the protocol, and then have another class use the method. This is my first time trying to use a protocol, and I can't seem to figure out how to link up my UISwitch to the method call in the protocol.
This is my protocol:
#protocol responderForOptionalSwitch <NSObject>
#required
- (IBAction) onOffSwitch:(id)sender;
#end
But this method doesn't show up under received actions in the connections inspector.

A protocol is a list of methods that an object should (or, in some cases, must) implement. It is not an implementation of your method itself. To see it show up in IB, you should implement the method in the view/controller (the .h/.m) that your switch belongs to (i.e.: what xib is it in?).

Related

Watir: how to find iframe's tag?

I have an element, for example #<Watir::IFrame:0x..f98fef949215c673e located=false selector={:element=>(webdriver element)}>. How do I determine what tag it is (iframe)?
Found it by searching for similar Javascript method: there exists element.tag_name, but when using it for iframe I get NoMethodError: private method 'tag_name' called for #<Watir::IFrame:0x00000002f8c288>'.
What does it mean and is there some alternative to .tag_name for iframes?
The exception means that the tag_name method is private for Watir::IFrame (and Watir::Frame) objects. "Private", along with "public" and "protected", methods are used for controlling access of methods within a class. The Ruby Pickaxe book has a good description of the method types:
Public methods can be called by anyone---there is no access control. Methods are public by default (except for initialize, which is always private).
Protected methods can be invoked only by objects of the defining class and its subclasses. Access is kept within the family.
Private methods cannot be called with an explicit receiver. Because you cannot specify an object when using them, private methods can be called only in the defining class and by direct descendents within that same object.
Ultimately, this means that you cannot call the tag_name from outside of the class.
Given that the Watir API allows calling the tag_name method for other element types, I would say it is a bug. A pull request has been opened to have the method made public Issue 293.
As a workaround, you can call private methods by using send:
browser.iframe.send('tag_name')
#=> "iframe"
Note that given you already have a Watir::IFrame object and depending on what you are trying to do, you might not need to check the tag name. You could check the class of the object instead:
browser.iframe.class
#=> Watir::IFrame

Monotouch -- Changing label text in ViewController from another class?

I have a class that functions as an async TCP Client. In that class, I have a callback function, such as Client_Connected. This fires when my TCP Client has been connected. In my main viewcontroller class, I have an instance of the TCPClient and a label that I want to display the status of the tcpclient.
My question is, in the callback function of the tcpclient class, how can I reference and set the label's text in my mainviewcontroller's class?
When you create your TCPClient class, pass in a reference to your parent class (or just a reference to the label you want to update) - then your "child" class will have access to the element on the "parent" that needs to be updated.
There are probably other approaches, but this is fairly common.

What UINavigationController event can be overridden to get access to current view controller?

What UINavigationController event can be overridden to get access to current view controller?
My end goal is to check the current screen in the Navigation Controller to determine whether or not to call SetNavigationBarHidden.
If by "current" you mean "currently visible" you can make use of UINavigationController's VisibleViewController property. Though if you're using MT.D you'll want to cast it out:
var currentViewController = (DialogViewController)myNavController.VisibleViewController
Alternatively you could access the ViewController array directly. Or...you can also subclass DialogViewController and set the NavigationBar.Hidden = true inside the implementation.
How about having a UINavigationController subclass adopt the UINavigationControllerDelegate protocol? Then implement the monotouch equivalent of navigationController:willShowViewController:animated: or navigationController:didShowViewController:animated:. Each of these methods passes a parameter which is a pointer to "[t]he view controller whose view and navigation item properties are being shown." You'll have to remember to make the navigation controller its own delegate.

Getting UITabBarController to work with Core Data

I've been reading this thread on Stackoverflow and have been trying to replicate the solution with no success in my own project.
My project has 4 tabs. In my app delegate I do this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
Page1 *page1 = (Page1 *)[navController topViewController];
Page2 *page2 = (Page2 *)[navController topViewController];
Page3 *page3 = (Page3 *)[navController topViewController];
Page4 *page4 = (Page4 *)[navController topViewController];
page1.managedObjectContext = self.managedObjectContext;
page2.managedObjectContext = self.managedObjectContext;
page3.managedObjectContext = self.managedObjectContext;
page4.managedObjectContext = self.managedObjectContext;
[self.window makeKeyAndVisible];
return YES;
}
In the originating thread it says I need to create a IBOutlet to each navController for each tab I want to use Core data on.
Whilst you can assign multiple delegates for the UINavigationController the same is not true for the outlets, you can only ever supply ONE outlet for the navController.
I can get Page1 to work, but the other pages simply crash; because of the lack of an IBOutlet.
Do I really need X IBOutlets for Y Tabs or can I do it another way?
Another issue is that the originating thread the accepted answer is:
Ideally you want to pass either the
NSManagedObjectContext,
NSFetchedResultsController or the
relevant NSManagedObject "down" into
the UIViewController.
But there is no code or example of how to do this.
Ideally, I do not want to use a singelton or use the app delegate all over the place.
Any confirmation and clarification would be great.
Thanks.
Your immediate problem has nothing to do with Core Data. You are assigning the same navigation controller to each tab when you need a separate navigation controller for each tab otherwise the navigation controller's hierarchy of views will get scrambled every time you change tabs.
The pattern recommended in the question you linked to is called "dependency injection" and it is the one that Apple recommends in most cases. However, in the case of tabbars or any other complex view/view-controller hierarchy, dependency injection can get to complicated. It's a particular issue with tabbars because you don't usually load all tab view/view-controllers when the app starts but wait until each tab is selected before loading its elements.
Instead, you can use an alternative pattern that exploits the UIApplication objects singleton status. Since there is only one application object, there is only one application delegate object. That means that anywhere in the app you can make a call like this:
(MyApplicationDelegate *) appDelegate=(MyApplicationDelegate *)[[UIApplication sharedApplication] delegate];
... and always get the same application object. Then, if you have the managed object context defined as a property of the app delegate you can get the context just by:
theManagedObjectContext=appDelegate.managedObjectContext
Add these two lines to every view controller and you can always be sure of getting the app delegate's managed object context.

How can I suspend the working of an NSFetchedResultsController?

I have a UITableViewController fed by an NSFetchedResultsController. From it, the user can call up a modal ViewController in which he or she can enter new data. As this begins, I create a temporary object as follows:
newPtr = [[Entry alloc] initWithEntity:[NSEntityDescription
entityForName:#"Entry" inManagedObjectContext:self.nmocontext]
insertIntoManagedObjectContext:self.nmocontext];
As the user makes choices, attributes of this 'provisional' object, newPtr, are set.
The problem is that the base UITableViewController remains active while the modal ViewController is visible. It seems to be freaking out (causing crashes) in some cases when it realizes a mandatory attribute of newPtr has not been set yet.
What can I do to stop the NSFetchedResultsController from looking at my managed object context until the modal ViewController is dismissed?
Core Data supports "nested" managed object contexts which allow for a flexible architecture that make it easy to support independent, cancellable, change sets. With a child context, you can allow the user to make a set of changes to managed objects that can then either be committed wholesale to the parent (and ultimately saved to the store) as a single transaction, or discarded. If all parts of the application simply retrieve the same context from, say, an application delegate, it makes this behavior difficult or impossible to support.
I haven't tested this myself but a possible approach would be to implement viewWillAppear and viewWillDisappear, and set the fetchedResultsController delegate to self on will appear and nil on will disappear.
OR
You could create an NSObject that mirrors the attributes of your NSManagedObject in your editing window. Once the user has finished editing the attributes (and you have run the appropriate validation rules) you can pass them back to your NSManagedObject instance and let the fetchedResultsController do its job.

Resources