I have a custom class (Packages) that is of form NSObject. I have many instances of this object. In initializing each of these instances, I pass self from my UIViewController names ViewController.
In the code for these packages, I would like to call a method from ViewController.
-(void)toThisView:(UIView *)someView
{
[imagesToRender addObject:someView];
[self.mainImageView addSubview:someView];
}
and in Packages.m
I have
- (UIView *)handleTapFrom:(UITapGestureRecognizer *)sender
{
[view2 toThisView:sender.view]; // Error No visible #interface for 'UIViewController' declares the selector 'toThisView:'
}
where view2 is UIViewController *view2 and its being set as view2 = object via the init method of this classes
- (id)initWithPath:(NSString *)path andObject:(NSObject *)object
Why am I getting this error:
No visible #interface for 'UIViewController' declares the selector 'toThisView:'
if view2 is your custom type object then you can simply do this :
[(YourCustomClass *)view2 toThisView:sender.view];
import YourCustomClass. in viewController.
It sounds like you have a class named ViewController which is a subclass of UIViewController.
It also sounds like you have an instance variable named view2 which you declared like this:
#implementation Packages {
UIViewController *view2;
}
or possibly like this:
#interface Packages : NSObject
#property (nonatomic, strong) UIViewController *view2;
You need to declare view2 to be a ViewController, not a UIViewController. In other words, declare it like this:
#implementation Packages {
ViewController *view2;
}
or like this:
#interface Packages : NSObject
#property (nonatomic, strong) ViewController *view2;
I think you need to add
-(void)toThisView:(UIView *)someView
To your viewController.h file, otherwise it won't be visible from any other class.
1st import your custom class in viewController.
create an object of the class.
Call method simply like this.
[object toThisView:YourPrameter];
Before calling also declare this method in your class .h file like this
-(void)toThisView:(UIView *)someView;
Related
I have two controllers. A BaseViewController and MyController. On BaseViewController I have as property an NSObject that has a Protocol
BaseViewController.h
#property (nonatomic, strong) MyListener *myListener;
MyListener.h
#protocol MyListenerProtocol;
#interface MyListener : NSObject
#property (nonatomic, weak) id<MyListenerProtocol> delegate;
#end
#protocol MyListenerProtocol;
#protocol MyListenerProtocol <NSObject>
#optional
-(void) myMethod: (int) input;
#end
MyController extends BaseViewController
#interface MyController : BaseViewController <MyListener>
and in it's viewDidLoad:
super.myListener = [[MyListener alloc] init];
super.myListener.delegate = self;
in BaseViewController in a method, when called it does:
if (self.myListener && [self.myListener.delegate respondsToSelector:#selector(myMethod:)]) {
[self.myListener.delegate myMethod: input];
}
But in this point the "self.myListener" is always nil.
What I want is to call a method in the child view controller when a BaseViewController's method is called (but only for some children view controllers, not all).
Any suggestions?
Please implement a custom getter for the property named delegate, set it normally and set a breakpoint there. This way you will find the cause of the problem.
Also, be aware that a weak property will go away as soon as no other objet points to the
Object that you set as delegate.
The most likely cause (and an insanely common cause) is that your BaseViewController method is being called prior to viewDidLoad. Have you verified this is not the case?
As a note, you mean self in all the places you've put super.
Also note, in this line:
if (self.myListener && [self.myListener.delegate respondsToSelector:#selector(myMethod:)]) {
There is no reason for self.myListener &&... If self.myListener is nil, the rest of the call will become false automatically.
You should tell the MyController the delegate it uses, but you tell the wrong name.
#interface MyController : BaseViewController <MyListener>
change to:
#interface MyController : BaseViewController <MyListenerProtocol>
Set delegate in prepareForSegue method.
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
LastNameViewController *lastNameViewController = [segue destinationViewController];
lastNameViewController.delegate = self;
}
I'm creating a custom UIView subclass (shareView) from a Nib.
I created a custom protocol for shareView like this:
#protocol sharePopupDelegate
#required
-(void)userPublishedContent;
-(void)userAbortedPublish;
#end
#interface shareView : UIView
{
id<sharePopupDelegate> delegate;
}
In my main.storyboard I created a custom UIViewController myViewController with a shareView view instance called "popup" inside.
So now I got
#property (weak, nonatomic) IBOutlet shareView *popup;
I would like now to delegate myViewController from shareView methods i declared, so I did
self.popup.delegate = self;
inside myViewController but the protocols' methods are not being called inside myViewController.
So i correctly see the shareView instance but cannot interface to its delegate.
Can you help me please?
Thanks in advance
Make sure that you have the protocol declared in myViewController.
For example
#interface MyViewController : UIViewCOntroller <sharePopupDelegate>
In this section of the code:
#interface shareView : UIView
{
id<sharePopupDelegate> delegate;
}
You are creating a strong reference to the delegate, which is not what you want most of the time. Change it to this:
#interface shareView : UIView
#property(weak, nonatomic) id<sharePopupDelegate> delegate;
The shareView class itself must have some way to know when a user publishes content. Maybe you have an action linked up to the shareView which calls a method in the shareView class. For examaple:
- (void)publishButtonTapped {
// some code
}
What you want to do is let the delegate know in that method, something like this:
- (void)publishButtonTapped {
// some code
[self.delegate userPublishedContent];
}
Then whatever action the user takes to cancel:
- (void)cancelButtonTapped {
// some code
[self.delegate userAbortedPublish];
}
Hope this helps.
I want to access super class iBoutlets objetcs in my subclass. Is that possible?. I am trying in the following way but am always getting nil.
Here is my code:
My super class
#import <UIKit/UIKit.h>
#interface SuperClassA : UIViewController {
}
#property (weak, nonatomic, getter=getDummyView) IBOutlet UIView *dummyView;
#end
#implementation SuperClassA
- (void)viewDidLoad {
[super viewDidLoad];
SubClassB *obj = [SubClassB new];
[obj printSuperClassiBouletObject];
}
#end
my subclass:
#import <UIKit/UIKit.h>
#interface SubClassB : SuperClassA {
}
#end
#implementation SubClassB
-(void)printSuperClassiBouletObject
{
NSLog(#"view: %#", [self getDummyView]);
}
#end
The above code gives me nil value always. Any idea how to get the actual iBoutlet object?. But when i pass the iBoutlet as an function argument then the object was not nil. In the super class i tried strong property, using #synthesize in implementation file but no helps. Any help that really might be appreciated.
My guess is that the problem is here:
SubClassB *obj = [SubClassB new];
[obj printSuperClassiBouletObject];
New will use default initializer, that will try to load nib with your class name, which is SubClassB. Do you have SubClassB.xib that set the outlet your project? If not, then SubClassB will be initialized with empty properties, by the default objc initializer.
Try this:
SubClassB *obj = [[SubClassB alloc] initWithNibName:#"SuperClassA"]; //or xib name that SuperClassA uses to initialize
There's nothing special about IBOutlet relative to the scope rules. You can inherit any property from super by including its declaration in the subclass. The simple way to do this is by placing those property declarations in the superclass's public interface (in superclass.h). Since we know that the subclass must import that, we know that everything in there will be available to the subclass.
A more complicated arrangement is required if you'd like the subclass to access the property but not other classes. These "protected" declarations need to go into a third header file that only the super and subclass import.
In other words... (simple case):
// MySuper.h
#interface MySuper : NSObject
#property (weak,nonatomic) IBOutlet UIView *someOutlet;
#end
// MySub.h
#import "MySuper.h"
#interface MySub : MySuper
// stuff for my sub
#end
Now both MySuper and MySub can refer to someOutlet
For "protected", something like this:
// MySuper.h
#interface MySuper : NSObject
// only public stuff here
#end
// MySuper-protected.h
#interface MySuper ()
#property (weak,nonatomic) IBOutlet UIView *someOutlet;
#end
// MySuper.m
#import "MySuper.h"
#import "MySuper-protected.h"
// MySub.h
// same as simple case
// MySub.m
#import "MySub.h"
#import "MySuper-protected.h"
Finally, i was able to achieve this by using this way!!!!
In my subclass i changed the method to:
-(void)printSuperClassiBouletObject:(SuperClassA*)superClassObj
and in my super class i am calling this way:
SubClassB *obj = [SubClassB new];
[obj printSuperClassiBouletObject:self];
And in my subclass i was access the super class objects and its variable from the super class instance it self.
Thanks for all the help !!!!!! :-)
I have a UIView subclass called NumberPickerView. I'm writing a delegate method for it. The compiler won't let me pass an instance of NumberPickerView as an parameter in that method. What am I missing?
#protocol NumberPickerViewDelegate
-(void) numberPickerDidChangeSelection:(NumberPickerView *)numberPickerView;
//error: expected a type
#end
#interface NumberPickerView : UIView <UIScrollViewDelegate> {
id <NumberPickerViewDelegate> delegate;
}
Actually it CAN. At that point compiler doesn't know about NumberPickerView class
#class NumberPickerView;
add it over protocol declaration to let compiler know about that class... It's called forward declaration.
For better understanding check this out:
iPhone+Difference Between writing #classname & #import"classname.h" in Xcode
OR
move protocol declaration below the class NumberPickerView definition but in that case you should also add at top:
#protocol NumberPickerViewDelegate;
Not to get warnings using id<NumberPickerViewDelegate>delegate
You can change parameter type to id instead of NumberPickerView * and pass any class object afterword as bellow
#protocol NumberPickerViewDelegate
-(void) numberPickerDidChangeSelection:(id)numberPickerView;
#end
#interface NumberPickerView : UIView <UIScrollViewDelegate> {
id <NumberPickerViewDelegate> delegate;
}
The title is what I think I need but i will go back one step. I want to create a class which handles certain things in an iOS app. This class might be called by multiple UIViewcontrollers in an iOS app. The class may need to show a UIView at some stage for user input. So my question is how can I show a UIView when I don't know which subclass of UIViewController is calling it? To what can I add the UIView from this class?
I suppose there are two possible answers either the class finds the current UIViewController or the calling subclass of UIViewController passes itself to the class so the class knows.
How is this supposed to be done.
Thanks guys for your help.
I'm going to expand on #ericleaf's comment regarding using a protocol and subclasses. It sounds like you are asking the following:
How can I create a resusable, generic class that presents a view
within a UIViewController subclass?
A great way to do this is to define a protocol in your generic class and have your view controller subclasses support this protocol. The protocol defines an interface for your custom class to comunicate with it's delegate, in this case a UIViewController subclass. Other than the protocol, the objects don't need to know anything else about the implementation of each other.
Any information your custom object needs to be able to present views within it's delegate would be passed via protocol methods. The specifics of the protocol are up to you based on your needs. You could have the custom object "ask" the delegate for information (e.g. what view should I put a subview in?) or you could have the protocol provide information to the delegate and let the delegate deal with it (e.g. here is a subview you can put wherever you want).
There is a lot of great documentation on protocols available on SO and elsewhere. This is long enough already so I kept the example fairly simple.
custom class .h file with protocol definition
// my custom class that adds adds a view to a view controller that supports it's protocol
// forward class definition for the protocol
#class MyAwesomeObject;
#protocol MyAweseomeObjectDelegate <NSObject>
- (UIView *)viewForMyAwesomeObject:(MyAwesomeObject *)awesomeObject;
#end
// this could be defined such that the delegate *must* be a UIViewController. I've left it generic.
#interface MyAwesomeClassObject : NSObject
#property (nonatomic, weak) id <MyAwesomeObjectDelegate> delegate;
#end
custom class .m file
// MyAwesomeObject.m
#import "MyAwesomeObject.h"
#implementation MyAwesomeObject
// this is a dumb example, but shows how to get the view from the delegate
// and add a subview to it
- (void)presentViewInDelegate
{
UIView *containingView = [self.delegate viewForMyAwesomeObject:self];
if (containingView) {
UIView *subview = [[UIView alloc] initWithFrame:containingView.bounds];
subview.backgroundColor = [UIColor redColor];
subview.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
[containingView addSubview:subview];
}
}
MyViewController .h using the custom object
// MyViewController.h
#import "MyAwesomeObject.h"
#interface MyViewController : UIViewController <MyAwesomeObjectDelegate>
#property (nonatomic, strong) MyAwesomeObject *awesomeObject;
#end
MyViewController .m using the custom object
// MyViewController.m
#import "MyViewController.h"
#implementation MyViewController
- (void)init
{
self = [super init];
if (self) {
_awesomeObject = [[MyAwesomeObject alloc] init];
_awesomeObject.delegate = self;
}
return self;
}
// MyAwesomeObjectDelegate
- (UIView *)viewForMyAwesomeObject:(MyAwesomeObject *)awesomeObject
{
return self.view;
}
You can get the class into a string and do a compare.
For example, lets assume your custom UIViewController subclass is CustomViewCon and the UIViewController object reference is myUnknownClassObject, then:
NSString *classString = NSStringFromClass([myUnknownClassObject class]);
Then you can:
if([classString isEqualToString:#"CustomViewCon"]){
//do something like maybe present a particular view
myUnknownClassObject.view = myCustomView; //or anything..
}
Similarly you can check for any class.
Edit: According to the suggestions from comments, you could also do the following(better way):
if([[myUnknownClassObject class] isKindOfClass:[CustomViewCon class]]){
//same as before
}
Why wont you use a block for this?
BaseViewController.h:
#property (copy) void (^addViewBlock)();
- (IBAction)showViewWhenNeeded;
BaseViewController.m:
- (IBAction)showViewWhenNeeded
{
if (self.addViewBlock)
self.addViewBlock();
}
And in your child class, set that block's actions, and call the method when you feel like you should put up a view.
ChildViewController.m
// within some method, propably init or smth
[self setAddViewBlock:^{
[self.vied addSubView:...];
}];
// when need to actually add the view
[self showViewWhenNeeded];