Использование нескольких маяков (отображение представления для каждого отдельного маяка)

Я новичок в задаче C. Мое приложение корректно работает с одним маяком. Я использую "estimote SDK". У меня много проблем, я хочу использовать 2 или 3 маяка. Я хочу нажать View для каждого из маяков.

Я не понимаю, как я могу сделать это с несколькими маяками.

  1. Я не знаю, нужно ли мне использовать несколько диспетчеров маяков. (ESTBeaconManager* beaconManager)

  2. Я не знаю, как передать разные регионы в didRangeBeacons:(NSArray *)beacons inRegion:(ESTBeaconRegion *)region

  3. Могу ли я использовать один маяк только для уведомления, а два других — для отображения двух разных видов, когда я закрываюсь от них. (один вид для каждого маяка)

Спасибо за вашу помощь.

С уважением.

Код:

#import "ESTViewController.h"
#import "PresentViewController.h"
#import <ESTBeaconManager.h>
#import <AudioToolbox/AudioToolbox.h>

@interface ESTViewController () <ESTBeaconManagerDelegate>

@property (nonatomic, strong) ESTBeaconManager* beaconManager;
@property (nonatomic, strong) ESTBeaconManager* beaconManager2;
@property (nonatomic, strong) ESTBeaconManager* beaconManager3;

@property (nonatomic, strong) ESTBeacon* selectedBeacon;


@end

@implementation ESTViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    // should i create one manager instance or more ?

    self.beaconManager = [[ESTBeaconManager alloc] init];
    self.beaconManager.delegate = self;
    self.beaconManager.avoidUnknownStateBeacons = NO;

    //self.beaconManager2 = [[ESTBeaconManager alloc] init];
    //self.beaconManager2.delegate = self;
    //self.beaconManager2.avoidUnknownStateBeacons = NO;

    //self.beaconManager3 = [[ESTBeaconManager alloc] init];
    //self.beaconManager3.delegate = self;
    //self.beaconManager3.avoidUnknownStateBeacons = NO;



    // My Differents regions


    region = [[ESTBeaconRegion alloc] initWithProximityUUID:ESTIMOTE_PROXIMITY_UUID
                                                      major:12800 minor:228 identifier:@"Icy Marshmellow"];

    region2 = [[ESTBeaconRegion alloc] initWithProximityUUID:ESTIMOTE_PROXIMITY_UUID
                                                       major:12800 minor:128 identifier:@"Mint Cocktail"];

    region3 = [[ESTBeaconRegion alloc] initWithProximityUUID:ESTIMOTE_PROXIMITY_UUID
                                                       major:12800 minor:328 identifier:@"Blueberry Pie"];


    // Should i do it for each region with one ESTBeaconManager or 3 ?

    [self.beaconManager requestStateForRegion:region];
    [self.beaconManager requestStateForRegion:region2];
    [self.beaconManager requestStateForRegion:region3];


}

// NOTIFICATION METHOD :

-(void)beaconManager:(ESTBeaconManager *)manager
      didEnterRegion:(ESTBeaconRegion *)region
{
    // iPhone/iPad entered beacon zone

    // present local notification
    UILocalNotification *notification = [[UILocalNotification alloc] init];
    notification.alertBody = @"Hello blabla blabla";
    notification.soundName = UILocalNotificationDefaultSoundName;

    [[UIApplication sharedApplication] presentLocalNotificationNow:notification];
}

-(void)beaconManager:(ESTBeaconManager *)manager
       didExitRegion:(ESTBeaconRegion *)region
{
    // iPhone/iPad left beacon zone

    // present local notification
    UILocalNotification *notification = [[UILocalNotification alloc] init];
    notification.alertBody = @"bye bye";
    notification.soundName = UILocalNotificationDefaultSoundName;

    [[UIApplication sharedApplication] presentLocalNotificationNow:notification];
}



- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [self.beaconManager startRangingBeaconsInRegion:region];
    [self.beaconManager startMonitoringForRegion:region];

    //[self.beaconManager2 startRangingBeaconsInRegion:region2];
    //[self.beaconManager2 startMonitoringForRegion:region2];

    //[self.beaconManager3 startRangingBeaconsInRegion:region3];
    //[self.beaconManager3 startMonitoringForRegion:region3];


}

  - (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];

    [self.beaconManager stopRangingBeaconsInRegion:region];
    [self.beaconManager stopMonitoringForRegion:region];

    //[self.beaconManager2 stopRangingBeaconsInRegion:region2];
    //[self.beaconManager2 stopMonitoringForRegion:region2];

    //[self.beaconManager3 stopRangingBeaconsInRegion:region3];
    //[self.beaconManager3 stopMonitoringForRegion:region3];

}

// My problem is here , i dont know how i can pass differents regions here


-(void)beaconManager:(ESTBeaconManager *)manager
     didRangeBeacons:(NSArray *)beacons
            inRegion:(ESTBeaconRegion *)region
{
    if([beacons count] > 0)
    {

        if(!self.selectedBeacon)
        {
            // initialy pick closest beacon
            self.selectedBeacon = [beacons objectAtIndex:0];
        }
        else
        {
            for (ESTBeacon* cBeacon in beacons)
            {
                // update beacon it same as selected initially
                if([self.selectedBeacon.major unsignedShortValue] == [cBeacon.major unsignedShortValue] &&
                   [self.selectedBeacon.minor unsignedShortValue] == [cBeacon.minor unsignedShortValue])
                {
                    self.selectedBeacon = cBeacon;
                }
            }
        }



        switch (self.selectedBeacon.proximity)
        {
            case CLProximityUnknown:
            {

                self.rangeStatusImageView.image = [UIImage imageNamed:@"logo_signal.jpg"];
                self.descriptionStateLabel.text = @"Signal lost";
                break;
            }
            case CLProximityImmediate:
            {
                [self performSegueWithIdentifier: @"presentSegue" sender: self];
                break;
            }
            case CLProximityNear:
            {
                self.rangeStatusImageView.image = [UIImage imageNamed:@"logo_near_bleu.jpg"];
                self.descriptionStateLabel.text = @"Come closer";
                break;

            }
            case CLProximityFar:
            {
                self.rangeStatusImageView.image = [UIImage imageNamed:@"logo_far_clair.jpg"];
                self.descriptionStateLabel.text = @"Welcome";
                break;
            }

            default:
                break;
        }


    }
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];

}

@end

ИЗМЕНИТЬ

Хорошо, я работал над своим кодом, и теперь я делаю это с одним регионом. мой массив маяков имеет 3 маяка.

region = [[ESTBeaconRegion alloc] initWithProximityUUID:ESTIMOTE_PROXIMITY_UUID identifier:@"multibeacons"];

я не использую мажор или минор в инициализации.

в ViewDidAppears я делаю:

[self.beaconManager startRangingBeaconsInRegion:region];

Такой делегат:

-(void)beaconManager:(ESTBeaconManager *)manager
     didRangeBeacons:(NSArray *)beacons
            inRegion:(ESTBeaconRegion *)region
{

// I used a sort , sorting by distance
    NSSortDescriptor *sortDescriptor;
    sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"distance" ascending:YES];
    NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];

