Аварийное приложение GoogleMaps SDK после модуляции проекта - PullRequest
1 голос
/ 21 февраля 2020

У меня есть рабочий проект с GoogleMaps, который отлично работает. Я сделал копию этого проекта, чтобы сделать проект модульным, и теперь я получаю ошибку EXC_BAD_ACCESS при попытке открыть карту.

вот моя конфигурация модуля:

def shared_pods
    ...
    pod 'GoogleMaps', :modular_headers => true
    pod 'GooglePlaces', :modular_headers => true
end

def application_pods
    ...
end


def core_application_pods
...
end


target 'Application' do

  project 'Application/Application.xcodeproj'

  # Pods for Application

  shared_pods
  application_pods

  target 'ApplicationTests' do
    inherit! :search_paths
    # Pods for testing
  end

  target 'ApplicationUITests' do
    # Pods for testing
  end
end

target 'Core' do

    project 'Core/Core.xcodeproj'

    # Pods for Core

    shared_pods
    core_application_pods

    target 'CoreTests' do
      inherit! :search_paths
      # Pods for testing
    end
end

# Static libraries
static_libraries = ['GoogleMaps', 'GoogleMapsBase', 'GoogleMapsCore']#, 'GooglePlaces']

post_install do |installer|
puts "Running post_install script"

puts "Fix static_libraries"
installer.aggregate_targets.each do |aggregate_target|
    unless ['Pods-Application'].include? aggregate_target.name
        aggregate_target.xcconfigs.each do |config_name, config_file|
            config_file.frameworks.subtract(static_libraries)
            xcconfig_path = aggregate_target.xcconfig_path(config_name)
            config_file.save_as(xcconfig_path)
        end
    end
end
...
end

Я даже попытался поместить оба модуля в shared_pods, включить / отключить modular_headers, и в результате нет разницы.

Вот часть кода, который создает объект UIGMapsView. Объект успешно создан, и делегаты Карт запускаются до того, как cra sh ..

final fileprivate func setupMapViewConstraints() {
        if self.mapView == nil {
            let mapView = UIGMapsView(frame: CGRect(x: 0, y: 0, width: 0, height: 0))
            mapView.gmapDelegate = self
            mapView.translatesAutoresizingMaskIntoConstraints = false
            mapView.settings.myLocationButton = false
            self.mapView = mapView
        }

        if let mapView = self.mapView {

            self.view.addSubview(mapView)
                self.view.sendSubviewToBack(mapView)

            let views : [String: UIView] = ["mapView": mapView]
            let vertical = NSLayoutConstraint.constraints(withVisualFormat: "V:|[mapView]|", options: [], metrics: nil, views: views)
            let horizontal = NSLayoutConstraint.constraints(withVisualFormat: "H:|[mapView]|", options: [], metrics: nil, views: views)

            NSLayoutConstraint.activate(vertical + horizontal)

            autoreleasepool {
                mapView.startMonitoringLocation()
                mapView.backToMyPosition()
            }
        }
    }

Экран откроется, и примерно через 1 секунду на этом экране появится cra sh. (Я даже могу видеть синюю точку в середине карты, но карта вся серая ...)

Я даже пытался включить Zomb ie, чтобы попытаться выяснить, что вызывает это, но не так много там тоже помощь ... вот скриншот:

crash screenshot

Кто-нибудь знает, что может быть причиной этого крэ sh?

Заранее спасибо!

РЕДАКТИРОВАНИЕ:

Я попробовал решение, упомянутое ниже, и ошибки Связи возникли во время сборки.

Неопределенные символы для архитектуры arm64:
"_OBJC_CLASS _ $ _ GMSServices", на который ссылаются из: obj c -class-ref в AppDelegate.o "_OBJC_CLASS _ $ _ GMSMapView", на который ссылаются из: типа метаданных для Natura.UIGMapsView в UIGMapsView.o "_OBLMASS _ $ _ _ _ _ _ _ _ _ _ _ _ _ _" : _OBJC_METACLASS _ $ __ TtC6Natura11UIGMapsView в UIGMapsView.o "_OBJC_CLASS _ $ _ GMSMutablePath", на который ссылаются из: obj c -класс-ref в UIGMapsView.o "_OBJC_CLASS _ $ _ Классифицируется * из-за ссылки на 10-й класс, в UGMCView. «_OBJC_ CLASS _ $ _ GMSCameraUpdate ", на который ссылается: obj c -class-ref в UIGMapsView.o obj c -class-ref в SearchConsultantOnMapViewController.o" _OBJC_CLASS _ $ _ GMSMarker ", на который ссылается: obj c UIGMapsView.o ld: символ (ы) не найден для архитектуры arm64 clang: error: сбой команды компоновщика с кодом выхода 1 (используйте -v для просмотра вызова)

У меня была дополнительная строка в сообщении Сценарий, который был:

unless ['Pods-Application'].include? aggregate_target.name

Таким образом, предлагаемое решение не было установлено основной проект, только для ядра. Но когда я убираю эту строку, появляется ошибка выше о неопределенных символах

Ответы [ 2 ]

1 голос
/ 05 марта 2020

Итак ... Наконец-то я обошел эту проблему. Это не идеально, но это лучший вариант, учитывая обстоятельства.

