My protocol method is not triggered, and no errors while trying - iphone

First time working with protocols and it is not working but no errors either...
I have defined and implemented a protocoll in a delegate (BlockPopViewController). Then I try to access it from a UIViewController (BoardViewController) whose view has been added to the delegate as a subview.
The result is that my request to the protocol's method is not creating any errors, but the method is not triggered either. Would be most appreciated if someone has an idea. Thanks in advance!
BlockPopViewController.h
#import "DirectionViewController.h"
#class BoardViewController;
#protocol BVCProtocol
- (void)testing;
#end
#interface BlockPopViewController : UIViewController <BVCProtocol> {}
-(void)testing;
#end
BlockPopViewController.m
#implementation BlockPopViewController
-(void)testing{
NSLog(#"Testing in delegate BlockPopViewController");
}
#end
BoardViewController.h
#class BoardView; //This I cannot import, I think this should be ok instead. Probably cyclic import...
#class Bric; //This I cannot import, I think this should be ok instead. Probably cyclic import...
#protocol BVCProtocol;
#interface BoardViewController : UIViewController {
}
#property(nonatomic, assign) id <BVCProtocol> blockPopViewController;
#end
BoardViewController.m
#import "BlockPopViewController.h"
#import "BoardViewController.h"
#implementation BoardViewController
#synthesize blockPopViewController;
-(void)touchesEnded:(NSSet*)touches withEvent:(UIEvent *)event{
NSLog(#"INSIDE TOUCHESENDED");
[[self blockPopViewController] testing];
}

You are missing a declaration of your BlockPopViewController class which says that BlockPopViewController implements the BVCProtocol protocol.
You should also have your implementation of BVCProtocol derive NSObject in order to get proper memory management behavior. Additionally, you should derive all your protocols from the NSObject protocol in order to prevent compiler warnings when you use NSObject messages on instances of your protocol implementation.
In BlockPopViewController.h you need:
#protocol BVCProtocol <NSObject>
- (void) testing;
#end
#interface BlockPopViewController : UIViewController <BVCProtocol>
#end
In BoardViewController.h you must also #import "BlockPopViewController.h". Otherwise, the compiler won't know anything about the fact that BlockPopViewController is implementing BVCProtocol nor anything about BVCProtocol to begin with.
It would be more logical to declare a protocol in its own .h file and to import that in .h file declaring an implementation of the protocol.
You might find this little tutorial helpful.

Declare protocol outside #interface ... #end context
#protocol BVCProtocol
- (void) testing;
#end
#interface BlockPopViewController : UIViewController <BVCProtocol>
//...
#end

I think the problem I had was that I didn't create an instance of "BlockPopViewController". I changed my solution to not use protocols since it seems like overkill for me. I do have full controll of all involved classes and don't get any benefits using protocols. I do however think that this is what caused it to not work. If there is a reason for using protocols in this kind of situation which I am not aware of, pleas fill me in...

Also see Apple's Communicating with Objects, which discusses delegates, protocols, and selectors. Though its listed under Mac OS X, most (if not all) appears to apply to iOS also.

Related

In interface file: when to use forward declaration for custom class as opposed to just including its header?

I have subclass of UIViewController called FullScreenViewController which has a property of type ImageScrollView which is subclassed UIScrollView object. The implementation and interface look as follows:
FullScreenViewController.h
#import <UIKit/UIKit.h>
#class ImageScrollView;
#interface FullScreenViewController : UIViewController
{
ImageScrollView *_scrollView;
}
#property(nonatomic, retain) ImageScrollView *scrollView;
#end
FullScreenViewController.m
#import "FullScreenViewController.h"
#import "ImageScrollView.h"
#implementation FullScreenViewController
#synthesize scrollView = _scrollView;
...
#end
now I subclass FullScreenViewController, and I try to access any properties from the ImageScrollView property and I keep getting the error message: "Property cannot be found". When I add ImageScrollView.h to the subclass, it works, but I'm not understanding this. I've already added ImageScrollView.h in FullScreenViewController, why should I have to add it again?
UPDATE: Rather than using a forward class declaration, I've included ImageScrollView.h in FullScreenViewController.h. I'm a little confused as to why I've ever use a forward declaration versus just including the .h file?
The reason you need to add it is you only have a #class declaration in your FullScreenViewController.h file. That only declares variable of type ImageScrollView* as pointers to object of class ImageScrollView. It does not give you access to the properties of ImageScrollView. To get access to methods and properties specific to ImageScrollView, you need to include the #interface declaration of ImageScrollView, which I assume is in your ImageScrollView.h file.
Given the header:
#interface FullScreenViewController : UIViewController
{
ImageScrollView *_scrollView;
}
#property(nonatomic, retain) ImageScrollView *scrollView;
#end
a forward declaration #class ImageScrollView is all that's needed. This tells the compiler that there is an objc class named ImageScrollView.
Of course, with a forward declaration, the interface is not visible where you need to use it unless you also #import ImageScrollView where you use it.
now I subclass FullScreenViewController, and I try to access any properties from the ImageScrollView property and I keep getting the error message: "Property cannot be found". When I add ImageScrollView.h to the subclass, it works, but I'm not understanding this. I've already added ImageScrollView.h in FullScreenViewController, why should I have to add it again?
ImageScrollView's declaration is not visible to the subclass FullScreenViewControllerSubclass. ImageScrollView.h is visible only where #imported. FullScreenViewController.m is not visible to FullScreenViewControllerSubclass.m. Therefore, you must write another #import in FullScreenViewControllerSubclass.m to use ImageScrollView there.
UPDATE: Rather than using a forward class declaration, I've included ImageScrollView.h in FullScreenViewController.h. I'm a little confused as to why I've ever use a forward declaration versus just including the .h file?
Use forwards for fast build times and sane, controlled dependency structures. This is a very time consuming problem to undo. And this problem gets much worse as the size of your programs and libraries increase:
Would you prefer a change to a header in a medium sized project to require recompilation of 50 sources with an average preprocessed input of 150,000 lines per translation, or would you favor that change to affect 6 sources with an average preprocessed input of 40,000 lines per translation? The difference here is that small change takes the incremental rebuild from seconds to minutes to complete, depending on how you have structured your dependencies and imports.
Have you tried accessing it using the alias _scrollView or scrollView.you should access it using _scrollView and see if u have imported the file in .m or .h as #class won't suffice.

Unknown Expected identifier

I have taken over a project and am fairly new to cocotouch. I was looking throught the code trying to understand things. I didn't think I changed anything but when I went to run It came up with three build errors (it had run just a few minutes before with no problems). The second two seemingly related to the first:
#import <UIKit/UIKit.h>
#protocol MapViewDelegate; //Expected identifier or '(' before 'protocol'
#interface MapView : TTImageView
{
id<MapViewDelegate> mv_delegate; //Cannot find protocol declaration for 'MapViewDelegate'
}
#property (assign) id<MapViewDelegate> mv_delegate; //Cannot find protocol declaration for 'MapViewDelegate'
#end
#protocol MapViewDelegate <NSObject>
- (void)mapView:(MapView *)mv pressedAt:(CGPoint)point;
- (void)mapViewFinishedLoading:(MapView *)mv;
#end
I am using XCode4 which I have just switched to but have had working since the switch.
What is going on here?
MapKit.framework has been added to the project?

I can't declare this property in the .h file, can i do it in the .m?

I want to create a property out of a view which already has my class imported into it's own .h file, and therefore I cannot import it's .h file into my .h file because it causes problems. This means i have to put it's import into the .m file.
Putting this into the .m file:
View1 *view1;
works fine. But putting in a #property causes problems. I can't seem to find where best to put it to not cause an error. Is there a workaround to this?
You can put this in your #interface in your header file without importing View1.h. Just use a forward declaration like this:
#class View1;
#interface MyClass : NSObject {
}
#property (attrs) View1 *view1;
#end
You can also declare properties in your implementation (.m) file, if you ever need to, with a class extension like so:
#interface MyClass()
#property (attrs) View1 *somePrivateProperty;
#end
This is useful for other reasons, but not necessary in your case from what you've said. Think of it as a secondary #interface with properties and methods that you might want to hide from other classes which import "MyClass.h"
Hope that helps.