// if breakpoint here 3 beacons in array
    self.beaconsArray = [beacons sortedArrayUsingDescriptors:sortDescriptors];

    if([self.beaconsArray count] > 0)
    {

        if(!self.selectedBeacon)
        {
            // initialy pick closest beacon
            self.selectedBeacon = [beacons objectAtIndex:0];
            currentBeaconMinor = self.selectedBeacon.minor;
        }
        else
        {
            for (ESTBeacon* cBeacon in self.beaconsArray)
            {
                // update beacon it same as selected initially
                if([self.selectedBeacon.major unsignedShortValue] == [cBeacon.major unsignedShortValue] &&
                   [self.selectedBeacon.minor unsignedShortValue] == [cBeacon.minor unsignedShortValue])
                {
                    self.selectedBeacon = cBeacon;
                    currentBeaconMinor = self.selectedBeacon.minor;
                }
            }
        }

Я сортирую по расстоянию, и у меня есть значение currentBeaconMinor. В моем массиве маяков есть 3 маяка, если я поставлю точку останова, я увижу 3.

В близости Switch я делаю так:

switch (self.selectedBeacon.proximity)
        {

            case CLProximityImmediate:
            {

                if ([currentBeaconMinor floatValue] == 128)
                {
                    NSLog(@"128 128 128");
                    //[self performSegueWithIdentifier: @"presentSegue1" sender: self];
                }

                else if ([currentBeaconMinor floatValue] == 228)
                {
                    NSLog(@"228 228 228");
                    //[self performSegueWithIdentifier: @"presentSegue2" sender: self];
                }
                else if ([currentBeaconMinor floatValue] == 328)
                {
                    NSLog(@"328 328 328");
                    //[self performSegueWithIdentifier: @"presentSegue3" sender: self];
                }

                break;
            }

Но это все еще не работает :((( Я злюсь. Мое приложение изначально выбирает ближайший маяк. После этого приложение всегда сохраняет один и тот же маяк и никогда не меняется. Я перемещаю маяк рядом с устройством, но nslog всегда отправляет мне один и тот же младший номер Пожалуйста, не могли бы вы мне помочь?Я уверен, что делаю что-то не так.


person mad_mask    schedule 19.05.2014    source источник
comment
нет необходимости сортировать, Estimote SDK при поиске маяков возвращает уже отсортированный по расстоянию массив маяков   -  person raistlin    schedule 03.06.2014


Ответы (2)


Каждый маяк имеет 3 части информации — UUID, старший номер и младший номер. Когда вы создаете маяковый регион, вы должны указать как минимум UUID. При желании вы можете указать основное и дополнительное значение. Существует ограничение на количество областей-маяков, которые iOS будет сканировать в фоновом режиме (я полагаю, что это 20), поэтому, как правило, лучше указать как можно более широкую регистрацию вашего региона, а затем определить, когда будет получено уведомление, если вы заинтересованы. в маяке, который виден.

Все маяки Estimote имеют одинаковый UUID, поэтому, если вы зарегистрируете регион только с UUID, ваше приложение будет получать уведомления всякий раз, когда вы находитесь в диапазоне любого маяка Estimote. Я вижу, что все ваши три маяка используют основной 12800, поэтому вы можете просто создать регион, в котором указаны UUID и основной, а затем вы будете получать уведомления всякий раз, когда маяк с этими значениями был виден, или вы можете сделать то, что вы сделали и зарегистрируйте определенные регионы для каждого из ваших трех маяков.

Вам нужен только один экземпляр EstBeaconManager для управления всеми регионами.

Всякий раз, когда вы входите в регион или выходите из него, будут вызываться ваши методы didEnterRegion и didExitRegion. Также ваш метод didRangeBeacons будет вызываться, если вы в данный момент настраиваете маяки.

В этих методах делегата вам нужно проверить основные и второстепенные (ну, на самом деле только второстепенные, потому что в вашем случае основные всегда одни и те же) значения, чтобы определить, какое действие вы хотите предпринять. Вы также можете проверить строку идентификатора региона, чтобы определить, какой маяк виден.

Обратите внимание, что в радиусе действия может находиться более одного маяка, поэтому вам может потребоваться изучить окрестности, чтобы определить, какое действие вы хотите предпринять.

Наконец, хотя вы определяете три региона, вы не ранжируете/отслеживаете их все, поэтому измените viewWillAppear на

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [self.beaconManager startRangingBeaconsInRegion:region];
    [self.beaconManager startMonitoringForRegion:region];

    [self.beaconManager startRangingBeaconsInRegion:region2];
    [self.beaconManager startMonitoringForRegion:region2];

    [self.beaconManager startRangingBeaconsInRegion:region3];
    [self.beaconManager startMonitoringForRegion:region3];


}
person Paulw11    schedule 19.05.2014
comment
Вы имеете в виду это для идентификатора? (void)beaconManager:(ESTBeaconManager *)manager didEnterRegion: (ESTBeaconRegion *)region { if ([region.identifier isEqualToString:@firstRegionIdenfifier]) { // сделать что-то } else if ([region.identifier isEqualToString:@secondRegionIdentifier]) { // делаем что-то еще } } - person mad_mask; 19.05.2014
comment
Да, или вы можете посмотреть числовое значение минора - person Paulw11; 19.05.2014
comment
У вас есть переменная экземпляра с именем «регион» и локальная переменная с именем «регион» — переименуйте одну из них. - person Paulw11; 19.05.2014
comment
Большое спасибо за вашу помощь, я работал над своим кодом, но у меня всегда один и тот же маяк в маяках массива (я использовал точки останова): -(void)beaconManager:(ESTBeaconManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(ESTBeaconRegion *)region { if([beacons count] > 0) { // do something } } Массив содержит только маяки региона1, у меня регион2 и 3, но, даже если я уберите мои маяки, они обнаруживаются всегда одинаково. Также мне нужно, чтобы этот массив был отсортирован, чтобы иметь возможность отображать разные представления для каждого маяка (в случае немедленного). - person mad_mask; 19.05.2014
comment
Как я уже сказал в своем ответе, вам нужно проработать массив, чтобы определить ближайший маяк в случае, когда вы видите более одного. Вы можете использовать свойство расстояния, чтобы помочь - person Paulw11; 20.05.2014
comment
я пробовал, как ты сказал, с сортировкой массива по расстоянию. (см. мой код, который я отредактировал внизу), но это все еще не работает. Надеюсь, ты поможешь мне в этом. заранее спасибо . С наилучшими пожеланиями. - person mad_mask; 21.05.2014
comment
Я не вижу, как ваш обновленный код когда-либо изменит self.selectedBeacon. Он устанавливается, когда он изначально равен нулю, но после этого он устанавливается только тогда, когда минор и мажор совпадают, поэтому он будет установлен на один и тот же маяк. - person Paulw11; 22.05.2014
comment
Спасибо за вашу помощь. Мне нужно установить ближайший маяк, но я не знаю, как это сделать :(. Я знаю, что у меня есть хороший способ сделать это. Может быть, вы можете сказать мне, как действовать? `Мне нужно снова отсортировать его с помощью self.beaconsArray = [маяки sortedArrayUsingDescriptors:sortDescriptors];` ? - person mad_mask; 22.05.2014
comment
Вы уже отсортировали массив по расстоянию по возрастанию, поэтому [self.beaconsArray objectAtIndex:0] будет ближайшим. - person Paulw11; 22.05.2014
comment
ДА! Я сделал это. Большое спасибо ! if([self.beaconsArray count] > 0) { if(!self.selectedBeacon) { // initialy pick closest beacon self.selectedBeacon = [beacons objectAtIndex:0]; currentBeaconMinor = self.selectedBeacon.minor; } else { self.beaconsArray = [beacons sortedArrayUsingDescriptors:sortDescriptors]; if(self.selectedBeacon != [beacons objectAtIndex:0] ) { self.selectedBeacon = [beacons objectAtIndex:0]; currentBeaconMinor = self.selectedBeacon.minor; } - person mad_mask; 22.05.2014

Я раньше не использовал Estimote SDK. Я просто рассматриваю свои маяки Estimote как ванильные iBeacons и использую структуру Apple Location Manager.

Мне кажется, вы очень запутались.

Я бегло взглянул на Estimote SDK, и он очень похож на диспетчер местоположений Apple.

В диспетчере местоположения вы создаете область маяка, затем вы просите диспетчера местоположения начать ранжирование для этой области маяка (что сообщает вам о расчетных показаниях расстояния или вы используете startMonitoringForRegion, чтобы запросить уведомление о событиях входа/выхода в область).

Вы можете делать и то, и другое одновременно. Глядя на Estimate API, похоже, что они используют тот же подход.

Вам нужно создать регион-маяк, затем вызвать startRangingBeaconsInRegion и/или startMonitoringForRegion, чтобы запросить диапазон и/или уведомления о входе/выходе региона.

Затем вы ждете, пока будут вызваны методы вашего делегата, когда маяк входит/выходит из диапазона (startMonitoringForRegion) или изменяет расстояние (startRangingBeaconsInRegion)

Глядя на документы, кажется, что вызов requestStateForRegion приведет к тому, что диспетчер маяков Estimote вызовет ваш метод locationManager:didDetermineState:forRegion: delegate один и только один раз.

В вашем коде вы не запрашивали мониторинг регионов или диапазон маяков, поэтому все 3 региона вернут состояние «не в диапазоне».

Не вызывайте эти requestStateForRegion. Вызовите startMonitoringForRegion и/или startRangingBeaconsInRegion и подождите, пока система не уведомит вас об изменении статуса маяка.

person Duncan C    schedule 19.05.2014