После обновления до Xcode 11.2 с Xcode 11.1 приложение вылетает из-за _UITextLayoutView - PullRequest
304 голосов
/ 01 ноября 2019

После обновления до Xcode 11.2 из Xcode 11.1 мое приложение аварийно завершает работу:

*** Завершение работы приложения из-за необработанного исключения «NSInvalidUnarchiveOperationException», причина: «Не удалось создать экземпляр класса с именем _UITextLayoutView, так как класс не назван_UITextLayoutView был найден;класс должен быть определен в исходном коде или связан с библиотекой (убедитесь, что класс является частью правильной цели) '

Почему это происходит? Как я могу предотвратить этот сбой?

Ответы [ 12 ]

191 голосов
/ 01 ноября 2019

Обновление: исправлено! 100

ЕДИНСТВЕННОЕ решение заключается в обновлении

Эта ошибка исправлена ​​ в Xcode 11.2.1. Таким образом, вы можете скачать и использовать его здесь.

Раскадровки, содержащие UITextView, больше не будут вызывать сбой приложения на версиях операционной системы ранее, чем iOS13.2, tvOS 13.2 или macOS 10.15.2. (56808566, 56873523)


Xcode 11.2 устарела Apple 5 ноября 2019

, если вы когда-нибудь попытаетесь отправить свое приложение, созданное с Xcode 11.2, в AppStore, вам будет отказано:

Предупреждение операции подключения к App Store

ПРЕДУПРЕЖДЕНИЕ ITMS-90703 : "Устаревшая сборка Xcode. Из-за разрешенных архивов приложенийиз-за проблем мы устарели в Xcode 11.2 5 ноября 2019 года. Скачайте Xcode 11.2.1 или новее, перестройте свое приложение и повторите отправку. "

Так что все обходные пути, сделанные с Xcode 11.2, бесполезно


Это ошибка для Xcode 11.2, исправленная в Xcode 11.2.1.

Решение (я)

Rollвернуться к предыдущему Xcode release версии от: Откат больше не возможен, и AppStore отклонит любую сборку с Xcode ниже 11.2.1 , посмотрите на

https://developer.apple.com/services-account/download?path=/Developer_Tools/Xcode_11.1/Xcode_11.1.xip

Обратите внимание, что вы должны использовать Safari, чтобы сделатьwnload его, и вы должны сначала войти на портал разработчиков Apple .

Все другие версии Xcode и ссылку на другие ресурсы (включая релизные и бета-версии) можно найти здесь на https://developer.apple.com/download/more

Обходной путь

Это очень сложный, но рабочий обходной путь. Замените все UITextView с в раскадровке с и Xib с версией с чистым кодом .


Обратите внимание, что эта ошибка найдена и исправлена ​​Apple

Fixed

Также ранее, ошибка былаподтверждено Apple Staff Эдфорд

Confirmation


Для тех, кто с iOS 13.2 и не может использоватьXcode 11.1 больше:

  1. Обновление macOS до 10.15.1 или новее
  2. Установка Xcode 11.2.1 или новее
  3. Теперь оно должно работать на обновленном устройстве.

Для тех, у кого раскадровка:

  1. Подкласс UITextView
  2. Назначить его всем UITextView объектам
  3. Нене забудьте обновить любые изменения свойств, которые могут потеряться в подклассе.

Для тех, кому не безразличен метод swizzling (Objc и динамическое поведение)

Headна @ aftab Мухаммед хан ответ для Objective-C и @ MikRo ответ для адаптированной версии Swift

Просто не делайте этого больше:

Дажеесли эти два последних обходных обходных пути не используют закрытый API Apple , они будут отклонены в AppStore, поскольку Apple не будет принимать сборки с версиями Xcode под 11.2.1!

И еще раз:

Xcode 11.2 устарела Apple 5 ноября 2019

105 голосов
/ 04 ноября 2019

Поздравление

Доступна новая версия Xcode (11.2.1), которая является лучшим способом избавиться от этой проблемы.

Обходные пути

