XCode 4.5 and static (singleton) class (C++) - iphone

I'm running into a weird issue with XCode 4.5, the one supporting the new iOS6.
In most of my apps, I make a State class as a singleton accessible from everywhere for convenience, but with latest XCode, it seems like after I set any non-static pointer member to some object, right after the assignment the value is back to NULL.
Even weirder is I only see the issue if I start a new project from scratch, not if I load an older project created with an earlier version of XCode. I looked at compiler settings, and everything looks the same. The issue only appears if I test on the actual device (iPhone4 running iOS6). The simulator does not show this problem.
Here's the relevent code :
State.h
class State
{
public:
State();
~State();
static State& Get();
private:
static State * s_state;
State.mm
State* State::s_state = nil;
State& State::Get()
{
if(s_state==nil)
s_state = new State();
return *(s_state);
}
Example usage assuming State has a non-static member Object * m_object :
void SomeClass::DoSomething()
{
State::Get().SetObject( new Object() );
// this will return null with newly created XCode 4.5 projects
State::Get().GetObject();
** EDIT **
Regarding thread safety-ness, I'd like to know if the 2 cases below are considered "multi-threaded" scenarios.
I have one timer using display link for my opengl loop
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
And I have one timer responsible for updating the game logic that I init this way
timer = [NSTimer scheduledTimerWithTimeInterval:1.f/60.f target:self selector:#selector(timerUpdate) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:m_timer forMode:NSRunLoopCommonModes];
So if I call State::Get() from both these loops, is this considered a threaded scenario?
Thank you for your help.
- Marc

Your code looks okay (although it is not threadsafe). You don't post accessors, so I'll assume they are the standard type that actually get and set things.
Which means I can only guess but it's worth checking if the source of the problem is some corrupted memory that occurred earlier due to something like double delete.
Enable guard malloc and try again. You can also try valgrind.
About your edit, you should be okay as long as you are calling the addToLoop code from the main thread (you probably are calling it in some viewDidLoad or init code which is on the main thread), since both timer callbacks (timer and display link will be processed on the main loop).

Ok I found out what my issue was and thought I'd share with you all. Although it doesn't have anything to do with single/static classes, this kind of issue can be hard to debug.
In my State class, I had a member available only to a specific config :
#ifdef SOME_CONFIG
int m_someValue;
#endif
The problem in this case was that at compile time, SOME_CONFIG was actually defined, but undefined elsewhere according to target conditionals etc, causing the variable to exist on the stack but never inited/used etc. Just having the variable in the header was causing the issue (even if I didn't make any call using it.)
Hope this can help someone out there.
Thanks.

Related

EXC_BAD_ACCESS when calling new entity() method in iOS 10 / macOS Sierra Core Data

The new entity() method helps us avoid magic strings. Rather than saying something like managedObjectModel.entitiesByName["foo"], we can say Foo.entity().
The problem is that in my testing it always throws EXC_BAD_ACCESS. I've configured my NSPersistentStore and I've run a test query to make sure that everything is set up properly.
Any insight? What are the prerequisites to call this method?
Something is wrong with your setup.
To check, open Xcode, start a new project, choose "Master/Detail", check "Core Data". In the MasterViewController, insert this line anywhere:
print("The entity is ", Event.entity(), ".")
You will see that it works out of the box. Notice that in the model editor, when inspecting the Event entity, the option "Codegen" is set to "Class Definition".
The problem turned out to be that merely initializing NSPersistentStore and calling loadPersistentStores isn't enough. You have to explicitly or implicitly use its managedObjectModel property at least once, most likely due to lazy loading.
I tentatively regard this as a bug. The entity() method should probably do this itself under the hood, though there may be other considerations.

xcode 5 XCTestCase running not how i expect

In unit test case I try to make some own logic for my app, like register from another username at current or connect to different servers, without duplicate existing code.
First step that i try to make is a create XCTestCase, alloc class which support for external connections and try to get delegate calls from him.
But NSURLConnection just waiting without network exchange, so i was not success.
Next case, which i try to do is waiting while app will be done and do all issues then:
- (BOOL)waitForCompletion:(NSTimeInterval)timeInterval {
NSDate *timeoutDate =
[NSDate dateWithTimeIntervalSinceNow:timeInterval];
do {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
beforeDate:timeoutDate];
if([timeoutDate timeIntervalSinceNow] < 0.0) {
break;
}
} while (self.hasOperationFinishedPerforming == NO);
return self.hasOperationFinishedPerforming;
}
But in that case, app starting, do all current cycle, but i have no idea, how i can detect from current app code that there is running unit tests. I tried to set preprocessor macros on unit test target's but it not effected in code inside app, only effect on code of tests classes as well.
Any ideas?
Assuming you have set your unit test target's Bundle Loader build setting to use your app, you can determine if your app is running as part your unit tests like so:
static BOOL isRunningTests(void)
{
NSDictionary* environment = [[NSProcessInfo processInfo] environment];
NSString* injectBundle = environment[#"XCInjectBundle"];
return [[injectBundle pathExtension] isEqualToString:#"octest"]; // For SenTestKit; use "xctest" for XCTest
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if (isRunningTests())
return YES;
// Normal app launch stuff here...
...
}
That being said, your unit tests should not be testing anything that relies on external services, like APIs or databases, being available. If you cannot avoid having those kinds of things available, then you should look at "mock" objects (using 3rd party libraries like OCMock) which let you stub out complex classes and control what they return within your test environment.
The purpose of unit testing is NOT to test someone else's API or database or SDK, but rather to test your code and algorithms. If you can't test your code this way, that may be a signal that you need to refactor your code into more testable chunks.
There is a great book titled "Test-Driven iOS Development" by Graham Lee which I highly recommend that talks all about writing unit tests for iOS projects.
When you try to test a NSURLConnection which implements delegates, you need to take care to correctly implement the run loop related code.
Your waitForCompletion: method will likely not work or be unreliable. The reason is, method runMode:beforeDate: will not return until after an "event" has been executed in mode :NSDefaultRunLoopMode - or the timeout is expired. An event originates from some "run loop source" and ends up being a method which gets called. The NSURLConnection for example is such a "run loop source" since it schedules delegate methods which are "events" that get eventually executed by the target run loop for the specified mode.
Now, you loop until self.hasOperationFinishedPerforming == NO. The flag may be eventually set, and you may expect the run loop will return and check the flag. But this is not the case until after some arbitrary event has been scheduled afterwards to the run loop with the specified mode. Only then (unless expired), the runMode:beforeDate: returns and finally checks the flag.
In order to cause the run loop return immediately, you may send a dummy event in your completion handler, or wherever it's appropriate when signaling an asynchronous completion:
self.hasOperationFinishedPerforming == YES;
[#"" performSelector:#selector(self) onThread:thread
withObject:nil
waitUntilDone:NO];
This however, WILL indeed require the completion handler to know that it will execute in the testing environment.
There are solutions to avoid this completely, but will require third party libs.

Setter failing selectively in NSManagedObject

I have a NSManagedObject which I'm trying to instantiate with given values. I access the setters like so:
object.couchID = (NSString *)[dictObject objectForKey:#"_id"];
...and this works fine on my machine, but my partner gets this error when he runs it on his machine:
'-[NSCFString type]: unrecognized selector sent to instance 0x4e465e0'
About 90% of the setters (all formatted in the same way) work on my partner's machine, but a good 10% fail with that error. All of them work on my machine.
We're running the exact same code (according to SVN (yes, I know)), and fetching the same data from the same server, so everything seems like it should work.
We've checked the objects being passed, and they're the same. Commenting out the setter allows the code to get through to the next troublesome setter, but of course we need it to actually work. How else should we troubleshoot? Thanks in advance.
Update 1: Unlocked the Tumbleweed badge for that one... guess it's too sticky to touch? Any thoughts or guesses are welcome. And hey, you could earn 50 points.*
Update 2: the mixed-good-news is that checking out a fresh version from source control results in the same problem on my machine, so a) it's definitely something in the code, and b) I can more actively troubleshoot. Thanks for all your suggestions so far, I'm going to go through them all again.
I ran into something similar at work the other day. I suspect that one of you has a stale .momd file inside the app bundle, and that it's not being replaced when it gets upgraded. I suspect this is a bug in Xcode 4, though I haven't totally verified it yet. If your partner deletes the app completely and then installs the app, does the error go away?
You may need to create a temporary variable whose value is object cast to whatever the actual class is, e.g.
MyClass *c = (MyClass *)object; // if object is in fact a MyClass instance
c.couchID = (NSString *)[dictObject objectForKey:#"_id"];
I have seen cases where the compiler cannot make mental leap and realize that your attribute is the class you know it is. The solution for me in these cases has been to be more explicit. Does this make sense? It's worth a shot at least, no? :-)
if this code fails on your partner's machine:
someManagedObject.couchID = #"some hardcoded string";
seems like you have a dangling pointer: i would check that someManagedObject is properly retained and still a valid object when you try to call the -setCouchID method on it.
I have had nearly the same problem when trying to draw a CATiledLayer with data in NSManagedObjects. What should be a valid object barfs with an "unrecognised selector" exception
It nearly always happens because theres no retain on the object external to the point where you are trying to set or get the property. Being in a separate thread seemed to have a relationship too.
After fruitlessly trying to get round this with [NSManagedObjectContext lock] and retain on the context within the new thread I eventually just threw the contents of my fetch into a mutable set to try and keep a grip on it which seems to work on iOS but not on OS X so well.
So a couple of possibilities
Are you doing this not in the main
thread and does the MOC have a retain
within that thread. Check the docs
for [NSManagedObjectContext lock]. But essentially each thread working with the context needs its own retain on the context.
Try throwing it into a container
while you operate on it. Make it a
bit stickier. Sorry if that sounds
like voodoo but it is.

EXC_BAD_ACCESS on IPhone Cocos2d

I Have the following code:
-(void) changeAnimation:(NSString*)name forTime:(int) times {
if(currentAnimation != #"attack")
{
id action = [CCAnimate actionWithAnimation:[self animationByName:name]];
id repeatAction = [CCRepeat actionWithAction:action times:times];
currentAction = [self runAction:repeatAction];
lastANimation = currentAnimation;
currentAnimation = name;
}
else if(currentAction.isDone)
{
//Here is where I would change the animation
//but I commented the code for now
}
}
So when I run this and click on the button that changes the animation to "attack" (by calling [mysprite changeAnimation:#"attack" forTime:1];), I get a EXC_BAD_ACCESS error from the "currentAction.isDone" line, the next time the function is called (the joystick will call changeAnimation to try and change the animation to "run" or "idle", but I want the attack animation to finish first). Any thoughts on whyI get this? currentAction is declared in my class.
Edit: there is nothing in the rest of the class that interacts with currentAction, beside a getter. Its declaration is in the .h (CCAction* surrentAction). Do I need to initialize it? I thought the returned value from runAction would be sufficient? ANyways, when I run the debugger, it is not nil, and assigned to the correct action.
Thanks,
Dave
Edit:
I ended up creating a sequence when "attacking" that calls a function that changes the currentAnimation, so i avoided the issue. Still no idea what was happening.
Here's the answer if your interested:
Other Post
More of the class is probably needed to really answer this properly, but the EXC_BAD_ACCESS typically happens because you're accessing something that has been released and is no longer available in memory.
I'm guessing that somewhere in your class you're releasing, either explicitly, or implicitly, the "currentAction" object asynchronously - and when you're checking later, it's done & gone and you're hitting this crasher.
In general, keeping a state variable or two that you always have known values on is a good way to go, and for the "actions" that you're going through, if they're asynchronous and doing their own memory management, leave them as such and work through some state variables that you maintain and control all the memory management around. It's a pretty reasonable pattern for asynchronous callbacks, either with the classic stuff or as you move into using blocks with iOS 4.0

Memory leak using (void) alloc

I have seen a similar line of code floating about in Apples code:
(void)[[URLRequest alloc] initializeRequestWithValues:postBody url:verifySession httpHeader:nil delegate:self];
URLRequest is my own custom class. I didn't write this and I think the guy that did just grabbed it from Apple's example. To me this should leak and when I test it I'm pretty sure it leaks 16 bytes. Would it? I know how to fix it if it does but wasn't sure as it was taken from Apple's code.
EDIT: The problem was with the SDK, not the above code. See answer below for further details
Thought I might update this as after further testing and the release of iOS4 it has changed.
The above code doesn't leak and the memory footprint of the App returns to normal even after 200 iterations of the code. The leak did occur in iOS3 but was very small, in iOS4 it has completely disappeared both in simulator and device.
Some might wonder why you would want to implement this code but it works and make sense when dealing with lots of different NSURLConnections throughout your code running simultaneously.
Yes. This is a leak, which can easily be fixed by adding an autorelease:
[[[URLRequest alloc] initializeRequestWithValues:postBody url:verifySession httpHeader:nil delegate:self] autorelease];
Perhaps a better fix would be to create a class function that does this:
#interface URLRequest
{
// ...
}
// ...
+ (void) requestWithValues:/* ... */
// ...
#end
Then you could simply use [URLRequest requestWithValues: /* ... */] without invoking alloc.
Not at all sure what this code is supposed to accomplish. It does appear to break every single convention about initialization methods. What's the point of returning a void pointer from an initialization method? The entire point of an initialization method is to return an object. Where in Apple's code examples did you see this?
Having said that, I don't see why it would leak. Since it doesn't return an object there is nothing to leak external to the method. There might be something internally that leaks.
Edit:
It basically does an NSURLConnection.
Because we are submitting a lot of
forms with a lot of different values
we put it in an external class. All
the delegate methods like
didFailWithError: are in NSURLRequest
and connectionDidFinishLoading just
passes the data to its delegate. So it
doesn't really need to return anything
as it is done through a delegate
method.
Yeah, you need to redesign this. At present, this method is just a disaster waiting to happening. If nothing else, everyone else looking at this code will be utterly confused about what you are doing.
If you have no need to retain the object created, then move its allocation and clean up entirely within a method. Change the method name prefix from "initialize" to something like "setup", "configure", "acquire" etc so the name doesn't imply that it creates and returns and object.
If you need a one shot instance of a particular class, use a class method like Michael Aaron Safyan suggested (again without initialize in the name.) The class method should internally initialize an instance, perform the operations needed, return the data to wherever, then dealloc the instance.
That way, you won't have to worry about leaks and everyone else who may read your code (including yourself months down the road) will immediately understand what the code does.