how to use buttons defined in one class that class inherits UINavigationController and appeared in every other class in objective c? - objective-c-protocol

is it possible that i define a class which inherit UINavigationController and add buttons in this class.and when ever i use this class in another class buttons will be shown on navigation bar of each class..hope it is clear.Thanks in Advance

Instead of using UINavigationController, I would suggest you to subclass UIViewController and configure what ever you want in this class.
Further where ever you need the same implementation, just use your newly created class.
For eg; create new CustomViewController as below
in .h file
#interface CustomViewController : UIViewController {
}
in .m file,
-(void)viewDidLoad {
[super viewDidLoad];
// Custom Implementation of bar and View as per your requirement
}
Now if you want to have this configuration in some other View Controller, subclass CustomViewController and everything will be done. Eg: If you have ListViewController,
in .h file,
#interface ListViewController : CustomViewController {
}
in .m file
-(void)viewDidLoad {
[super viewDidLoad]; // Its super class is "CustomViewController" so viewDidLoad method you implemented in CustomViewController will be called and your view will be configured.
// Further Whatever you want in this controller
}
Hope it helps.

Related

NSViewController not dealloc'd when outlets are bound

I have the following files:
Main.storyboard
This is the same as the default storyboard created when creating a new project with a few additions: There is a button in the view which is connected to the button outlet of the view controller (instance of ViewController) and the doTheThing: action on the view controller.
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#property (weak) IBOutlet NSButton *button;
#property (weak) NSViewController *controller;
#end
#implementation ViewController
- (IBAction)doTheThing:(id)sender {
if (self.controller) {
NSLog(#"Removing %#", self.controller);
[self.controller.view removeFromSuperview];
[self.controller removeFromParentViewController];
} else {
self.controller = [[NSStoryboard storyboardWithName:#"Another" bundle:[NSBundle mainBundle]] instantiateInitialController];
[self addChildViewController:self.controller];
[self.view addSubview:self.controller.view];
NSLog(#"Adding %#", self.controller);
}
}
#end
Another.storyboard
A simple storyboard containing a single scene (view controller + view) that is set to the initial controller and is an instance of AnotherViewController. There is a label in the view that is not connected to any outlet.
AnotherViewController.m
#import "AnotherViewController.h"
#interface AnotherViewController ()
#property (weak) IBOutlet NSTextField *label;
#end
#implementation AnotherViewController
- (void)dealloc {
NSLog(#"Deallocing AnotherViewController %#", self);
}
#end
When I run the app and click the button, it adds the view controller and view from Another.storyboard, and when I click the button again they are removed and the instance of AnotherViewController is deallocated.
However, if I connect the label in Another.storyboard to the label outlet on the AnotherViewController, the deallocation never occurs. Why is this and what can I do to fix it?
Edit: I do have a few workarounds, but they aren't very desirable and I would prefer to understand why the recommended way (storyboards and outlets) isn't working properly.
Undesirable workaround 1: Do the same thing but load the view controller and view from a XIB file. This works as expected, but ideally I would be able to do the same thing using storyboards.
Undesirable workaround 2: Bind all my outlets manually in code in the view controller's viewDidLoad method. This is just tedious and ugly as it requires iterating through all the view's subviews and comparing identifiers.
Apple have confirmed (via bug report) that this is a known issue and will be fixed in OS X 10.10.3.

GWT DataGrid : "Unable to find ImageResource method value("cellTableLoading")" when overriding styles

I tried to override styles for GWT DataGrid component like described here :
DataGrid / CellTable styling frustration -- overriding row styles
My interface
public interface DataGridResources extends DataGrid.Resources {
#Source({ DataGrid.Style.DEFAULT_CSS, "myDataGrid.css" })
DataGrid.Style dataGrid();
}
public static final DataGridResources dataGridResources =
Datagrid instance using Inteface
GWT.create(DataGridResources.class);
static {
dataGridResources.dataGrid().ensureInjected();
}
...
dataGrid = new DataGrid<User>(10, dataGridResources);
But I get the following error :
Rebinding xxx.DataGridResources
-Invoking generator com.google.gwt.resources.rebind.context.InlineClientBundleGenerator
--Creating assignment for dataGrid()
---Creating image sprite classes
----Unable to find ImageResource method value("cellTableLoading") in xxx.DataGridResources : Could not find no-arg method named cellTableLoading in type xxx.DataGridResources
--Generator 'com.google.gwt.resources.rebind.context.InlineClientBundleGenerator' threw an exception while rebinding 'xxx.DataGridResources'
-Deferred binding failed for 'xxx.DataGridResources'; expect subsequent failures
The following works. Really.
public interface Resources extends DataGrid.Resources {
interface Style extends DataGrid.Style { }
#Source(value = {DataGrid.Style.DEFAULT_CSS, "myDataGrid.css"})
public Style dataGridStyle();
}
Also you don't need to call ensureInjected() since DataGrid will call it for you.
Anyway there is something wrong in the error log: it looks for cellTableLoading style which is not part of the DataGrid.Resources interface (is part of CellTable.Resources). Have you left some spurious CSS classes in myDataGrid.css that are not defined in the original interface?
Maybe you have moved from CellTable to DataGrid by simply renaming the css, but without changing the inner class names.

Gesture controls crash when calling methods on C4WorkSpace.m

I'm working with the C4 framework on a project and I'm having a bit of trouble with using the gesture controls and calling methods from C4WorkSpace.
I found this link that had to do with this problem but it didn't seem to stop my program from throwing an error.
A little background: I'm creating a custom button class that has 4 properties: UIColor, C4Shape and 2 floats (x/y position). I'm storing the custom button objects in an array and have this bit of code going to add a gesture to each button and add it to the canvas.
C4WorkSpace.m
for (button in buttonArray){
[button.shape addGesture:TAP name:#"tapGesture" action:#"tapped"];
[self.canvas addShape:button.shape];
[self listenFor:#"tapped" fromObject:button andRunMethod:#"doThis:"];
}
And I also have a function outside my '-(void)setup' that just prints a log message:
-(void)doThis:(NSNotification *)notification{
NSLog(#"notification test");
}
I have extended my C4Shape class with a category and when I call this method it works fine:
#import "C4Shape+myC4Shape.h"
#implementation C4Shape (myC4Shape)
-(void)printTest{
NSLog(#"this is a print test");
}
#end
The error I'm getting gets thrown when I try and tap on a button, it says: Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[C4Shape tapped]: unrecognized selector sent to instance 0x931e9c0'
I have my "action" set to 'tapped', but that's just something I made up. I know this usually calls a method inside the shape class, but I'm trying to call a method that isn't in the C4Shape class but on the main WorkSpace. I'm not sure what's causing this or what I'm doing wrong? Is there something specific I need to be writing in the 'action' part of the method?
this Obj-C stuff can be confusing at first. Hopefully this will help.
I notice two things for you to change.
The first is in regards to your TAP gesture. When you add this to your code you're actually telling the gesture to recognize a TAP and then run the tapped method. However, this method doesn't exist (hence the -[C4Shape tapped]: unrecognized selector sent to instance 0x931e9c0). You should have a method in your code called -(void)tapped{}; for this message to go away.
The following code illustrates this:
#implementation C4WorkSpace
-(void)setup {
[self addGesture:TAP name:#"tap" action:#"tapped"];
}
-(void)tapped {
C4Log(#"tapped!");
}
#end
Putting that into a shape is quite similar.
Second, for the subclassing, C4Shape (and all other visual objects) inherit from C4Control so I would suggest that subclassing C4Control isn't the best approach. For creating your own custom button with a C4Shape I would subclass C4Shape directly.
The above code would look exactly the same for a subclassed C4Shape except that if you created a MyShape subclass would have #implementation MyShape instead.
Finally, you want to add a little broadcast message to your tap method so that the canvas can listen for it... All in all your .h and .m files for your subclass should look like this:
.h
#import "C4Shape.h"
#interface MyShape : C4Shape
#end
.m
#import "MyShape.h"
#implementation MyShape
-(void)setup {
[self addGesture:TAP name:#"tap" action:#"tapped"];
}
-(void)tapped {
[self postNotification:#"tapNotification"];
}
#end
Finally, with those two files in your project you can add the following to your workspace:
#import "C4WorkSpace.h"
#import "MyShape.h"
#implementation C4WorkSpace
-(void)setup {
MyShape *m = [[MyShape alloc] init];
[m rect:CGRectMake(0, 0, 100, 100)];
m.center = self.canvas.center;
[self.canvas addShape:m];
[self listenFor:#"tapNotification" fromObject:m andRunMethod:#"heardTap:"];
}
-(void)heardTap:(NSNotification *)aNotification {
MyShape *notificationShape = (MyShape *)[aNotification object];
C4Log(#"%4.2f,%4.2f",notificationShape.center.x,notificationShape.center.y);
C4Log(#"%#",notificationShape.strokeColor);
}
#end
Here's a link to a gist with the 3 files you'll need for this to run.
Button Subclass with Canvas Listener
PS thanks for giving C4 a try!
Oh, and this is the output I get in Xcode's console when I tap on the square:
[C4Log] 384.00,512.00
[C4Log] UIDeviceRGBColorSpace 1 0.1 0.1 1
This gives me the x and y coordinates, as well as the strokeColor of the "button" without having to add these as objects to the MyShape class (because they already exist in C4Shape).

How to pass an NSString from modal view to parent view

I have a parent view and a modal view with a text box. What I am trying to do is pass whatever is entered into the text box from the modal view and then pass it to a label in the parent view which updates the label to what was entered. I hope that made any sense.
I have been pulling my hair out for a couple of weeks trying to figure this out with no luck. I found many examples and tutorials about segues and passing between views that are being pushed but nothing about modal views and passing back to the parent view.
I have been trying to understand this and need a good example. I kind of understand the prepare for segue concept but for some reason, I just can't figure this one out. Any help on this would be much appreciated and you would be my hero for life lol.
In my project that uses segues, here's how I did it (note that I'm new to iOS, so there's probably "better" ways, and this may be obvious to the iOS veterans):
The short version: define a callback protocol in your modal view controller's .h file. When your modal view controller closes, it checks to see if the presenter implements that protocol and invokes those methods to pass along the data.
So like you said, let's say your modal view controller just gathers a single string value from the user and then they click OK or Cancel. That class might look like this:
#interface MyModalViewController : UIViewController
...
#end
I'm suggesting you add a protocol like this to the same header:
#protocol MyModalViewControllerCallback
-(void) userCancelledMyModalViewController:(MyModalViewController*)vc;
-(void) userAcceptedMyModalViewController:(MyModalViewController*)vc
withInput:(NSString*)s;
#end
Then in MyModalViewController.m, you add a viewDidDisappear with code similar to this:
-(void) viewDidDisappear:(BOOL)animated {
UIViewController* presenter = self.presentingViewController;
// If the presenter is a UINavigationController then we assume that we're
// notifying whichever UIViewController is on the top of the stack.
if ([presenter isKindOfClass:[UINavigationController class]]) {
presenter = [(UINavigationController*)presenter topViewController];
}
if ([presenter conformsToProtocol:#protocol(MyModalViewControllerCallback)]) {
// Assumes the presence of an "accepted" ivar that knows whether they
// accepted or cancelled, and a "data" ivar that has the data that the
// user entered.
if (accepted) {
[presenter userAcceptedMyModalViewController:self withInput:data];
}
else {
[presenter userCancelledMyModalViewController:self];
}
}
[super viewDidDisappear:animated];
}
And finally in the parent view, you implement the new #protocol, e.g. in the .h:
#interface MyParentViewController : UIViewController <MyModalViewControllerCallback>
...
#end
and in the .m:
#implementation MyParentViewController
...
-(void) userCancelledMyModalViewController:(MyModalViewController*)vc {
// Update the text field with something like "They clicked cancel!"
}
-(void) userAcceptedMyModalViewController:(MyModalViewController*)vc
withInput:(NSString*)s {
// Update the text field with the value in s
}
...
#end

storyboard navigation Item link to a uiviewcontroller

I create a split view project, on the iPhone's storyboard, i drag a bar button item to the navigation right and change the style Add, and i drag a view controller to the storyboard, so i use control-drag to build the link, and change the uiviewcontroller's custom class "AddViewController", when i run the project and push the DetailViewController, it is black view.
And i have input the code on the AddViewController.m
-(void) viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard_iPhone" bundle:nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"AddViewController"];
[vc setModalPresentationStyle:UIModalPresentationCurrentContext];
[self presentModalViewController:vc animated:YES];
}
i found the reason
On the my create "AddCreateViewController", i should comment the function.
- (void)loadView
{
// If you create your views manually, you MUST override this method and use it to create your views.
// If you use Interface Builder to create your views, then you must NOT override this method.
}

Resources