I have a very complicated problem with geolocation : the didupdatetolocation delegate method is not called which I'm not understand.
this the code of the method:
- (void) locationManager:(CLLocationManager *)pLocationManager didUpdateToLocation:(CLLocation *)pNewLocation fromLocation:(CLLocation *)pOldLocation {
lGPSAccuracy = 0;
// Stop trace record when the GPS Signal is poor or null
if (pNewLocation.horizontalAccuracy > GPS_POOR_SIGNAL || pNewLocation.horizontalAccuracy < 0){ return;}
if (pNewLocation.horizontalAccuracy > pNewLocation.verticalAccuracy) {
lGPSAccuracy = pNewLocation.horizontalAccuracy;
} else {
lGPSAccuracy = pNewLocation.verticalAccuracy;
}
if (self.delegate && [self.delegate respondsToSelector:#selector(traceRecorder:didUpdateToLocation:fromLocation:)]) {
[self.delegate traceRecorder:self didUpdateToLocation:pNewLocation fromLocation:pOldLocation];
}
CLLocationCoordinate2D lUserLocation = pNewLocation.coordinate;
Boolean lLatitudeOK = (self.mMapSouthWest.latitude < lUserLocation.latitude) && (lUserLocation.latitude < self.mMapNorthEast.latitude);
Boolean lLongitudeOK = (self.mMapSouthWest.longitude < lUserLocation.longitude) && (lUserLocation.longitude < self.mMapNorthEast.longitude);
//IF USER IS OUT OF THE MAP
if (self.delegate && [self.delegate respondsToSelector:#selector(userPositionOnMap:)]) {
if ( (!lLatitudeOK || !lLongitudeOK) ) {
[self.delegate userPositionOnMap:NO];
} else {
[self.delegate userPositionOnMap:YES];
}
}
if (![self isNewLocation:pNewLocation acceptableComparedToOldLocation:pOldLocation]) {
return;
}
[self treatLocation:pNewLocation];
}
when I read about this problem i found that this method is deprecated but it's still working on a old version of my project which is very abnormal.
Any help please.
Make sure your CLLocationManager variable isn't a local variable. And call startUpdatingLocation after creating CLLocationManager. One of these 2 mistake can make didUpdateToLocation isn't called.
Try my code below
- (void) beginMonitoring {
if (TracageAutomatic) {
tracageAutomaticTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(tracageAutomaticTimeCalled) userInfo:nil repeats:YES];
}
if (self.mLocationManager == nil) {
[self setMLocationManager: [[CLLocationManager alloc] init]];
[self.mLocationManager setDelegate:self];
[self.mLocationManager setDesiredAccuracy:kCLLocationAccuracyBestForNavigation];
[self.mLocationManager setDistanceFilter:2.0f]; //Minimum distance to move in meters before calling location update.
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"8.0")) {
//TODO: restore for iOS8
[self.mLocationManager requestWhenInUseAuthorization];
}
}
[self.mLocationManager startUpdatingLocation];
if ([self.mLocationManager respondsToSelector:#selector(setAllowsBackgroundLocationUpdates:)]) {
[self.mLocationManager setAllowsBackgroundLocationUpdates:YES];
}
}
yes I'm sure that i did this in the code of this method which is called in running perfectly
- (void) beginMonitoring {
if (TracageAutomatic) {
tracageAutomaticTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(tracageAutomaticTimeCalled) userInfo:nil repeats:YES];
} else {
if (self.mLocationManager == nil) {
[self setMLocationManager: [[CLLocationManager alloc] init]];
[self.mLocationManager setDelegate:self];
[self.mLocationManager setDesiredAccuracy:kCLLocationAccuracyBestForNavigation];
[self.mLocationManager setDistanceFilter:2.0f]; //Minimum distance to move in meters before calling location update.
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"8.0")) {
//TODO: restore for iOS8
[self.mLocationManager requestWhenInUseAuthorization];
}
}
[self.mLocationManager startUpdatingLocation];
if ([self.mLocationManager respondsToSelector:#selector(setAllowsBackgroundLocationUpdates:)]) {
[self.mLocationManager setAllowsBackgroundLocationUpdates:YES];
}
}
}
this the method to launch an automatic hike :
- (void) tracageAutomaticTimeCalled{
if (_mUserReachedTrackEnd){
[tracageAutomaticTimer invalidate];
tracageAutomaticTimer = nil;
}
[self treatLocation:[self.mTrackPoints objectAtIndex:tracageAutomaticCurrentIndex]];
tracageAutomaticCurrentIndex += TracageAutomoticPas;
if (tracageAutomaticCurrentIndex > [self.mTrackPoints count]){
tracageAutomaticCurrentIndex = (int)([self.mTrackPoints count]-1);
}
}
thank you #truncdug. I resolved the problem by changing the deprecated didtoupdatelocations method
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
{
if ([locations count]>0) {
CLLocation *pNewLocation = [locations firstObject];
CLLocation *pOldLocation = _currentLocation;
_currentLocation = pNewLocation;
lGPSAccuracy = 0;
// Stop trace record when the GPS Signal is poor or null
if (pNewLocation.horizontalAccuracy > GPS_POOR_SIGNAL || pNewLocation.horizontalAccuracy < 0){ return;}
if (pNewLocation.horizontalAccuracy > pNewLocation.verticalAccuracy) {
lGPSAccuracy = pNewLocation.horizontalAccuracy;
} else {
lGPSAccuracy = pNewLocation.verticalAccuracy;
}
if (self.delegate && [self.delegate respondsToSelector:#selector(traceRecorder:didUpdateToLocation:fromLocation:)]) {
[self.delegate traceRecorder:self didUpdateToLocation:pNewLocation fromLocation:pOldLocation];
}
CLLocationCoordinate2D lUserLocation = pNewLocation.coordinate;
Boolean lLatitudeOK = (self.mMapSouthWest.latitude < lUserLocation.latitude) && (lUserLocation.latitude < self.mMapNorthEast.latitude);
Boolean lLongitudeOK = (self.mMapSouthWest.longitude < lUserLocation.longitude) && (lUserLocation.longitude < self.mMapNorthEast.longitude);
//IF USER IS OUT OF THE MAP
if (self.delegate && [self.delegate respondsToSelector:#selector(userPositionOnMap:)]) {
if ( (!lLatitudeOK || !lLongitudeOK) ) {
[self.delegate userPositionOnMap:NO];
} else {
[self.delegate userPositionOnMap:YES];
}
}
if (![self isNewLocation:pNewLocation acceptableComparedToOldLocation:pOldLocation]) {
return;
}
[self treatLocation:pNewLocation];
}
}
Related
I need to allow two-finger pinch/rotate/panning and deny single-finger panning.
I've tried some ways to achieve this:
for (UIPanGestureRecognizer *pan in mapView.gestureRecognizers) {
if ([pan isKindOfClass:[UIPanGestureRecognizer class]]) {
if ([pan minimumNumberOfTouches] < 2) {
[pan setMinimumNumberOfTouches:2];
}
}
}
But this not works. Maybe some kind of UIGestureRecognizer failing dependency?
Just found nice solution:
self.twoFingerPan = [[UIPanGestureRecognizer alloc] init];
self.twoFingerPan.maximumNumberOfTouches = 1;
self.twoFingerPan.delegate = self;
[self addGestureRecognizer:self.twoFingerPan];
...
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
if (gestureRecognizer == self.twoFingerPan &&
[otherGestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] &&
(otherGestureRecognizer.view == self.mapView ||
otherGestureRecognizer.view.superview == self.mapView)) {
return YES;
}
return NO;
}
And addition to allow any outer scrolling:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
if (gestureRecognizer == self.twoFingerPan &&
[otherGestureRecognizer.view isKindOfClass:[UIScrollView class]]) {
return YES;
}
return NO;
}
I am working on a collision game as objects move across the screen, but for some reason, it won't return to the main menu when the object collides. It looks fine to me. What's wrong here?
-(void)Crash {
if (CGRectIntersectsRect(StealthBomber.frame, LargeObstacle1.frame)) {
[self EndGame];
}
if (CGRectIntersectsRect(StealthBomber.frame, MediumObstacle1.frame)) {
[self EndGame];
}
if (CGRectIntersectsRect(StealthBomber.frame, SmallObstacle1.frame)) {
[self EndGame];
}
if (CGRectIntersectsRect(StealthBomber.frame, Grass.frame)) {
[self EndGame];
}
if (CGRectIntersectsRect(StealthBomber.frame, Dirt.frame)) {
[self EndGame];
}
}
-(void)EndGame {
StealthBomber.hidden = YES;
[timer invalidate];
[self performSelector:#selector(NewGame) withObject:nil afterDelay:5];
}
-(void)NewGame {
LargeObstacle1.hidden = NO;
MediumObstacle1.hidden = NO;
SmallObstacle1.hidden = NO;
StealthBomber.hidden = NO;
StealthBomber.center = CGPointMake(32, 92);
StealthBomber.image = [UIImage imageNamed:#"stealthbomber.png"];
startGame = YES;
}
I fixed the issue. It was a matter of not showing hidden items and hiding other items when newGame is called.
Have recently been teaching myself objective-c in order to learn Cocos2d.
Started a new project to teach myself the basics with a classic falling gems tetris-like game. The first step I took was to enable the project for ARC using edit > refactor, and selecting the last 4 files in the template.
So far have been able to add a single gem with a dynamically colored sprite through subclassing CCSprite, and move it along the XCoordinates while having it fall from the top. The gems are given a gemPos location – eg 5,3 – in order for me to later implement the matching methods.
Am getting an EXC_BAD_ACCESS warning when a few of the blocks stack up on top of each other after testing out the project for a while. Am confused as to why this is happening if ARC is enabled.
My clumsy code is as follows (have left out .h files):
Default helloworld layer:
-(id) init
{
if( (self=[super init]) ) {
oldGems = [[NSMutableArray alloc]init];
[self setIsTouchEnabled:YES];
[self newGem];
[self scheduleUpdate];
}
return self;
}
- (void)registerWithTouchDispatcher
{
[[[CCDirector sharedDirector] touchDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:YES];
}
- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
CGPoint touchLocation = [self convertTouchToNodeSpace:touch];
oldPos = touchLocation;
return TRUE;
}
- (void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event
{
CGPoint touchLocation = [self convertTouchToNodeSpace:touch];
[self updateXCoord:(CGPoint)touchLocation];
}
- (void)updateXCoord:(CGPoint)touchLocation
{
CGPoint distance = ccpSub(touchLocation, oldPos);
float xDistance = distance.x;
if (abs(xDistance) >= 36) {
if (touchLocation.x > oldPos.x) {
[_thisGem setPosition:ccp([_thisGem position].x + 36, [_thisGem position].y)];
[_thisGem setGemPos:ccp([_thisGem gemPos].x+1,[_thisGem gemPos].y)];
NSLog(#"The gem position is %#", NSStringFromCGPoint([_thisGem gemPos]));
oldPos = touchLocation;
} else {
[_thisGem setPosition:ccp([_thisGem position].x - 36, [_thisGem position].y)];
[_thisGem setGemPos:ccp([_thisGem gemPos].x-1,[_thisGem gemPos].y)];
NSLog(#"The gem position is %#", NSStringFromCGPoint([_thisGem gemPos]));
oldPos = touchLocation;
}
}
}
- (void)newGem
{
if (_thisGem) {
PCGem *oldGem = _thisGem;
NSLog(#"Old gem position at %#", NSStringFromCGPoint([oldGem gemPos]));
[oldGems addObject:oldGem];
}
_thisGem = [[PCGem alloc] initWithGemColor];
[_thisGem setPosition:ccp(160, 450)];
[self addChild:_thisGem];
[_thisGem setGemPos:ccp(4,10)];
NSLog(#"Gem added with %# color", [_thisGem gemColorName]);
}
- (void)update:(ccTime)dt
{
if ([_thisGem gemPos].y > 0) {
[self spaceBelowOccupied];
[_thisGem setPosition:ccp([_thisGem position].x, [_thisGem position].y-1)];
[_thisGem setGemPos:ccp([_thisGem gemPos].x, floor([_thisGem position].y / 36))];
} else {
[self newGem];
}
}
- (void)spaceBelowOccupied
{
for (PCGem *occupiedTile in oldGems) {
if (CGRectIntersectsRect(occupiedTile.boundingBox, _thisGem.boundingBox)) {
NSLog(#"Collision detected!");
[self newGem];
}
}
}
And my clumsy PCGem class:
- (id)initWithGemColor
{
if ((self = [super initWithFile:#"gemGS.png"])) {
NSArray *gemColorList = [NSArray arrayWithObjects:(NSString *)#"blue", (NSString *)#"red", (NSString *)#"green", nil];
NSInteger randColor = arc4random_uniform(3);
switch (randColor) {
case 0:
{
[self setGemColorName:[gemColorList objectAtIndex:0]];
ccColor3B gemColorRGB = {0,0,255};
[self setColor:gemColorRGB];
break;
}
case 1:
{
[self setGemColorName:[gemColorList objectAtIndex:1]];
ccColor3B gemColorRGB = {255,0,0};
[self setColor:gemColorRGB];
break;
}
case 2:
{
[self setGemColorName:[gemColorList objectAtIndex:2]];
ccColor3B gemColorRGB = {0,255,0};
[self setColor:gemColorRGB];
break;
}
}
}
return self;
}
Which leads me to another question, which I can't seem to find the answer to. In examples of ARC enabled Cocos2d projects, I've seen the node convenience method used, which of course is alloc]init]autorelease]. But I thought you can't use Autorelease with ARC and this would cause a crash? How does this work?
Any ideas to my woes? Would greatly appreciate clarification :)
Cheers,
Adrian
I think it might be caused by editing an array while enumerating through it. In your update function you call spaceBelowOccupied:
- (void)spaceBelowOccupied
{
for (PCGem *occupiedTile in oldGems) {
if (CGRectIntersectsRect(occupiedTile.boundingBox, _thisGem.boundingBox)) {
NSLog(#"Collision detected!");
[self newGem];
}
}
}
then if newGem gets called while in your for loop and this loop succeeds:
if (_thisGem) {
PCGem *oldGem = _thisGem;
NSLog(#"Old gem position at %#", NSStringFromCGPoint([oldGem gemPos]));
[oldGems addObject:oldGem];
}
then you are adding an object to an array while enumerating through it. So change your spaceBelowOccupied to this and see if it works:
- (void)spaceBelowOccupied
{
for (PCGem *occupiedTile in [oldGems copy]) {
if (CGRectIntersectsRect(occupiedTile.boundingBox, _thisGem.boundingBox)) {
NSLog(#"Collision detected!");
[self newGem];
}
}
}
that way you make a copy of oldGems to enumerate through that will get autoreleased once you are done going through it.
i had displayed some images in collectionview. now i want to select the image and press space button. If i pressed Space button , the image should quicklook in a seperate window. any idea?
On your view, do this:
- (void)keyDown:(NSEvent *)event
{
unichar firstChar = 0;
if ([[event charactersIgnoringModifiers] length] > 0)
firstChar = [[event charactersIgnoringModifiers] characterAtIndex:0];
if (firstChar == ' ')
{
if ([QLPreviewPanel sharedPreviewPanelExists]
&& [[QLPreviewPanel sharedPreviewPanel] isVisible])
{
[[QLPreviewPanel sharedPreviewPanel] orderOut:nil];
}
else
{
[[QLPreviewPanel sharedPreviewPanel] makeKeyAndOrderFront:nil];
[[NSApp mainWindow] makeKeyWindow];
}
}
else if (firstChar == NSRightArrowFunctionKey)
{
if ([QLPreviewPanel sharedPreviewPanelExists]
&& [[QLPreviewPanel sharedPreviewPanel] isVisible])
{
[[QLPreviewPanel sharedPreviewPanel] selectNextItem];
return;
}
}
else if (firstChar == NSLeftArrowFunctionKey)
{
if ([QLPreviewPanel sharedPreviewPanelExists]
&& [[QLPreviewPanel sharedPreviewPanel] isVisible])
{
[[QLPreviewPanel sharedPreviewPanel] selectPreviousItem];
return;
}
}
else
[super keyDown:event];
}
Then, I do this in my app's delegate (AppDelegate.m):
- (BOOL)acceptsPreviewPanelControl:(QLPreviewPanel *)panel
{
//note that this methods indeed gets called because NSApp's
//delegate is in the responder chain.
return YES;
}
- (void)beginPreviewPanelControl:(QLPreviewPanel *)panel
{
previewPanel = panel; //set an ivar
[panel setDataSource:self];
}
- (void)endPreviewPanelControl:(QLPreviewPanel *)panel
{
previewPanel = nil;
}
- (NSInteger)numberOfPreviewItemsInPreviewPanel:(QLPreviewPanel *)panel
{
//return a number of your choice (depends on your own app)
}
- (id <QLPreviewItem>)previewPanel:(QLPreviewPanel *)panel
previewItemAtIndex:(NSInteger)index
{
//return an object of your choice (depends on your app)
}
- (void)handleCurrentFileItemsSelectionChange:(NSNotification *)note
{
[previewPanel reloadData]; //referring to the ivar
}
i finally got. i just replaced imageViewes and put NSButton and setted spacebutton as keyequivalent as
- (BOOL)isOneOfMyKeyEquivs:(NSString *)keyChar
{
if (([keyChar isEqualToString:#" "])||([keyChar isEqualToString:#"\r"])) {
return YES;
} else {
return NO;
}
}
- (BOOL)performKeyEquivalent:(NSEvent *)theEvent
{
//NSLog(#"OK");
NSString* keyChar = [theEvent characters];
if ([self isOneOfMyKeyEquivs:keyChar])
{
[[self cell] setKeyEquivalent:keyChar];
}
return [super performKeyEquivalent:theEvent];
return NO;
}
and performed button action.
I am calling a Singleton method that does not get called when I try doing this.
I get no errors or anything, just that I am unable to see the CCLOG message.
Under what reasons would a compiler not give you error and not allow you to call a method?
[[GameManager sharedGameManager] openSiteWithLinkType:kLinkTypeDeveloperSite];
The method is defined as follows:
-(void)openSiteWithLinkType:(LinkTypes)linkTypeToOpen
{
CCLOG(#"WE ARE IN openSiteWithLinkType"); //I NEVER SEE THIS MESSAGE
NSURL *urlToOpen = nil;
if (linkTypeToOpen == kLinkTypeDeveloperSite)
{
urlToOpen = [NSURL URLWithString:#"http://somesite.com"];
}
if (![[UIApplication sharedApplication]openURL:urlToOpen])
{
CCLOG(#"%#%#",#"Failed to open url:",[urlToOpen description]);
[self runSceneWithID:kMainMenuScene];
}
}
HERE IS THE CODE TO MY SINGLETON:
#import "GameManager.h"
#import "MainMenuScene.h"
#implementation GameManager
static GameManager* _sharedGameManager = nil;
#synthesize isMusicON;
#synthesize isSoundEffectsON;
#synthesize hasPlayerDied;
+(GameManager*) sharedGameManager
{
#synchronized([GameManager class])
{
if (!_sharedGameManager)
{
[[self alloc] init];
return _sharedGameManager;
}
return nil;
}
}
+(id)alloc
{
#synchronized ([GameManager class])
{
NSAssert(_sharedGameManager == nil,#"Attempted to allocate a second instance of the Game Manager singleton");
_sharedGameManager = [super alloc];
return _sharedGameManager;
}
return nil;
}
-(id)init
{
self = [super init];
if (self != nil)
{
//Game Manager initialized
CCLOG(#"Game Manager Singleton, init");
isMusicON = YES;
isSoundEffectsON = YES;
hasPlayerDied = NO;
currentScene = kNoSceneUninitialized;
}
return self;
}
-(void) runSceneWithID:(SceneTypes)sceneID
{
SceneTypes oldScene = currentScene;
currentScene = sceneID;
id sceneToRun = nil;
switch (sceneID)
{
case kMainMenuScene:
sceneToRun = [MainMenuScene node];
break;
default:
CCLOG(#"Unknown Scene ID, cannot switch scenes");
return;
break;
}
if (sceneToRun == nil)
{
//Revert back, since no new scene was found
currentScene = oldScene;
return;
}
//Menu Scenes have a value of < 100
if (sceneID < 100)
{
if (UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPad)
{
CGSize screenSize = [CCDirector sharedDirector].winSizeInPixels;
if (screenSize.width == 960.0f)
{
//iPhone 4 retina
[sceneToRun setScaleX:0.9375f];
[sceneToRun setScaleY:0.8333f];
CCLOG(#"GM: Scaling for iPhone 4 (retina)");
}
else
{
[sceneToRun setScaleX:0.4688f];
[sceneToRun setScaleY:0.4166f];
CCLOG(#"GM: Scaling for iPhone 3G or older (non-retina)");
}
}
}
if ([[CCDirector sharedDirector] runningScene] == nil)
{
[[CCDirector sharedDirector] runWithScene:sceneToRun];
}
else
{
[[CCDirector sharedDirector] replaceScene:sceneToRun];
}
}
-(void)openSiteWithLinkType:(LinkTypes)linkTypeToOpen
{
CCLOG(#"WE ARE IN openSiteWithLinkType");
NSURL *urlToOpen = nil;
if (linkTypeToOpen == kLinkTypeDeveloperSite)
{
urlToOpen = [NSURL URLWithString:#"http://somesite.com"];
}
if (![[UIApplication sharedApplication]openURL:urlToOpen])
{
CCLOG(#"%#%#",#"Failed to open url:",[urlToOpen description]);
[self runSceneWithID:kMainMenuScene];
}
}
-(void) test
{
CCLOG(#"this is test");
}
#end
Perhaps sharedGameManager is returning nil? This won't cause an error.
Edit: The issue is in the new code you posted:
if (!_sharedGameManager) {
[[self alloc] init];
return _sharedGameManager;
}
return nil;
If _sharedGameManager is non-nil, this will return nil. You want:
if (!_sharedGameManager) {
[[self alloc] init];
}
return _sharedGameManager;
Check this Cocoa With Love article on how to make a proper singleton.