How can you conditionally include protocols during compiliation?

Is it possible to conditionally include a protocol? For example, below is some code that does not work, but should give you an idea what I'm referring to. I only want the interface AdWhirlDelegate to be included if ads are turned on.
// this works fine
#if ADS_SUPPORTED
#import "AdWhirlView.h"
#endif
// this does NOT work
#interface MyAppDelegate : NSObject <UIApplicationDelegate #if ADS_SUPPORTED ,AdWhirlDelegate #endif>
You could do:
#if ADS_SUPPORTED
#interface MyAppDelegate : NSObject <UIApplicationDelegate,AdWhirlDelegate>
#else
#interface MyAppDelegate : NSObject <UIApplicationDelegate>
#endif
...but then IB can get a little confused. See this answer, which presents an alternative to that.
That won't work
Repeat the interface declaration twice , one with the protocol and one without blocked inside the #if/#else/#endif structure
Preprocessor directives will only work in a non nested way like your header include.

How to conform to a self-made protocol?

I have a class with an delegate property. Anyone who wants to be a delegate must conform to a protocol. I defined everything like this:
#import <UIKit/UIKit.h>
#protocol TheDelegateProtocol;
#interface MyClass : UIView {
id<TheDelegateProtocol> theDelegate;
}
#property (nonatomic, assign) id<TheDelegateProtocol> theDelegate;
#end
#protocol TheDelegateProtocol<NSObject>
#required
- (void)fooBarWithFoo:(CGFloat)foo;
#end
Now the crazy thing is: I have another class that wants to be the delegate. So it conforms to that protocol, like this:
#import <Foundation/Foundation.h>
#class MyClass; // forward declaration. importet in implementation.
#protocol TheDelegateProtocol; // need forward declaration here, right?
#interface OtherClass : NSObject <TheDelegateProtocol> {
// ivars
}
#end
I can't get that to work. It says: "No definition of protocol 'TheDelegateProtocol' found". Well, that protocol is defined in MyClass, and I am importing MyClass in the implementation. Any idea what's wrong there?
Figured out something: In a method where I try to assign the protocol, it is telling me, that OtherClass does not conform to the protocol. But it does! That makes no sense. I also added the protocol method in the header....
Put the definition of the protocol in a separate file.
#import that file into any header file that needs it.
I think you need to #import the header file that defines the protocol. How can the compiler know which methods are available without it?
If you use another class (i.e., as an ivar or as a parameter to a method) then you can use a forward declaration. But if you subclass then you need to #import.
The compiler's warning is correct. OtherClass doesn't conform to the protocol because it doesn't declare the required fooBarWithFoo method that the protocol expects.
Have you tried it this way?
#import "MyClass.h"
#interface OtherClass : NSObject <TheDelegateProtocol> {
// ivars
}
- (void)fooBarWithFoo:(CGFloat)foo; // <<< missing bit
#end
He doesn't need to declare the methods to conform to the protocol. He only need to implement them in the .m file.
Is this a warning? because sometimes it does that when you have circular references and stuff, and it gets confused, but in reality its ok, have u tried running it to see if it works? In my project i have a bunch of warning about protocols not found, they are there though and it works fine... What you can do to get rid of the warning is try defining the protocol outside the class on some other .h file. You also dont really need the forward declaration, you can just do #import of the .h file its defined in
Your two classes differ in their use of the protocol.
MyClass does not implement the protocol, it has an attibute that is a pointer to a class that implements the protocol.
OtherClass should implement the protocol.
OtherClass needs to have available before its interface is defined all the details of the protocols, interfaces and classes that it inherits from. Thus you need the protocol in a header to be #imported in OtherClass.h
MyClass just needs to know the protocol exists in its interface.
Note on Stephen's reply subclassing is the case you can't use forward declarations of classes. (In the example OtherClass is a subclass of NSObject)
Also see Apple's Communicating with Objects, which discusses delegates, protocols, and selectors.