#import "MPOContactAuthorizationManager.h"
#protocol MPOContactAuthorizationManagerDelegate <NSObject>
- (void)authorizationManger:(MPOContactAuthorizationManager *)manager
didUpdateContactState:(ContactsState)contactState;
#end
MPOContactAuthorizationManager and ContactState are not resolving to types even though they are declared in MPOContactAuthorizationManager:
#import "MPOContactAuthorizationManagerDelegate.h"
typedef enum _contactsState {
kContactsStateUnknown,
kContactsStateAllowed,
kContactsStateDisallowed
} ContactsState;
#interface MPOContactAuthorizationManager : NSObject <UIAlertViewDelegate> {
ContactsState _contactsAuthorizationState;;
}
#property (strong, nonatomic) NSObject<MPOContactAuthorizationManagerDelegate> *delegate;
#property (nonatomic) ContactsState contactsAuthorizationState;
Any ideas as to why these are not resolving? Both are getting the error "Expected a type"
Thanks
Mike
You have a circular dependency. Update the MPOContactAuthorizationManagerDelegate.h header by getting rid of the #import line and adding the following:
#class MPOContactAuthorizationManager;
just before the #protocol line.
Just put both in one .h file (you still need the forward declaration for MPOContactAuthorizationManager):
typedef enum _contactsState {
kContactsStateUnknown,
kContactsStateAllowed,
kContactsStateDisallowed
} ContactsState;
#class MPOContactAuthorizationManager;
#protocol MPOContactAuthorizationManagerDelegate <NSObject>
- (void)authorizationManger:(MPOContactAuthorizationManager *)manager
didUpdateContactState:(ContactsState)contactState;
#end
#interface MPOContactAuthorizationManager : NSObject <UIAlertViewDelegate> {
ContactsState _contactsAuthorizationState;;
}
#property (strong, nonatomic) NSObject<MPOContactAuthorizationManagerDelegate> *delegate;
#property (nonatomic) ContactsState contactsAuthorizationState;
Replace the import of "MPOContactAuthorizationManagerDelegate.h" from MPContactAuthorizationManager.h by using a forward declaration of the protocol:
#protocol MPOContactAuthorizationManagerDelegate;
typedef enum _contactsState {
kContactsStateUnknown,
kContactsStateAllowed,
kContactsStateDisallowed
} ContactsState;
#interface MPOContactAuthorizationManager : NSObject <UIAlertViewDelegate> {
ContactsState _contactsAuthorizationState;;
}
........
You need to choose this import scheme as you are referring to a user defined type (the ContactsState type) in the protocol's header - so this header needs to import the manager's header. In the manager's header, however, you only refer to the protocol as the types of the method parameters, so you can legally forward-declare here.
In general, you should only import one header from another in a few cases:
Declaring a class in your header that's a subclass of a class defined in the other header
Referring to user defined types (e.g. via a typedef) in your header that are defined in the other header
Declaring a class in your header as conforming to a protocol declared in another header
Declaring a category in your header for a class defined in another header
I think I'm forgetting one, so saving this space for that one.
Also - read this enlightening answer.
The more common case of needing protocol and class names in public method parameters and properties can be accomplished using forward declarations with #class and #protocol. Although, if it were me, I'd keep the protocol declaration in the same header as the authorization manager - seems more convenient that way. Note that you will need to do a forward-declaration within the file for this. For example:
typedef enum _contactsState {
kContactsStateUnknown,
kContactsStateAllowed,
kContactsStateDisallowed
} ContactsState;
//forward-declare the protocol before referencing it in the file
#protocol MPOContactAuthorizationManager;
#interface MPOContactAuthorizationManager : NSObject <UIAlertViewDelegate> {
ContactsState _contactsAuthorizationState;;
}
#property (strong, nonatomic) NSObject<MPOContactAuthorizationManagerDelegate> *delegate;
#property (nonatomic) ContactsState contactsAuthorizationState;
........
#end
// Provide the real protocol declaration.
#protocol MPOContactAuthorizationManagerDelegate <NSObject>
- (void)authorizationManger:(MPOContactAuthorizationManager *)manager
didUpdateContactState:(ContactsState)contactState;
#end
Related
I have a class written in Swift where I've defined a protocol:
protocol PhotoIngestionDelegate {
func pictureTaken()
}
I am trying to have a class (CameraViewController) written in Objective-C conform to this protocol.
CameraViewController.h:
#import <GSSDK/GSSDK.h>
#protocol PhotoIngestionDelegate;
#interface CameraViewController : GSKCameraViewController <PhotoIngestionDelegate>
#end
CameraViewController.m:
#import "CameraViewController.h"
#import <GSSDK/GSSDK.h>
#import "EditFrameViewController.h"
#import "Scan.h"
#interface CameraViewController<PhotoIngestionDelegate> ()
#property (nonatomic, strong) UIView *toolbar;
#property (nonatomic, strong) UIButton *cameraButton;
#end
#implementation CameraViewController
...
The implementation in CameraViewController.m continues, but I cut it off to keep it brief. I know that I need to define the function pictureTaken() in CameraViewController.m, but I can't seem to get the delegate hookup to work. In CameraViewController.h I am getting that it Cannot find protocol definition for 'PhotoIngestionDelegate'.
Try this
#objc protocol PhotoIngestionDelegate {
}
At first, in LoadingVC.h I declare a protocol:
#protocol VideoWorker <NSObject>
#required
#property (nonatomic) float progress;
#property (nonatomic) BOOL done;
-(void)beginWorking;
#end
#interface LoadingVC : UIViewController <UIAlertViewDelegate>
...
#end
then in BlurWorkerGPU.h
...
#import "LoadingVC.h"
#interface BlurWorkerGPU : NSObject <VideoWorker> {
...
}
- (void)beginWorking;
#property(nonatomic)float progress;
#property(nonatomic)BOOL done;
...
#end
However, llvm says that
"No type or protocol named 'VideoWorker'"
which is strange since I am importing the header where the protocol is defined. Any clues?
You should forward declare protocol in .h files before you use it. Put this in the top of BlurWorkerGPU.h
#protocol VideoWorker;
check whether you are importing "BlurWorkerGPU.h" in "LoadingVC.h"
Possible solutions are
import protocol
#import
YOURPROTOCOLNAME
import Class in which protocol is declared
#import "YOURCLASSWHICHDECLAREDPROTOCOL.h"
Use #Class to import the class
#class YOURCLASSWHICHDECLAREDPROTOCOL;
//Super class .h file
#interface MySuperClass : NSObject
#end
//Super class .m file
#interface MySuperClass ()
#property (nonatomic, strong) UITextField *emailField;
#end
#implementation MySuperClass
-(void)accessMyEmailField {
NSLog(#"My super email: %#", self.emailField.text);
}
#end
// ********** my subclass *******
//Subclass .h file
#interface MySubClass : MySuperClass
#end
//SubClass .m file
#interface MySubClass ()
#end
#implementation MySubClass
-(void)myEmail {
NSLog(#"My subclass email: %#", self.emailField.text);
}
-(void)setMyEmailFromSubclass{
self.emailField.Text = #"email#gmail.com"
}
#end
How do i access emailField in -(void)myEmail method.
How do i set email in Subclass -(void)setMyEmailFromSubclass; , and access it in super class accessMyEmailField
You can put accessors to these properties in a second header file, and import that file on a 'need-to-know' basis..
eg
mySuperClass+undocumentedProperties.h
#import "mySuperClass.h"
#interface mySuperClass(undocumentedProperties)
#property (nonatomic, strong) UITextField *emailField;
#end
mySuperClass.m
#import "mySuperClass+undocumentedProperties.h"
#interface mySuperClass()
///stuff that truly will be private to this class only
// self.emailField is no longer declared here..
#end
#implementation mySuperClass
#synthesize emailField; //(not really needed anymore)
/// etc, all your code unaltered
#end
mySubclass.h
#import "mySuperClass.h"
#interface mySubclass:mySuperClass
///some stuff
#end
mySubclass.m
#import "mySubclass.h"
#import "mySuperClass+undocumentedProperties.h"
#implementation
//off you go, this class is now 'aware' of this secret inherited property..
#end
obviously MySuperClass.m will have to import this .h file as well as its default one (or actually instead of, the default one is built in to this one), but your subclasses can import it too (directly into their .m file, so these properties remain private to the class. This is not a proper category because there is no corresponding mySuperClass+undocumentedProperties.m file (if you tried that you could not synthesize the backing iVars for these secret properties. Enjoy :)
Copy the private interface portion of the methods you want from your superclass - or in other words, in your Subclass.m file you would put:
#interface MySuperClass ()
#property (nonatomic, strong) UITextField *emailField;
#end
( place it above the existing #interface MySubClass () code )
Now your subclass knows that method exists in the superclass and can use it, but you are not exposing it to anyone else.
The whole point of private properties is exactly that and you should not want to access them. Because they are private they can change or be removed thus breaking the subclass that relies on them.
That being said they are not really private, just not "published". The can be called because Objective-C is a run-time dynamic language.
i've worked with delegation before. i know how to create delegation from a superview to a subview class. however, i'm trying to do it the opposite way using the same approach but it's not working! is delegation meant only to work one way or is there a way/trick to use it as a two way communication between the classes? I'm receiving an error at the parent/superview .h class which is:
Cannot find protocol definition for 'SubViewControllerDelegate'
my code goes like this:
subview.h
#import <UIKit/UIKit.h>
#import "SuperViewController.h"
#protocol SubViewControllerDelegate <NSObject>
- (void)someMethod:(NSData *)data;
#end
#interface SubViewController : UIViewController
#property (weak, nonatomic) id <SubViewControllerDelegate> delegate;
#end
subview.m:
[self.delegate someMethod:data];
SuperView.h
#import <UIKit/UIKit.h>
#import "SubViewController.h"
#interface SuperViewController : UIViewController <SubViewControllerDelegate>
#end
SuperView.m:
#pragma mark - SubView Controller Delegate Methods
- (void)someMethod:(NSData *)data{
NSLog(#"%#", data);
}
am i doing anything wrong or missing out anything?
You have an "import-cycle", because "SuperViewController.h" imports "SubViewController.h" and vice versa.
Removing the #import "SuperViewController.h" in "SubViewController.h"
should solve the problem.
If you really need that class to be declared in "SubViewController.h", use
#class SuperViewController; to avoid the import-cycle.
Remark: The <SubViewControllerDelegate> protocol declaration is probably not
needed in the public interface "SuperViewController.h" at all.
In "SuperViewController.h", declare the class as
#interface SuperViewController : UIViewController
In "SuperViewController.m", define a class extension with the protocol:
#interface SuperViewController () <SubViewControllerDelegate>
#end
Sorry if this is stupid... but it confuses me?...
I'm trying a new storyboard app with Xcode and just asked myself why there is a second declaration of the #interface in my implementation file?
.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController {
}
#end
.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
....
#end
See Apple's documentation: https://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocCategories.html
It's a class extension, subtly different from a category, since it has no name inside the parentheses. You use it for declaring properties and methods that are intended to be kept private (out of the header), and redeclaring publicly read-only properties and methods as privately read-write. This allows for cleaner encapsulation.
By request, a friendly example:
JYDuckPondManager.h
#interface JYDuckPondManager : NSObject
#property (nonatomic, assign, readonly) NSUInteger duckCount;
#property (nonatomic, assign, readonly) CGFloat waterLevel;
- (JYDuckReaction *)feedDucks:(JYDuckFood *)food;
- (JYDuckReaction *)harassDucks:(JYDuckTaunt *)taunt;
#end
JYDuckPondManager.m (extension, imaginary implementation omitted)
#interface JYDuckPondManager ()
//// Redefined for internal modification
#property (nonatomic, assign, readwrite) NSUInteger duckCount;
#property (nonatomic, assign, readwrite) CGFloat waterLevel;
//// Internally exclusive properties
#property (nonatomic, strong) NSSet *duckPersonalitySet;
#property (nonatomic, assign) CGFloat flockAnxietyLevel;
//// Private messages
- (void)recalculatePondState;
#end
Other objects should be able to interact with the pond, but they're not supposed to know certain things going on in the pond or redefine the pond's statistics. Keeping nuts-and-bolts stuff in the .m extension ensures that the .h is concise and appropriately limited.
The second #interface block in the .m file is an extension. You could add declarations for methods and instance variables you want to use internally within your class.
The second interface #interface ViewController () is a class extension which is like an anonymous category. A class extension is declared like a category only without a name. Declarations found in these extensions directly extend the declarations found in the class’s primary #interface and can sometimes (in some situations) override declarations found in the primary interface.