Как масштабировать изображение аннотации на MapKit Map? IN SWIFT [дубликат]

Ссылка NullReferenceException или Object, не установленная на экземпляр объекта, возникает, когда объект класса, который вы пытаетесь использовать, не создается. Например:

Предположим, что у вас есть класс с именем Student.

public class Student
{
    private string FirstName;
    private string LastName;
    public string GetFullName()
    {
        return FirstName + LastName;
    }
}

Теперь рассмотрим другой класс, в котором вы пытаетесь получить полное имя учащегося.

public class StudentInfo
{      
    public string GetStudentName()
    {
        Student s;
        string fullname = s.GetFullName();
        return fullname;
    }        
}

Как видно из вышеприведенного кода, оператор Student s - объявляет только переменную типа Student, обратите внимание, что класс Student не создается в этой точке. Следовательно, когда выполняется выполнение инструкции s.GetFullName (), она выкинет исключение NullReferenceException.

6
задан shannoga 27 November 2011 в 17:42
поделиться

5 ответов

Фактически на MKMapView по умолчанию - аннотация (например, контакт или изображение) и выноска (например, пузырь) остаются того же размера, что и вы увеличиваете или уменьшаете масштаб. Они не масштабируются. Но я получаю вашу точку зрения по отношению к карте, которую они, по-видимому, растут по мере того, как карта масштабируется и сжимается по мере приближения карты.

Итак, есть две проблемы в вашей проблеме, и они работают несколько иначе:

  1. Внедрите -(void)mapView:(MKMapView *)pMapView regionDidChangeAnimated:(BOOL)animated из ссылки протокола MKMapViewDelegate, которую вы уже выполнили.
  2. Прикрепите UIPinchGestureRecognizer к объекту MKMapView, а затем выполните действие.

Вариант №1 - mapView:regionDidChangeAnimated: будет вызван либо для прокрутки, либо для события масштабирования - в основном в любое время, когда область карты изменилась с учетом названия. Это приводит к чуть менее плавному изменению размеров значков, потому что события карты срабатывают реже.

Мои настройки предназначены для варианта № 2 - присоедините UIPinchGestureRecognizer к объекту MKMapView и затем выполните действие. События жестового нажатия запускаются довольно быстро, поэтому вы получаете плавное изменение размера значка. И они только срабатывают для распознанного события пинча, поэтому они не будут стрелять во время события прокрутки.

Вызванные методы действия должны соответствовать одной из следующих подписей:

- (void)handleGesture; - (void)handleGesture:(UIGestureRecognizer *)gestureRecognizer;

Вы должны быть осторожны, чтобы не переопределять поведение по умолчанию по умолчанию для карт. См. Это сообщение: «UIMapView: UIPinchGestureRecognizer не называется» для получения дополнительной информации. Короткий ответ заключается в том, что вы должны реализовать shouldRecognizeSimultaneouslyWithGestureRecognizer: и вернуть YES.

Все сказанное здесь - это пример кода:

// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
    [super viewDidLoad];

    self.mapView.mapType = MKMapTypeStandard;   // also MKMapTypeSatellite or MKMapTypeHybrid

    // Add a pinch gesture recognizer
    UIPinchGestureRecognizer *pinchRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinchGesture:)];
    pinchRecognizer.delegate = self;
    [self.mapView addGestureRecognizer:pinchRecognizer];
    [pinchRecognizer release];
}

#pragma mark -
#pragma mark UIPinchGestureRecognizer

- (void)handlePinchGesture:(UIPinchGestureRecognizer *)pinchRecognizer {
    if (pinchRecognizer.state != UIGestureRecognizerStateChanged) {
        return;
    }

    MKMapView *aMapView = (MKMapView *)pinchRecognizer.view;

    for (id <MKAnnotation>annotation in aMapView.annotations) {
        // if it's the user location, just return nil.
        if ([annotation isKindOfClass:[MKUserLocation class]])
            return;

        // handle our custom annotations
        //
        if ([annotation isKindOfClass:[MKPointAnnotation class]])
        {
            // try to retrieve an existing pin view first
            MKAnnotationView *pinView = [aMapView viewForAnnotation:annotation];
            //Format the pin view
            [self formatAnnotationView:pinView forMapView:aMapView];
        }
    }    
}

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
    return YES;
}

Итак, на этом этапе у вас снова есть несколько вариантов как изменить размер аннотации. Оба следующих примера кода полагаются на код Трой Бранта для получения уровня масштабирования MKMapView .

  1. Измените размер аннотационного изображения и выноска с помощью преобразования. Лично я думаю, что преобразование приводит к более чистому изменению размера. Но в большинстве случаев - изменение размера выноски не требуется.
  2. Измените размер только аннотационного изображения. Я использую . Тревор Harmon's Resize a UIImage правильный путь , но опять же мое мнение состоит в том, что оно не так чисто выглядит, как изменение размера.

Вот еще пример кода:

