I am making a photo upload to Facebook app and I think I need two #interfaces in my .h file for my View Controller.
Here is my ViewController.h file.
#import <UIKit/UIKit.h>
#import <Social/Social.h>
#interface FirstViewController : UIViewController <UIImagePickerControllerDelegate, UINavigationControllerDelegate> {
UIImagePickerController *bailey;
UIImagePickerController *baileys;
UIImage *image;
IBOutlet UIImageView *imageView;
}
- (IBAction)TakePhoto;
- (IBAction)ChooseExisting;
#end
#interface FirstViewController : UIViewController { SLComposeViewController *slComposeViewController;
UIImage *image; }
- (IBAction)ShareFB;
#end
When I try to build this code on to my iPhone or a Emulator it says
/Users/Condrum/Desktop/project/myApp/myApp/FirstViewController.h:21:1: Duplicate interface definition for class 'FirstViewController'
Thanks in advance for the help.
-Condrum.
The pattern is to put a single public interface into the .h file:
#interface FirstViewController : UIViewController
// in here put those public properties and method declarations that
// other classes need to have access to
#end
Then put the second #implementation in the .m file as a private class extension:
#interface FirstViewController () <UIImagePickerControllerDelegate, UINavigationControllerDelegate>
// in here, place those private properties and instance variables that
// only this class needs to be aware of
#end
Note, this second interface uses the () syntax, which indicates that the interface is extending a previously defined interface.
But there's no point in putting both of those interfaces in the same .h file (why have two interfaces; it would be more logical to combine them into one). The primary value of the private class extension is you can extend your interface with details that only the implementation cares about, and avoid cluttering your nice simple public interface. So generally, keep public interface in the .h file, and move the private stuff into the class extension in the .m file.
For more information, see Class Extensions Extend the Internal Implementation.
Related
I started writing Swift extensions on my view controllers. So I have three files right now:
My header file, ViewController.h:
#interface MyViewController : UIViewController
#end
My Obj-C implementation file, ViewController.m:
#interface MyViewController () <UIScrollViewDelegate>
#property (strong, nonatomic) UIScrollView *scrollView;
#end
#implementation MyViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.scrollView = [[UIScrollView alloc] init];
[self customiseScrollView]; //This is Swift method called from Obj-C file
}
#end
And finally, ViewController.swift:
extension MyViewController {
func customiseScrollView() {
}
}
My question is, is it possible to access my Obj-C properties from my Swift implementation file? Every time I refer to it, I got an error:
Value of type 'MyViewController' has no member 'scrollView'
Bonus 1: Can someone also clarify if the Swift component can see what the .m is a delegate of as well. (To clarify, doing scrollView.delegate = self in Swift is a compile error because the Swift file does not realise that the .m file is a UIScrollViewDelegate).
Bonus 2: Can Swift extension file call Obj-C methods that are declared from the .m counterpart?
I think that you can't access private properties from extension. Your scrollView property is in .m file, not .h - which means it's private and it's not visible from extension file.
Solution: move
#property (strong, nonatomic) UIScrollView *scrollView;
to your header file.
You can access internal objc properties and methods if you declare the objc class extension in a separate header and include that header in the bridging header.
MyClass.h
#interface MyClass : NSObject
#property (nonatomic, copy, readonly) NSString *string;
#end
MyClass+Private.h
#import "MyClass.h"
#interface MyClass ()
#property (nonatomic, copy) NSString *string;
#end
MyClass.m
#import "MyClass+private.h"
#implementation MyClass
//...
#end
Project-Bridging-Header.h
#import "MyClass.h"
#import "MyClass+Private.h"
In Swift, private properties are not accessible from another file. This is the meaning of private in Swift. For example:
file1.swift
class MyClass {
private var privateProperty: String = "Can't get to me from another file!"
}
extension MyClass: CustomStringConvertible {
var description: String {
return "I have a `var` that says: \(privateProperty)"
}
}
file2.swift
extension MyClass {
func cantGetToPrivateProperties() {
self.privateProperty // Value of type 'MyClass' has no memeber 'privateProperty'
}
}
A property declared in the implementation of an Objective-C class is a private property. As such, the property cannot be accessed from a Swift extension since this will be necessarily from a different (.swift) file...
You can. All you need is to create a bridging objective C header.
Per Apple Documentation:
To import a set of Objective-C files in the same app target as your
Swift code, you rely on an Objective-C bridging header to expose those
files to Swift. Xcode offers to create this header file when you add a
Swift file to an existing Objective-C app, or an Objective-C file to
an existing Swift app.
Just create a Bridging-Header file and later import your ObjC file in it, like:
#import <objectivec.h>
Later in your swift file:
var a = objectivec()
a.method_from_those_file
For more information read Apple Doucmentation from here.
-(IBAction)ok
{
//send message to the delegate with the new settings
[self.delegate setHeight:_height Width:_width Mines:_mines];
[self.delegate dismissViewControllerAnimated:YES completion:nil];
}
the first message to the delegate wouldn't work until i imported ViewController.h, but the second one worked without the import.
if i add -(void)setHeight:(int)h Width:(int)w Mines:(int)m; as required in the optionsViewController protocol will that mean that i no longer have to import the root .h file.
i intend to use delegation to send messages in other parts of the program so i want to make sure i am using it correctly and not importing things when i don't need to.
Thank you.
if i add -(void)setHeight:(int)h Width:(int)w Mines:(int)m; as required in the optionsViewController protocol will that mean that i no longer have to import the root .h file.
Yes! You could also add it as #optional and it would work (remember to check if the delegate -respondsToSelector: in that case). The whole idea is that your object regularly knows nothing about the delegate object - except that it conforms to the protocol (ie implements the #required and possibly the #optional methods).
Added for clarification (on my phone, which is a pain in the butt):
//OptionsViewController.h
//this object does NOT have to import
//the calling viewControllers .h file
//which is what I think the OP does
#protocol optionsViewControllerProtocol;
#interface OptionsViewController : UIViewController
#property (nonatomic, assign) id<optionsViewControllerProtocol> delegate; //should be id, could be UIViewController too, if absolutely necessary (better design to make it id)
#end
#protocol optionsViewControllerProtocol <NSObject>
#required
-(void) setHeight: (NSInteger) height;
#end
//viewController.h
#import "optionsViewController.h" //necessary to get the protocols definitions
#interface OptionsViewController: UIViewController <optionsViewControllerProtocol>
//.....
If you define your delegate property to be of class UIViewController*, then the compiler will recognize the dismissViewControllerAnimated:completion: method without you needing to import anything, since that's a standard method for that class.
For a custom method, i.e. setHeight:Width:Mines:, you absolutely need to import the header file, or have it imported somewhere up the import chain.
Example: You have MyProtocol.h, and you want SomeClass to have a delegate property that conforms to that protocol. If you #import "MyProtocol.h" in SomeClass.h, you don't need to re-import it in SomeClass.m.
// SomeClass.h
#import "MyProtocol.h"
#interface SomeClass : NSObject
#property (weak, nonatomic) id<MyProtocol> delegate;
#end
//SomeClass.m
#import "SomeClass.h"
#implementation SomeClass
- (void)someMethod
{
[self.delegate myProtocolMethod];
}
#end
My view controller is getting a little large for me. I'm implementing five delegate protocols and was about to add a sixth.
ABCViewController : UITableViewController<NSFetchedResultsControllerDelegate,
UITableViewDelegate,
UITableViewDataSource,
UIAlertViewDelegate,
CLLocationManagerDelegate>
One controller to implement them all seems ridiculous, but they aren't being used anywhere else. Should these be in their own classes or in the view controller?
You could add categories to ABCViewController, like this:
1. Move any declarations in ABCViewController.m into a private category in ABCViewController.h
// in ABCViewController.h
#interface ABCViewController : UIViewController <delegates>
// anything that's in the _public_ interface of this class.
#end
#interface ABCViewController ()
// anything that's _private_ to this class. Anything you had defined in the .m previously
#end
2. ABCViewController.m should include that .h.
3. Then in ABCViewController+SomeDelegate.h and .m
// in ABCViewController+SomeDelegate.h
#interface ABCViewController (SomeDelegateMethods)
#end
// in ABCViewController+SomeDelegate.m
#import "ABCViewController+SomeDelegate.h"
#import "ABCViewController.h" // here's how will get access to the private implementation, like the _fetchedResultsController
#implementation ABCViewController (SomeDelegateMethods)
// yada yada
#end
You can also declare conformity to that protocol in the .m file like this:
#interface ABCViewController (NSFetchedResultsControllerDelegateMethods) <NSFetchedResultsControllerDelegate>
#end
#implementation ABCViewController (NSFetchedResultsControllerDelegateMethods)
...
#end
This won't make your file shorter but at least it will be clearly divided into parts
If you are using Xcode you can try something like this for example:
#pragma mark - NSFetchedResultsControllerDelegateMethods
Quite handy to find your methods like in this tip: Pragma mark
Alternatively, depending on what you do the delegate methods and how structured is your code you could have another object that has only methods of the delegate protocol
#interface Delegate <NSFetchedResultsControllerDelegate> : NSObject
#end
You would have an instance of this object as an ivar in your ABCViewController.
When you start a SplitViewController-based project for the iPad, it creates a DetailViewController. In DetailViewController.h, it declares the interface as normal:
#interface DetailViewController : UIViewController <UIPopoverControllerDelegate, UISplitViewControllerDelegate> {
UIPopoverController *popoverController;
UIToolbar *toolbar;
id detailItem;
UILabel *detailDescriptionLabel;
}
Then, in the implementation file (DetailViewController.m), it declares some other parts of the interface:
#interface DetailViewController ()
#property (nonatomic, retain) UIPopoverController *popoverController;
- (void)configureView;
#end
Why do they do this? What is the point of declaring the interface in two different places/files?
They've created a private category. The methods defined in the .m are only supposed to be used within the .m and are not part of the advertised interface into the DetailViewController. External users of the controller are only expected to call those methods defined in the .h, internal users can also use those in the private category. It is common to also see
#interface DetailViewController (Private)
It's to extend the standard interface with extra methods that you can implement for that specific implementation so that the compiler knows about them.
See Apple's documentation on class extensions for details.
The first is the public interface while the second is a "class continuation" and contains private methods.
How can you use circular #import to strongly typed objects in objective-c
I have an audio controller class, a menu class and a gameview class.
The application delegate sets up these classes and assigns a pointers so:
the menu class is aware of the audio and gameview class
the gameview class has a reference to the audio and menu class
I am using NSObject for the reference to the gameview class from the menu class. This is because the menu class has a reference to the gameview class and has a #import gameview.h declaration. The code won't compile with circular #import
Suggestions please :) ?
#interface MenuViewController : UIViewController {
NSObject *gameref; // weak type here to avoid include of gameview above
AudioController *audioref;
}
and...
#import "AudioController.h"
#import "MenuViewController.h"
#interface GameViewController : UIViewController {
MenuViewController *menuref;
AudioController *audioref;
}
Fisrt, in your .h file use
#class GameViewController, AudioController
and
#class AudioController, MenuViewController
in your .m file use
#import "GameViewController"
#import "AudioController"
and
#import "AudioController.h"
#import "MenuViewController.h"
There is no 'circular reference' problem.
Second, using NSObject instead of the actual classname isn't in any way a weak reference. Also, if you mean #include say #include. If you mean #import, say #import.