Так что, если у вас есть похожая проблема, я надеюсь, что это поможет.

GoogleMaps и GooglePlaces не работают хорошо, если импортированы в 2 проекта (некоторые ошибка дублирует модуль, и вы получаете 2 фреймворка для проекта во время выполнения и получаете cra sh, потому что он не знает, какой из них использовать)

Мой обходной путь - установить GoogleMaps и GooglePlaces только в мой основной проект. вот подфайл:

def shared_pods
    ...
end

def application_pods
    ...
end


def core_application_pods
    ...
    pod 'GoogleMaps', :modular_headers => true
    pod 'GooglePlaces', :modular_headers => true
end


target 'Application' do

  project 'Application/Application.xcodeproj'

  # Pods for Application

  shared_pods
  application_pods

  target 'ApplicationTests' do
    inherit! :search_paths
    # Pods for testing
  end

  target 'ApplicationUITests' do
    # Pods for testing
  end
end

target 'Core' do

    project 'Core/Core.xcodeproj'

    # Pods for Core

    shared_pods
    core_application_pods

    target 'CoreTests' do
      inherit! :search_paths
      # Pods for testing
    end
end

Убедитесь, что у вас нет GoogleMaps и GooglePlaces в проекте приложения в разделе Фазы сборки -> Связать двоичный файл с библиотеками

Я связал GooglePlaces в своем основном проекте в рамках сборки Фазы -> Связать бинарный файл с библиотеками (вам нужно вручную выбрать фреймворк, он находится внутри папки Pods). Не уверен, что это необходимо, потому что я не связывал GoogleMaps, и он также работает.

Создайте пользовательский класс, который будет работать в качестве оболочки для вашего проекта приложения для использования каркаса GoogleMaps, например:

import GoogleMaps

public class NTGMSServices : GMSServices {
    convenience override init() {
        self.init()
    }
}

public class NTGMSCameraUpdate : GMSCameraUpdate {}

и

import GooglePlaces

public class NTGMSPlace : GMSPlace {}
public class NTGMSAutocompletePrediction : GMSAutocompletePrediction {}
public class NTGMSAutocompleteFetcher : GMSAutocompleteFetcher {
    convenience init() {
        self.init()
    }
}
public class NTGMSPlacesClient : GMSPlacesClient {}
public class NTGMSAutocompleteFilter : GMSAutocompleteFilter {}
public protocol NTGMSAutocompleteFetcherHandlerDelegate  {
    func didAutocomplete(with predictions: [NTGMSAutocompletePrediction])
    func didFailAutocompleteWithError(_ error: Error)
}

public class NTAutocompleteFetcherHandler : NSObject {
    public var delegate: NTGMSAutocompleteFetcherHandlerDelegate?
}
extension NTAutocompleteFetcherHandler : GMSAutocompleteFetcherDelegate {

    public func didAutocomplete(with predictions: [GMSAutocompletePrediction]) {
        delegate?.didAutocomplete(with: predictions as! [NTGMSAutocompletePrediction])
    }

    public func didFailAutocompleteWithError(_ error: Error) {
        delegate?.didFailAutocompleteWithError(error)
    }
}

Убедитесь, что вы изменили все переменные, которые вы использовали в проекте приложения, на эти новые типы и импортировали Core вместо импорта GoogleMaps или GooglePlaces и адаптировали протокол, если вы используете GMSAutocompleteFetcherDelegate

Убедитесь, что вы очистили и перестроили весь проект.

Таким образом, каркасы GoogleMaps и GooglePlaces не будут дублироваться из-за ошибки CocoaPods или реализации каркаса Google.

Вы можете следить, если Cocoapods исправит эту проблему здесь

1 голос
/ 21 февраля 2020

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

Обычно то, что я делал в прошлом для работы вокруг этой проблемы добавлял GoogleMaps ко всем модулям (что также приведет к загрузке двоичного файла GoogleMaps в каждом отдельном модуле), а затем написал скрипт post_install внутри Podfile для анализа всех сгенерированных xcconfig файлов через Podfile и удаления всех GoogleMap зависимостей (-framework GoogleMaps -framework GoogleBundle ...). Таким образом, в вашем приложении будет только один загруженный двоичный файл GoogleMaps , но все ваши модули смогут видеть и работать с GoogleMaps .

необходимо вручную анализировать файлы xcconfig, Cocoapods предоставляет их в post_install |installer| и надежный API для их изменения. Вы можете проверить документ Cocoapod для получения дополнительной информации. Это будет что-то вроде:

# Static libraries
static_libraries = ['GoogleMaps', 'GoogleMapsBase', 'GoogleMapsCore']

target 'Application' do
    pod 'GoogleMaps'
end

target 'Core' do
    project 'Core/Core'
    pod 'GoogleMaps'
end

# Post Installer section
post_install do |installer|
    puts "Running post_install script"

    puts "Fix static_libraries"
    installer.aggregate_targets.each do |aggregate_target|
        aggregate_target.xcconfigs.each do |config_name, config_file|
            config_file.frameworks.subtract(static_libraries)
            xcconfig_path = aggregate_target.xcconfig_path(config_name)
            config_file.save_as(xcconfig_path)
        end
    end
end
...