NSStringFromPoint disappears under Objective-C++ - iphone

The function NSStringFromPoint disappears when I compile my code using objective-C++, but it's fine under objective-C.
How can I make objective-C++ see that function?
If I compile under Objective-C++ it says:
error: 'NSStringFromPoint' was not declared in this scope
error: 'NSStringFromRect' was not declared in this scope
error: 'NSEqualSizes' was not declared in this scope

Someone can correct me if I'm wrong, but if you're linking against the iPhone SDK, there is no NSPoint or NSStringFromPoint. UIKit uses the Core Graphics structs CGPoint, CGSize and CGRect. The equivalent function would be NSStringFromCGPoint.
The Simulator libraries do not quite match up with the iPhone libraries -- I'm fairly certain applications compiled for the simulator link against the Mac's own Foundation.framework. For example, I wasted a lot of time in the pre-2.0 days thinking that NSXMLDocument was available on iPhone because it compiled and ran in the simulator.

I compiled this simple application:
#include <Cocoa/Cocoa.h>
int main (void)
{
NSLog (#"%#", NSStringFromPoint(NSMakePoint(10, 10));
return 0;
}
Using this command line:
gcc -x objective-c++ test.mm -framework Cocoa -lstdc++
And I got this output (ignoring the error about no autorelease pool in place):
2010-05-12 12:41:33.946 a.out[290:10b] {10, 10}
Make sure you're including the right headers, at the very least, make sure you're importing <Foundation/Foundation.h>. An explicit #import <Foundation/Foundation.h> will do no harm if it has already been included.

Related

What does the '#' symbol mean in Swift?

I have no experience in objective C, so I'm having trouble with some of the notation. In my "AppDelegate.swift" file, there is a "#UIMainApplication" at the top. What does this mean?
Also, if possible, could you please give me the "equivalent" statement (if it exists) in C++?
Thanks.
Well, you picked a rather complicated one. The # merely means that this is an attribute - a special marker or signal to the compiler, as Apple explains here. But #UIApplicationMain is a particularly profound attribute! It substitutes for the entire UIApplicationMain implementation that lies at the heart of a C / Objective-C application, in the main.m file (as I explain here):
int main(int argc, char *argv[])
{
#autoreleasepool {
return UIApplicationMain(argc, argv, nil,
NSStringFromClass([AppDelegate class]));
}
}
That is the main entry point of the app, implementing the entire launch-and-run code that is the running application. You can do something like that in Swift — a main.swift file with the Swift equivalent of that code — but Swift saves you the trouble by letting you designate your app delegate class with the #UIApplicationMain attribute.
If you start a project as an Objective-C or Objective-C++ project, the template will give you a main file containing the main implementation, so there's no need to do anything special in this regard.
Keywords starting with an # are instructions to the compiler – for example, in view controllers you use #IBOutlet to identify variable declarations that relate to connections within the visual interface build (a storyboard or XIB file – the 'IB' prefix stands for 'Interface Builder', which was the old name for the part of Apple's design tools that provided the GUI for visually creating interfaces).
Put simply, #UIApplicationMain is an indicator for Swift applications that indicates which object is your application's main application delegate file. In Objective-C application templates, you would have a trivial main.m C file which sets the application delegate. With Swift, that trivial implementation becomes a single directive.
In both cases, the trivial implementation can be replaced with something more complex if need be – but in most apps there is no need for anything else, and indeed if you're only just starting out in Swift, the chances of you needing a non-trivial implementation are most likely to be zero.
Swift attribute
Swift attribute is a marker which is used by compiler to execute some specific logic. It is a kind of Aspect Oriented approach
#<attribute_name>(<attribute_arguments>)
#NSApplicationMain, [#UIApplicationMain] - generates main.swift
[#objc vs #objcMembers]
[#noescape vs #escaping]
[#autoclosure]
[#testable]
There are some private attributes like #_exported, #inline...
[Objective-C property attributes]
[Java annotation]

Why am I getting this warning from Xcode? The iOS code seems fine

This one has me stumped. I'm writing an iPhone app that tracks bus schedules. Users can bookmark their favorite bus stops so they can jump directly to them from the home screen. I manage the list of favorites in my AppDelegate class (unrelated code has been redacted):
#interface AppDelegate : NSObject <UIApplicationDelegate>
+ (BOOL) isInFavorites: (FavoriteStopData*) inStop;
#end
I have a view controller that presents the list of stops for a given bus route and lets users select one to see predicted bus arrival times for that stop in a new view (and maybe add the stop to their list of favorites):
#implementation RouteStopsViewController
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
FavoriteStopData *stopData = [[FavoriteStopData alloc] init];
// ... set various properties in stopData from data in the selected cell
FavoriteStopViewController *fvc = [[FavoriteStopViewController alloc] initWithNibName:#"FavoriteStopViewController" bundle:nil];
fvc.stop = stopData;
fvc.isBookmarked = [AppDelegate isInFavorites:stopData];
[stopData release];
[self.navigationController pushViewController:fvc animated:YES];
[fvc release];
}
#end
The line
fvc.isBookmarked = [AppDelegate isInFavorites:stopData];
gets two warnings:
"'AppDelegate' may not respond to +isInFavorites:"
"Passing argument 1 of 'setIsBookmarked' makes integer from pointer without a cast"
I can't see any reason for Xcode to think '+isInFavorites:' is undefined, yet it does. I've verified that these possible causes for the warning are not in fact the case:
'+isInFavorites:' is declared in "AppDelegate.h" (as shown above)
"RouteStopsViewController.m" does #import "AppDelegate.h" (and "FavoriteStopData.h" and "FavoriteStopViewController.h")
'isBookmarked' is a public BOOL property on FavoriteStopViewController
The code is not being munged by some #define macro; when I preprocess "RouteStopsViewController.m", this code is unchanged.
The code behaves correctly, but I REALLY don't want to live with a warning that I must ignore every time the code compiles, and disabling this warning with some #pragma is a road I'd rather not take unless I have to.
I've tried renaming the method name, the variable names, using the method to set a local BOOL variable and then setting the property with that, using a conditional operator (x ? y : z) to make sure I'm passing a BOOL to the property ... nothing works. That first warning never goes away.
Can anyone suggest why Xcode is giving me this warning?
This is with Xcode 4.2 (Build 4C199) and iOS 5 SDK running in the 5.0 iPhone Simulator on a MacBook Pro running Mac OS X 10.6.8 (Snow Leopard).
If the +isInFavorites: method was completely unknown to the compiler then you'd see a warning like +isInFavorites: not found (return type defaults to 'id').
If you're not seeing that warning then we can assume that the compiler has seen a declaration of that method somewhere. However, the compiler expects this method to return a pointer rather than a BOOL, which is why you're seeing the makes integer from pointer without a cast warning.
Check for any other declarations of an isInFavorites: method in your project. Check for any global variables named AppDelegate that may conflict with your class name. Check for any circular imports between AppDelegate.h and RouteStopsViewController.h. Try renaming your AppDelegate class.
declare your isInFavorites method in your appdelegate.h file.
'AppDelegate' may not respond to +isInFavorites:
Passing argument 1 of 'setIsBookmarked' makes integer from pointer without a cast
The first error causes the second. The compiler's confusion on the existence of +isInFavorites: causes the compiler to assume the return type is id
This assumption causes the warning of making integer from pointer without a cast
You really have to focus on the first warning.
Are these the only warnings?
Try changing your AppDelegate.h to
#class FavoriteStopData
#interface AppDelegate : NSObject <UIApplicationDelegate>
+ (BOOL) isInFavorites: (FavoriteStopData*) inStop;
#end
If you still have issues, you might want to consider making this an instance method instead, considering the appDelegate is valid the whole runtime of your app
Found it. Even makes perfect sense ... now that I know exactly where to look.
My project has two targets: Dev for the version I use to test new code, and App for the user-facing version. Each has its own AppDelegate class (and some other duplicates). Code specific to one target or the other goes into either the ./Dev/ or the ./App/ folder. Common code goes into other folders.
Recently I promoted one Dev-specific class to be used in both targets ... but hadn't yet moved the files out of the Dev folder. This was my problematic RouteStopsViewController. My project was compiling the right "AppDelegate.m", but Xcode was finding the 'wrong' (to my thinking) "AppDelegate.h" because it was looking first in the same folder as "RouteStopsViewController.m".
The fix was easy: move RouteStopsViewController out of the Dev-specific folder into one for code shared by both targets. Now Xcode uses the "AppDelegate.m" file it's compiling to find the matching "AppDelegate.h".
I knew at the time I should move that RouteStopsViewController class when I decided to reuse it in the App target, I just didn't get around to it. When it comes to writing code, trust your nose. If it smells funny, it very probably is.

objective c xcode 4.0.2: subclass can't access superclass variables "was not declared in this scope"

I have several classes that are subclasses of one Layer class.. for some reason one of the subclasses acts differently. this is a stripped down version:
#interface Layer: CCLayer
{
GameScene* _scene;
CCNode* _layerNode;
}
#end
#import "Layer.h"
#interface UILayer: Layer
{
}
#end
#implementation UILayer
-(void) doStuff
{
[_layerNode addChild:[CCNode node]]; <---gives compile error: "_layerNode was not declared in this scope"
[_scene playSound];<------gives compile error: "_scene was not declared in this scope"
}
#end
I think that gets the basic idea across. I can fix this by doing
[[_self _layerNode] addChild:[CCNode node]];
[[_self _scene] playSound];
but what I can't figure out is why other subclasses of Layer can access _layerNode and _scene directly? I am guessing that it is a problem with the build settings. Further this problem only happens when I build it for the device (iphone) and not the simulator. let me know if you need more information to answer.
Edit:
Oops I wrote it wrong. It should have been [[self _layerNode] addNode:[CCNode node]] but I guess the question is why would one subclass have direct access to the ivar _layerNode and another have to access it with [self _layerNode]. It is like the UILayer can't find the super class header
From the docs: Apple Objective-C Programming Language (doesn't mention this anymore, but you can find it in this retired document).
The instance variable is accessible within the class that declares it and within classes that inherit it. All instance variables without an explicit scope directive have #protected scope.
However, a public instance variable can be accessed anywhere as if it were a field in a C structure. For example:
Worker *ceo = [[Worker alloc] init];
ceo->boss = nil;
I have the compilation error using LLVM GCC 4.2 (for an iOS project, on device):
error: 'fooInstanceVar' undeclared (first use in this function)
and the same one using GCC 4.2 :
error: 'fooInstanceVar' undeclared (first use in this function)
I can compile using LLVM Compiler 2.0 whithout error.
For compiling with LLVM GCC 4.2 and GCC 4.2 with the use of self->:
[NSArray arrayWithObjects:self.barProperty, self->fooInstanceVar, nil];
in the doSomethingWithProperty method.
Maybe it's the name. The 'UI' prefix is designated for UIKit classes. Could well be that UILayer is a private UIKit class used by Apple.
If you #synthesize ivars, the compiler unhelpfully stops you from accessing them "directly". The fix is relatively easy: Write self->_layerNode and self->_scene.
I'm assuming your "stripped-down version" compiles fine.
Note that it's also bad form to directly access your superlcass's ivars unless you're aware of its implementation details.
(What's _self?)

Objective-C, properties for references

This might be iPhone specific, I'm not sure. The compiler doesn't complain when building for the simulator but when compiling for device it throws some funky errors when I try to set properties for references to objects. Eg,
#property (nonatomic) CGRect &finalFrame;
and the coressponding synthesizer
#synthesize finalFrame;
for a variable declared as
CGRect finalFrame;
Gives the errors
type of property 'finalFrame' does not match type of ivar 'finalFrame'
Unrecognisable insn:
Internal compiler error: Bus error
Internal compiler error: in extract_insn, at recog.c:2904
However I can do it manually without issue, with the following methods:
- (CGRect&)finalFrame;
- (void)setFinalFrame:(CGRect&)aFrame;
Is this a gcc bug? It does compile for the simulator.
Your property is declared as a reference type (CGRect&) but your instance variable is not a reference type (CGRect). They need to be the same to use #synthesize.
Also, it's a little weird to be using C++ reference types as Objective-C properties, but I guess that might work as long as all the files are being compiled as Objective-C++.

std::map initialization crashing on iPhone device, but not in simulator

I've tried turning on the Call C++ Default Ctors/Dtors in Objective-C flag but I'm still getting an EXC_BAD_ACCESS error when I first try to access my map:
(*[TextureBatcher getSharedTextureBatcher].getMap)[texID].vertexCount=0;
(*[TextureBatcher getSharedTextureBatcher].getMap)[texID].indexCount=0;
getMap just returns a reference to my map:
-(VertexMap *) getMap{
return &texMap;
}
And a VertexMap is a typedef of a std::map:
typedef std::map<GLuint, VertexInfo> VertexMap;
Not sure why this is failing on device and not in the simulator, any thoughts?
Just so we're clear:
(*[TextureBatcher getSharedTextureBatcher].getMap)[texID].vertexCount=0;
If theMap[texID] does not exist, the above line will cause a VertexInfo object to be constructed (with the default constructor, VertexInfo()). Is this what you're intending?
Perhaps the underlying std::map is implemented differently on the device, preventing this kind of initialisation?
Are you sure you set the Call C++ Default Ctors/Dtors in Objective-C flag on the Device target, not just the Simulator target?
Generally, the pattern is to use pointers here (C++) so you'd end up with:
typedef std::map<GLunit, VertexInfo*> VertexMap;
VertexMap theMap;
theMap[0] = new VertexInfo(...);
// now operate on theMap[0] normally
Or did I misunderstand the question?