- (void)formatAnnotationView:(MKAnnotationView *)pinView forMapView:(MKMapView *)aMapView {
    if (pinView)
    {
        double zoomLevel = [aMapView zoomLevel];
        double scale = -1 * sqrt((double)(1 - pow((zoomLevel/20.0), 2.0))) + 1.1; // This is a circular scale function where at zoom level 0 scale is 0.1 and at zoom level 20 scale is 1.1

        // Option #1
        pinView.transform = CGAffineTransformMakeScale(scale, scale);

        // Option #2
        UIImage *pinImage = [UIImage imageNamed:@"YOUR_IMAGE_NAME_HERE"];
        pinView.image = [pinImage resizedImage:CGSizeMake(pinImage.size.width * scale, pinImage.size.height * scale) interpolationQuality:kCGInterpolationHigh];
    }
}

Если это работает, не забудьте отметить его как ответ.

25
ответ дан Funktional 27 August 2018 в 23:29
поделиться

Альтернативным методом было бы изменить размер свойства изображения представления аннотаций. Пример: , показанный в этом сообщении

1
ответ дан Community 27 August 2018 в 23:29
поделиться

@ Ответ Funktional в Swift 3:

class MapViewController: UIViewController: UIGestureRecognizerDelegate {

    @IBOutlet weak var mapView: MKMapView!

    override func viewDidLoad() {
        super.viewDidLoad()

        // You can also add this gesture recognizer and set the delegate via storyboard
        let pinchGR = UIPinchGestureRecognizer(target: self, action: #selector(handlePinchGesture))
        pinchGR.delegate = self
        self.mapView.addGestureRecognizer(pinchGR)
    }

    // link as @IBAction when added via storyboard
    func handlePinchGesture(_ sender: UIPinchGestureRecognizer) {
        if sender.state == .ended {
            for annotation in mapView.annotations {
                if annotation is MKUserLocation {
                    continue
                }
                guard let annotationView = self.mapView.view(for: annotation) else { continue }
                let scale = -1 * sqrt(1 - pow(mapView.zoomLevel / 20, 2.0)) + 1.4
                annotationView.transform = CGAffineTransform(scaleX: CGFloat(scale), y: CGFloat(scale))
            }
        }
    }

    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }
}

extension MKMapView {
    var zoomLevel: Double {
        return log2(360 * ((Double(self.frame.size.width) / 256) / self.region.span.longitudeDelta)) - 1
    }
}
1
ответ дан ElegyD 27 August 2018 в 23:29
поделиться

В Swift 3 это сработало для меня. Мое изображение было 100% на уровне 19, поэтому 1/19 дает мне 0,5263158, что является моей линейной шкалой:

func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {    
  if annotation is MKUserLocation {
    return nil
  }

  let mkView = MKAnnotationView(annotation: annotation, reuseIdentifier: "mkView")
  mkView.image = UIImage(named: "Foo")
  formatAnnotation(pinView: mkView, forMapView: mapView)
  return mkView;
}

func formatAnnotation(pinView: MKAnnotationView, forMapView: MKMapView) {
  let zoomLevel = forMapView.getZoomLevel()
  let scale = 0.05263158 * zoomLevel //Modify to whatever scale you need.
  pinView.transform = CGAffineTransform(scaleX: CGFloat(scale), y: CGFloat(scale))
}
1
ответ дан JoeGalind 27 August 2018 в 23:29
поделиться

Извините за мой плохой английский ... но я просто хочу помочь кому-то.

Большое спасибо, Funktional. Ваш ответ велик ... его работа над iOS5 отлично! Но это недействительно на iOS6, и, похоже, пока нет решения для решения этой проблемы.

Но, наконец, я решил это глупо / статически, и он отлично работает на обоих iOS. Я не собираюсь объяснять слишком много. Это то, что я сделал в своем проекте.

  1. Изображение для mkannotation называется pin.png (размер 20x20)
  2. Я создал еще пять изображений с разный размер для разных уровней масштабирования (18x18, 16x16, 14x14, 12x12, 10x10), и они называются pin-5.png, pin-4.png, pin-3.png, pin-2.png, pin-1.png .
  3. Я удалил весь код вычисления шкалы в форматеAnnotationView и добавил эту строку
    NSString* imageName = 
        [NSString stringWithFormat:@"%@%@.png", 
        [imageName substringToIndex:[imageName length]-4 ], 
        [self getImageLevel]];
    
  4. Также измените это из UIImage * pinImage = [UIImage imageNamed: @ "YOUR_IMAGE_NAME_HERE"] ; в UIImage * pinImage = [[UIImage alloc] initWithContentsOfFile: imageName];
  5. добавить эту функцию
    -(NSString *)getImageLevel{
    
    NSString* output;
    
    double zoomLevel = [self getZoomLevel:_mapview];
    
    
    if(zoomLevel >= 19.0)
        output = @"";
    else if(zoomLevel < 19.0 && zoomLevel >= 18.0)
        output = @"-5";
    else if(zoomLevel < 18.0 && zoomLevel >= 17.0)
        output = @"-4";
    else if(zoomLevel < 17.0 && zoomLevel >= 16.0)
        output = @"-3";
    else if(zoomLevel < 16.0 && zoomLevel >= 15.0)
        output = @"-2";
    else 
        output = @"-1";
    
    return output;}
    

извините за плохое кодирование и заново английскую.

1
ответ дан Vikdor 27 August 2018 в 23:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: