In cocoa2.0 does #property obviate variable declaration in the interface - cocoa

Just experimenting with #property and #synthesize:
#interface Greeter : NSObject
//{
// NSString * name;
//}
#property (assign) NSString * name;
- (NSString *) greeting;
#end
It seems to be the case that if you declare a variable using #property that you don't have to declare it between the braces (and you don't even need the braces if all of your interface variables are all declared using #property). Is this always correct? And is it good style to leave out the top part of the interface (braces included)? I have been using both and been irritated by the redundancy.

There is no “Cocoa 2.0”.
In Objective-C 2.0, on the modern runtime, yes, you can leave out the instance variables, and the property will generate them for you. The legacy runtime on Mac OS X still requires explicit instance variables.
You cannot leave out the ivar section entirely yet, but you can leave it empty.

Here is the webpage where I first found out you can automatically have you properties synthesized and also declare new properties in class extensions. It gives a bit of interesting back story as well.
http://www.mcubedsw.com/blog/index.php/site/comments/new_objective-c_features/
As for style and correctness, I've been using primarily properties for the last couple of weeks and it has made my code look quite clean! I can now declare private properties in my implementation and not have them exposed in the header making any interface to use my classes very simple and non-confusing to use.
I've ran into a problem when using interface builder where having an iVar to any subviews of a view controller still has to be declared in the header for interface builder to see it as an IBOutlet and assign to it. You can still declare those #private though and then have the private properties declared in a class extension in your implementation if you really want it as a property for you to use.
// In your header
#interface MenuViewController : UIViewController {
#private
IBOutlet UIButton *buttonPeopleShouldNotKnowAbout;
}
#end
// And in your implementation
#implementation MenuViewController ()
#property (nonatomic, readwrite, assign) IBOutlet UIButton *buttonPeopleShouldNotKnowAbout;
#end

Related

delegate works in xcode 5 but not in xcode 6