@ Mojtaba Hosseini Решение, которое я предложил, заключалось в помощи и участии моей стороны моим коллегам-разработчикам в StackOverflow. Вы, я и все остальные разработчики здесь уже знали, что когдаApple объявит о новой версии, этой проблемы больше не будет.

Но у каждой вещи

Вышеупомянутое решение было определенно принято Apple Review, так как нет частногоApi Involved at this Этот подход очень похож на свойство создания, например

@ interface UITextView (Layout)

Или

UITextView +Layout.h

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

Простой пример iс AMFNetworking классы

- (void)setImageWithURL:(NSURL *)url {
    [self setImageWithURL:url placeholderImage:nil];
}

Надеюсь, что я закончил с утверждением

Ниже ответ был только помощь с моей стороны, чтобы дать возможность разработчику продолжать разработчика, как вы, мы изначально предлагали разработчику откатитьсяxcode, и это было плохой практикой - снова загружать 8 ГБ xcode, даже если мы все знаем, что скоро выйдет новая версия

Хотя исправлено в Xcode 11.2.1, у меня есть одно решение для Xcode 11.2, с помощью которого выможет избавиться от этой аварии:

*** Завершение работы приложения из-за необработанного исключения «NSInvalidUnarchiveOperationException», причина: «Не удалось создать экземпляр класса с именем _UITextLayoutView, поскольку не найден класс с именем _UITextLayoutView;класс должен быть определен в исходном коде или связан с библиотекой (убедитесь, что класс является частью правильной цели) '

SOLUTION

Goв настройках сборки найдите «DEAD_CODE_STRIPPING» и установите для него значение NO

DEAD_CODE_STRIPPING = NO

Затем

создайте файлы UITextViewWorkaround

UITextViewWorkaround.h

    #import <Foundation/Foundation.h>


    @interface UITextViewWorkaround : NSObject
    + (void)executeWorkaround; 
@end

UITextViewWorkaround.m

#import "UITextViewWorkaround.h"
#import  <objc/runtime.h>



    @implementation UITextViewWorkaround

    + (void)executeWorkaround {
        if (@available(iOS 13.2, *)) {
        }
        else {
            const char *className = "_UITextLayoutView";
            Class cls = objc_getClass(className);
            if (cls == nil) {
                cls = objc_allocateClassPair([UIView class], className, 0);
                objc_registerClassPair(cls);
    #if DEBUG
                printf("added %s dynamically\n", className);
    #endif
            }
        }
    }

    @end

выполнить его в делегате приложения

#import "UITextViewWorkaround.h"

        - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
            // Override point for customization after application launch.

            [UITextViewWorkaround executeWorkaround];
    return yes;
    }

Скомпилируйте код, и у вас будет запущено приложение:)

31 голосов
/ 05 ноября 2019

Проблема была исправлена ​​в Xcode 11.2.1.

РЕДАКТИРОВАТЬ: Поскольку исправление теперь выпущено, вы должны переключиться на эту версию Xcode и комментировать этот обходной путь. Как сказал Моджтаба Хоссейни в своем ответе:

... эти два последних обходных пути используют закрытый API Apple и будут отклонены из обзора Apple!

Покапока Apple не выпустила исправление, это был хороший обходной путь для продолжения разработки и тестирования.


Для Xcode 11.2, основанного на идее Афтаба Мухаммеда Хана и с помощью Джона Нимиса, которого я только что протестировалследующий код.

Нет необходимости вносить изменения в файлы раскадровки!

Отредактировал мой файл AppDelegate.swift и добавил этот класс

//******************************************************************
// MARK: - Workaround for the Xcode 11.2 bug
//******************************************************************
class UITextViewWorkaround: NSObject {

    // --------------------------------------------------------------------
    // MARK: Singleton
    // --------------------------------------------------------------------
    // make it a singleton
    static let unique = UITextViewWorkaround()

