I'm developing a beacon app which has a tour mode option. So when the user taps the switch to turn on the tour, I'm creating beacon regions and using below code I'm listening for beacons
NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:beacon.beaconID];
CLBeaconRegion *region = [[CLBeaconRegion alloc] initWithProximityUUID:uuid major:[beacon.major integerValue] minor:[beacon.minor integerValue] identifier:beacon.identifier];
[self.locationManager startMonitoringForRegion:region];
region.notifyEntryStateOnDisplay = YES;
region.notifyOnEntry = YES;
region.notifyOnExit = YES;
[self.locationManager startRangingBeaconsInRegion:region];
Now to stop the ranging, I know I have to use
[self.locationManager stopRangingBeaconsInRegion:region];
But how do I get the same CLBeaconRegion created for monitoring? Should I save the CLBeaconRegion in an array?
CLLocationManager has a property called rangedRegions which is an NSSet of all regions being currently ranged. So if you do something like:
for (CLBeaconRegion *region in self.locationManager.rangedRegions) {
[self.locationManager stopRangingBeaconsInRegion:region];
}
If you want to stop ranging all regions.
Let me tell you how can we first range for all available beacons then how to monitor a particular beacon.
NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:beacon.beaconID];
CLBeaconRegion *region = [[CLBeaconRegion alloc] initWithProximityUUID:uuid identifier:beacon.identifier];
[self.locationManager startRangingBeaconsInRegion:region];
This will give you all available beacons in Range which matches with uuid.
Then you need to start monitoring for a particular beacon.(say beacon)
CLBeaconRegion *region = [[CLBeaconRegion alloc] initWithProximityUUID:beacon.uuid major:[beacon.major integerValue] minor:[beacon.minor integerValue] identifier:beacon.identifier];
[self.locationManager startMonitoringForRegion:region];
region.notifyEntryStateOnDisplay = YES;
region.notifyOnEntry = YES;
region.notifyOnExit = YES;
This will notify you when you comes in or goes out from beacon region
Let me know if anything else you need
Related
I am developing an iPhone app, where i have to monitor more then 20 Regions.
Development Environment: Xcode (Version 8.3.2)
IOS 10.3
please have a look at the code below:
I initialize my locationmanager :
- (id)init {
self = [super init];
if(self != nil) {
self.locationManager = [[CLLocationManager alloc] init];
// self.locationManager.distanceFilter = 100; // meters
self.locationManager.allowsBackgroundLocationUpdates = YES;
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
}
return self;
}
and then i start updating Location using below code:
- (void)startUpdatingLocation
{
NSLog(#"Starting location updates");
// Turn on location updates for accuracy and so processing can happen in the background.
[self.locationManager stopUpdatingLocation];
[self.locationManager startUpdatingLocation];
// Turn on significant location changes to help monitor the current region.
[self.locationManager startMonitoringSignificantLocationChanges];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
if (locations.count > 0) {
//stop all monitored region
for (CLRegion *monitored in [self.locationManager monitoredRegions]){
[self.locationManager stopMonitoringForRegion:monitored];
}
CLLocation *location = locations[0];
NSArray *allGeoFences = [self getAllGeoFences];
NSMutableArray *sortedFences = [[NSMutableArray alloc] init];
// add distance to each fence to be sorted
for (locationInterface *geofence in allGeoFences) {
// create a CLLocation object from my custom object
//CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(geofence.region., geofence.longitude);
CLLocation *fenceLocation = [[CLLocation alloc] initWithLatitude:
geofence.region.center.latitude
longitude:geofence.region.center.longitude];
// calculate distance from current location
CLLocationDistance distance = [location distanceFromLocation:fenceLocation];
// save distance so we can filter array later
geofence.distance = distance;
[sortedFences addObject:geofence];
}
// sort our array of geofences by distance and add we can add the first 20
NSSortDescriptor *sortByName = [NSSortDescriptor sortDescriptorWithKey:#"distance" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortByName];
NSArray *sortedArray = [sortedFences sortedArrayUsingDescriptors:sortDescriptors];
//get nearest 20 regions
NSMutableArray *nearestRegions = [[NSMutableArray alloc] init];
for (int i = 1; i <= 20; i++) {
[nearestRegions addObject:sortedArray[i]];
locationInterface* monitorRegion = sortedArray[i];
[self.locationManager startMonitoringForRegion:monitorRegion.region] ;
}
}
}
When i receive didUpdateLocations , first i stop all the monitored regions, After that i find 20 nearest locations,and start monitoring the 20 nearest locations.
The problem that I am facing is monitoredRegions always returned nil.That is why I cannot stop monitoring the regions and my newly added regions get ignored.Please help me.
I know that we can use the CoreLocation API in the AppleWatchKit code itself. But still, from the documentation, I read that the fetching of locations should be done only in the parent app and not in the watch app. Which is the standard way for doing this?
My requirement is simple. I need to show an annotation for the user location.
Get location like this in Apple Watch:
CLLocationManager *locationManager = [[CLLocationManager alloc]init];
locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
location = [locationManager location];
coordinate = [location coordinate];
latitude = [NSString stringWithFormat:#"%f", coordinate.latitude];
longitude = [NSString stringWithFormat:#"%f", coordinate.longitude];
Set annotation like this:
CLLocationCoordinate2D mapLocation = CLLocationCoordinate2DMake([lati floatValue], [longi floatValue]);
MKCoordinateSpan coordinateSpan = MKCoordinateSpanMake(1, 1);
[self.map setRegion:(MKCoordinateRegionMake(mapLocation, coordinateSpan))];
//For coloured pin
//[self.map addAnnotation:mapLocation withPinColor: WKInterfaceMapPinColorGreen];
[self.map addAnnotation:mapLocation withImage:[UIImage imageNamed:#"mapPin.png"] centerOffset:CGPointMake(0,-7)];
Here, "map" is the object of watchkit map.
This is my First Sprite game, and for some reason the only difficult I've been run to is the admob integration.
This is my ViewDidLoad
- (void)viewDidLoad
{
[super viewDidLoad];
// showing for the first time my AdMob Interstitial
[self showAdmobFullscreen];
// Configure the view.
SKView * skView = (SKView *)self.view;
SKScene *mc = [GameScene01 sceneWithSize:skView.bounds.size];
mc.scaleMode = SKSceneScaleModeAspectFill;
[skView presentScene:mc];
}
and this is my Admob Settings:
-(void)showAdmobFullscreen{
NSLog(#" showAdmoBFullScreenCalled");
// self.interstitial_ = [[GADInterstitial alloc] init];
// self.interstitial.delegate = self;
// self.interstitial.adUnitID = ADMOB_FULLSCREEN_ID;
// [self.interstitial loadRequest:[self adMobrequest]];
interstitial_ = [[GADInterstitial alloc]init];
interstitial_.delegate = self;
interstitial_.adUnitID = #"ca-app-pub-1032576214759203/773434443";
[interstitial_ loadRequest:[self adMobrequest]];
}
- (GADRequest *)adMobrequest {
NSLog(#"requestHasBeenCalled");
GADRequest *request = [GADRequest request];
request.testDevices = #[
// TODO: Add your device/simulator test identifiers here. Your device identifier is printed to
// the console when the app is launched.
//#"9481d65c607d68c867a51229a3c61340"
];
return request;
}
So Far So Good, The admob is fire when the game load. now I want to fire it every time when the user lose in the game.
Right now the whole game run into my Sprite files, and what I tried todo is to call the 'showAdmobFullscreen' every time there's a GameOver
So in my Sprite.m file, I have a method called GameOver, I've added those lines :
-(void)GameOver
{
//Trying to make Admob shows whenever User loses a game
MyMainViewController *spVc = [[MyMainViewController alloc]init];
[spVc showAdmobFullscreen];
I can see the logs of my Admob are being called but no ads are showing up.
any suggestion will be appreciated .
Instead of
MyMainViewController *spVc = [[MyMainViewController alloc]init];
[spVc showAdmobFullscreen];
Try this
[self showAdmobFullscreen];
We are trying to create multiple pdf files by using UIView.layer's renderInContext method
The below code run in a autoreleasepool.
---loop
UIGraphicsBeginPDFContextToFile(documentDirectoryFilename, CGRectZero, nil);
UIGraphicsBeginPDFPage();
CGContextRef pdfContext = UIGraphicsGetCurrentContext();
[view.layer renderInContext:pdfContext];
view =nil;
pdfContext =nil
UIGraphicsEndPDFContext()
--loop ends
After couple of iterations resident memory increases to 20 mb and subsequent iteration adds to the total memory used.
Some how ARC is not releasing the memory used in rendering the pdf and thus the application crashes with low memory.
Application is using ARC
Any help or pointers to resolve the issue would be much appreciated.
Thanks
UPDATED:
Thanks for the quick reply.
My apologies for having a typo in the pseudocode.
Here is sample code from a test project.
-(BOOL)addUIViewToPDFFile:(UIView*)view newBounds:(CGRect)newBounds pdfFile:(NSString*)pdfFile{
BOOL retFlag =YES;
NSArray* documentDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);
NSString* documentDirectory = [documentDirectories objectAtIndex:0];
NSString* documentDirectoryFilename = [documentDirectory stringByAppendingPathComponent:pdfFile];
UIGraphicsBeginPDFContextToFile(documentDirectoryFilename, CGRectZero, nil);
CGContextRef pdfContext = UIGraphicsGetCurrentContext();
if([NSThread isMainThread]){
NSLog(#"Main Thread");
}else{
NSLog(#"Not in Main Thread");
}
UIGraphicsBeginPDFPage();
logMemUsage1();
[view.layer renderInContext:pdfContext];
UIGraphicsEndPDFContext();
pdfContext = nil;
logMemUsage1();
return retFlag;
}
- (IBAction)createPdf:(id)sender {
for(int i=0;i<10;i++){
#autoreleasepool {
PDFViewController *vc = [[PDFViewController alloc] init];
[vc loadView];
NSString *PdfFileName =[ NSString stringWithFormat:#"TestPdf%d.pdf",i ];
[self addUIViewToPDFFile:vc.view newBounds:self.view.frame pdfFile:PdfFileName];
vc = nil;
}
}
}
One more to point to add is that when application goes into the background on press of the hardware home button and comes back again to foreground the memory seems to get cleared and released.
I am expecting that after each iteration the memory which is used for creating the pdf should be released.
I know its something to do with locks or dispatch groups, but I just cant seem to code it...
I need to know if the address was a valid address before leaving the method. Currently the thread just overruns and returns TRUE. I've tried locks, dispatchers the works but can't seem to get it correct. Any help appreciated:
- (BOOL) checkAddressIsReal
{
__block BOOL result = TRUE;
// Lets Build the address
NSString *location = [NSString stringWithFormat:#" %# %#, %#, %#, %#", streetNumberText.text, streetNameText.text, townNameText.text, cityNameText.text, countryNameText.text];
// Put a pin on it if it is valid
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder geocodeAddressString:location
completionHandler:^(NSArray* placemarks, NSError* error) {
result = [placemarks count] != 0;
}];
return result;
}
The documentation says that CLGeocoder calls the completionHandler on the main thread. Since you are probably also calling your method from the main thread it cannot wait for the geocoder's answer without giving it the opportunity to deliver the result.
That would be done by polling the runloop, using some API as -[NSRunLoop runMode:beforeDate:].
The disadvantage is that depending on the mode this will also deliver events and fire timers while waiting for the result.
Just use block as parameter:
- (void) checkAddressIsRealWithComplectionHandler:(void (^)(BOOL result))complectionHandler
{
__block BOOL result = TRUE;
// Lets Build the address
NSString *location = [NSString stringWithFormat:#" %# %#, %#, %#, %#", streetNumberText.text, streetNameText.text, townNameText.text, cityNameText.text, countryNameText.text];
// Put a pin on it if it is valid
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder geocodeAddressString:location
completionHandler:^(NSArray* placemarks, NSError* error) {
result = [placemarks count] != 0;
complectionHandler(result);
}];
}