#property (unsafe_unretained,nonatomic) id<SceneDelegate> delegate;
it works fine on xcode 5, but it gives me this error on xcode 6.1
Error: Property type 'id<SceneDelegate>' is incompatible with type 'id<SKSceneDelegate>' inherited from 'SKScene'
what's that mean?
Addition:
beginning of scene.h
#protocol SceneDelegate <NSObject>
- (void) eventStart;
#end
#interface Scene : SKScene<SKPhysicsContactDelegate>
#property (unsafe_unretained,nonatomic) id<SceneDelegate> delegate;
viewController.h
#import "Scene.h"
#import <AVFoundation/AVFoundation.h>
#interface ViewController : UIViewController<SceneDelegate, AVAudioPlayerDelegate>
viewController.m
scene.delegate = self;
That's all the lines contain SceneDelegate.
It means SKScene already has a property of the same name: delegate
You are trying to redeclare that property but with a different protocol: SceneDelegate instead of SKSceneDelegate.
So either you wanted to use the delegate property, in that case you needn't declare that property, just assign your SKSceneDelegate object to the delegate property. For example:
self.delegate = mySceneDelegateObject;
Otherwise use a different name instead of delegate if SceneDelegate is an actual protocol you created (and consider renaming the protocol because it's easily confused with SKSceneDelegate).

C4 passing image between subclasses

I'm trying to pass an image between 2 different views that are added as subclasses to the MainCanvasController.
the image seems to get passed (it is shown, when printed to the Console) but it doesn't display anything...
this is how I try to receive and display the image
-(void)receiveNumber:(C4Image*)number{
C4Log(#"number:%#", number);
number.center=self.canvas.center;
[self.canvas addImage:number];
receivedImage=number;
C4Log(#"received number: %#", receivedImage);
}
and here is how I post the image
[secondView receiveNumber:originalImage];
I don't really know what's going wrong. (well, honestly, I don't know at all...) So any hints are very much appreciated!
I had a look at your project and found the answer.
Your FirstView object has a variable called secondView, which is exactly the same name as the object in your main workspace. However, despite having the same name both of these are different objects.
I've done a couple things:
1) instead of using variables in the interface file for your objects, use properties.
2) create a SecondView property in your FirstView class
3) set the property of firstView to the same object in your workspace, secondView
My FirstView.h looks like:
#interface FirstView : C4CanvasController{
C4Label *goToSecondView;
}
#property (readwrite, strong) C4Window *mainCanvas;
#property (readwrite, strong) C4Image *postedImage;
#property (readwrite, strong) SecondView *secondView;
#end
My postNoti: looks like:
-(void)postNoti{
C4Log(#"tapped");
[self postNotification:#"changeToSecond"];
[self.secondView receiveNumber:self.postedImage];
}
NOTE I got rid of the [SecondView new]; line.
The following is the part that you were missing
My workspace has the following line:
firstView.secondView = secondView;
Which sets the variable of the first view to have a reference to the secondView object.
You hadn't done this, and so you were passing the image to an object that had the same name as the view that's visible from your main workspace's canvas.

Expected Identifier or "(" before "{" token

Somehow I got this error in XCode 4.0.2, not sure what is wrong.
File: HomeViewController.h
#import <UIKit/UIKit.h>
#interface HomeViewController : UIViewController <UITabBarDelegate>
{
UIButton *Button1, *Button2, *Button3;
}
#property (nonatomic, retain) IBOutlet UIButton *Button1;
#property (nonatomic, retain) IBOutlet UIButton *Button2;
#property (nonatomic, retain) IBOutlet UIButton *Button3;
.... other member functions...
....
#end
File: HomeViewController.m
......
#import "RemoteServiceManager.h"
#interface HomeViewController()
{ //This is where the error happens: Expected Identifier or "(" before "{" token
RemoteServiceManager* serviceManager;
}
#end
#implementation HomeViewController
#synthesize Button1, Button2, Button3;
.... other member functions
....
#end
Looks like it does not recognize RemoteServiceManager. Wherever I used the serviceManager, it will say HomeViewController has no member named serviceManager.
Is it possible that is caused by XCode version? I am using XCode 4.0.2 on Mac OS X 10.6.7.
Thanks.
you cant add instance variables to private categories.
put properties in there instead, and synthesize them to obtain a variable as well as an internal getter/setter
#interface HomeViewController
#property (nonatomic, strong) NSString *privateProperty;
#end
#implementation HomeViewController
#synthesize privateProperty = _privateProperty;
#end
or you can add the instance variable to the class itself.
#implementation HomeViewController
NSString *privateVariable;
#end
Bear in mind also. that if you create a category in another file, any variables you declare in the body of that category will be static across all instances. definitely something to keep an eye out for.
To recap. you can create a variable in the interface of the main category. or in the implementation of the main category.
and the private category is for you to add prototypes to your class that will let the rest of the file know they "will be/are" available.
the old xcode cant do this, no. it does know class extensions yet because it ships with an older version of the LLVM compiler
You probably found your answer, but I post the answer here for somebody who encounters the same problem:
as Daij said, the problem is due to the version of compiler, so to fix this you need to change the compiler setting:
Build Setting > Build Options > Compiler for C/C++/ObjectiveC
Change value from "LLVM GCC 4.2" to "Apple LLVM compiler 4.2"
Hope it helps.

Avoid method not found for protocol methods

My Cocoa AppDelegate contains a reference of type ID to it's main view. The reference is polymorphic because it may point to a subclass of PDFView or a subclass of NSImageView, depending on the origin of the view's image. Both view subclasses implement the same protocol, so my AppDelegate does not have to know what type of view it's dealing with. However, every time I call one of the protocol methods I get a warning that says "Instance method '-methodName' not found (return type defaults to 'id')". I can either ignore the warning or force the issue by using "performSelector:(#selector(methodName:)" to call the protocol method.
Is there something I can do (or should have done) to eliminate the warning without resorting to performSelector?
//FLAppDelegate.h
#interface FLAppDelegate : NSObject <NSApplicationDelegate>
{
...
IBOutlet id _formImageView; //type is FLPDFView* or FLImageView*
…
}
//FLFormImageProtocol.h
#protocol FLFormImageProtocol <NSObject>
#required
- (void) methodName;
#end
//FLPDFView.h
#interface FLPDFView : PDFView <FLFormImageProtocol>
#end
//FLImageView.h
#interface FLImageView : NSImageView <FLFormImageProtocol>
#end
Type the instance variable with the protocol:
IBOutlet id<FLFormImageProtocol> _formImageView;

How to prevent retain cycles caused by binding to self

I have an application where I need to access model data from my subviews. I've been using bindings to pass data across views; however, the bindings to self seem to be causing retain cycles (dealloc never gets called). When should I remove the bindings if not in the dealloc method? Thanks.
P.S. I know the method of binding to a proxy object controller, but I'd like to avoid using it if possible.
Here's an example of what I've been doing:
// Top-level Project view
#interface ProjectViewController : NSViewController {
FoldersView *foldersView;
}
#property (strong) NSObjectController *projectObjectController; // holds Project instance
end
// Displays folders
#interface FoldersView : NSView {
FolderView *folderView;
}
#property (weak) NSObjectController *projectObjectController; // binded from parent
#property (strong) NSArrayController *foldersArrayController; // binded to project.folders
#end
// Displays selected folder
#interface FolderView : NSView
#property (weak) NSArrayController *foldersArrayController; // binded from parent
#property (strong) NSObjectController *folderObjectController; // binded to folders.selection
#end
The bindings are the preferred way of removing C part (boilerplate code) from the MVC trinity. So your approach to handling this problem is correct.

Resources