    // --------------------------------------------------------------------
    // MARK: executeWorkaround()
    // --------------------------------------------------------------------
    func executeWorkaround() {

        if #available(iOS 13.2, *) {

            NSLog("UITextViewWorkaround.unique.executeWorkaround(): we are on iOS 13.2+ no need for a workaround")

        } else {

            // name of the missing class stub
            let className = "_UITextLayoutView"

            // try to get the class
            var cls = objc_getClass(className)

            // check if class is available
            if cls == nil {

                // it's not available, so create a replacement and register it
                cls = objc_allocateClassPair(UIView.self, className, 0)
                objc_registerClassPair(cls as! AnyClass)

                #if DEBUG
                NSLog("UITextViewWorkaround.unique.executeWorkaround(): added \(className) dynamically")
               #endif
           }
        }
    }
}

и в вызов делегата для "didFinishLaunchingWithOptions "вызывает обходной путь

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

    // Override point for customization after application launch.

    // This is the workaround for Xcode 11.2
    UITextViewWorkaround.unique.executeWorkaround()
}
26 голосов
/ 05 ноября 2019

Я адаптировал ханское решение Obj-C для Swift :

import UIKit

@objc
class UITextViewWorkaround : NSObject {

    static func executeWorkaround() {
        if #available(iOS 13.2, *) {
        } else {
            let className = "_UITextLayoutView"
            let theClass = objc_getClass(className)
            if theClass == nil {
                let classPair: AnyClass? = objc_allocateClassPair(UIView.self, className, 0)
                objc_registerClassPair(classPair!)
            }
        }
    }

}

Позвоните в конце didFinishLaunchingWithOptions в AppDelegate.

Спасибо @Aftab!

15 голосов
/ 02 ноября 2019

Более быстрое исправление:

///Substitute class for _UITextLayoutView bug
class FixedTextView: UITextView {
    required init?(coder: NSCoder) {
        if #available(iOS 13.2, *) {
            super.init(coder: coder)
        }
        else {
            let rect = CGRect(origin: .zero, size: CGSize(width: 100, height: 44*3))
            super.init(frame: rect, textContainer: nil)
        }
    }
}

Добавьте этот код куда-нибудь, а затем замените все экземпляры раскадровки на FixedTextView.

Примечание: вы потеряете все атрибуты, созданные в раскадровках. Это может иметь серьезные последствия (например, настройка делегата, размер и т. Д.)

11 голосов
/ 06 ноября 2019

11.2.1 GM seed решает эту проблему

(и его можно использовать для публикации в App Store)

Перейдите на https://developer.apple.com/download/. Загрузить Xcode 11.2.1 GM seed

Примечания к выпуску подтверждают, что исправляет эту ошибку:

enter image description here

11 голосов
/ 01 ноября 2019

Загруженный Xcode 11.1 с https://developer.apple.com/download/more/ Переключение с 11.2 на 11.1 исправило сбой.

Кроме того, для меня даже с Xcode 11.2, когда я обновил свой iPhone до 13.2, это исправило сбой.

7 голосов
/ 06 ноября 2019

Вы можете скачать последнюю бета-версию XCode (11.2.1 GM) с веб-сайта Apple для разработчиков.

Здесь прямая ссылка

enter image description here

Надеюсь, эта помощь ?

7 голосов
/ 03 ноября 2019

Улучшение @garafajon ответа. Для меня это работает в большинстве случаев.

///Substitute class for _UITextLayoutView bug
class FixedTextView: UITextView {
    required init?(coder: NSCoder) {
        if #available(iOS 13.2, *) {
            super.init(coder: coder)
        }
        else {
            super.init(frame: .zero, textContainer: nil)
            self.autoresizingMask = [.flexibleWidth, .flexibleHeight]
            self.contentMode = .scaleToFill

            self.isScrollEnabled = false   // causes expanding height

            // Auto Layout
            self.translatesAutoresizingMaskIntoConstraints = false
            self.font = UIFont(name: "HelveticaNeue", size: 18)
        }
    }
}
4 голосов
/ 01 ноября 2019

В качестве «быстрого» исправления вы можете добавить UITextView непосредственно из кода, а не через IB. По крайней мере, у меня это сработало. Хотя с моей точки зрения лучше откатиться на предыдущий Xcode / дождаться нового.

...