@IBDesignable error: IB Designables: Nie udało się zaktualizować stanu automatycznego układu: Awaria narzędzia Interface Builder Cocoa Touch Tool

157

Mam bardzo prostą podklasę UITextView, która dodaje funkcję „Placeholder”, którą można znaleźć natywną dla obiektu Text Field. Oto mój kod dla podklasy:

import UIKit
import Foundation

@IBDesignable class PlaceholderTextView: UITextView, UITextViewDelegate
{
    @IBInspectable var placeholder: String = "" {
        didSet {
            setPlaceholderText()
        }
    }
    private let placeholderColor: UIColor = UIColor.lightGrayColor()        
    private var textColorCache: UIColor!
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        self.delegate = self
    }
    
    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.delegate = self
    }
    
    func textViewDidBeginEditing(textView: UITextView) {
        if textView.text == placeholder {
            textView.text = ""
            textView.textColor = textColorCache
        }
    }
    
    func textViewDidEndEditing(textView: UITextView) {
        if textView.text == "" && placeholder != "" {
            setPlaceholderText()
        }
    }
    
    func setPlaceholderText() {
        if placeholder != "" {
            if textColorCache == nil { textColorCache = self.textColor }
            self.textColor = placeholderColor
            self.text = placeholder
        }
    }
}

Po zmianie klasy UITextViewobiektu w Inspektorze tożsamości na PlaceholderTextView, mogę dobrze ustawić Placeholderwłaściwość w Inspektorze atrybutów. Kod działa świetnie podczas uruchamiania aplikacji, ale nie wyświetla tekstu zastępczego w konstruktorze interfejsu. Otrzymuję również następujące błędy nieblokujące (zakładam, że dlatego nie renderuje się w czasie projektowania):

błąd: IB Designables: Nie udało się zaktualizować stanu automatycznego układu: Awaria narzędzia Interface Builder Cocoa Touch Tool

błąd: IB Designables: nie udało się wyrenderować instancji PlaceholderTextView: Renderowanie widoku trwało dłużej niż 200 ms. Twój kod rysowania może mieć niską wydajność.

Nie jestem w stanie dowiedzieć się, co powoduje te błędy. Drugi błąd nie ma żadnego sensu, ponieważ nawet nie nadpisuję funkcji drawRect (). Jakieś pomysły?

Albert Bori
źródło
1
Otrzymałem ten błąd. Obiekt działał dobrze w projekcie testowym, ale nie w moim głównym projekcie (w tabeli). Według developer.apple.com/library/mac/recipes /... wybrałem opcję Wybierz edytor> Debuguj wybrane widoki. Otrzymałem wtedy komunikat „Nie można debugować widoków” „Upewnij się, że platforma ma poprawne ustawienia kompilacji do kompilacji dla systemu iOS”. W Google nic nie pojawiło się w związku z tym błędem.
Matt

Odpowiedzi:

238

Istnieją raporty o awariach generowane w przypadku awarii narzędzia Interface Builder Cocoa Touch Tool. Tezy są zlokalizowane ~/Library/Logs/DiagnosticReportsi nazwane IBDesignablesAgentCocoaTouch_*.crash. W moim przypadku zawierały one użyteczny ślad stosu, który zidentyfikował problem w moim kodzie.

Petter
źródło
1
Dzięki! To było bardzo pomocne! Gdzie znalazłeś informacje o raportach o awariach? :)
Ben-G
57
W moim przypadku odkryłem, że initFrame(frame: CGRect)należy to zdefiniować. Zrób to, jeśli udostępniasz własne initmetody.
Travis
To było najlepsze rozwiązanie. Nie zaimplementowałem initWithFrame w jednym z widoków.
HotFudgeSunday
3
Skorzystałem z raportów diagnostycznych i tak jak wspomniał @Travis, musiałem init(frame: CGRect)jawnie nadpisać, ponieważ miałem niestandardową inimetodę. Możesz przejrzeć raport o awarii use of unimplemented initializer 'init(frame:)'bezpośrednio pod Application Specific Informationraportem. Dzięki chłopaki! Podwójne zwycięstwo w tej odpowiedzi!
Chris
4
Jak zwykle ten plik dziennika jest również dostępny w aplikacji Konsola macOS w grupie Raporty diagnostyczne użytkownika .
Paulo Mattos,
51

Kilka razy miałem ten sam problem. Za każdym razem zaczęło się to, gdy ładowałem stalówkę IBDesignable na scenorys, gdy stalówka nie była w stanie zmieścić się w widoku (tj. Miałem przycisk poza UIView, ale nadal w stalówce). Kiedy naprawiłem, że Xcode nadal dawał mi błędy, uruchomiłem ponownie Xcode, aż losowo przestał dawać mi błąd.

Mam nadzieję, że to pomoże.

AKTUALIZACJA: Właśnie zabiłem wszystkie procesy o nazwie „Interface Builder Cocoa Touch Tool”, zrestartowałem Xcode i błąd zniknął. Nie wiem, czy to zawsze zadziała, czy nie.

Dustin Williams
źródło
2
Chociaż nadal nie rozumiem dlaczego, jeśli nie nadpiszesz żadnej z initmetod, kod wysłany jako część pytania nie pokazuje już IB Designablesbłędów, a symbol zastępczy jest prawidłowo renderowany w programie Interface Builder.
Willington Vega,
2
Być może jest to błąd i musimy tylko poczekać, aż zostanie naprawiony. Być może w Xcode 6.3.
Youssef Moawad
3
XCode 7.1.1 i nadal obecny. Ponowne uruchomienie XCode nie rozwiązało problemu. Musiałem ręcznie zabić wszystkie procesy o nazwie Interface Builder Cocoa Touch Tool, a następnie XCode zawiesił się, zrestartowałem go i zaczął działać.
Cristian Pena
1
Ważna uwaga: Rzeczywiście, NAJPIERW zabij procesy konstruktora interfejsu, a następnie zatrzymaj XCode - jeśli zrobisz to w drugą stronę, problem nadal występuje ...
TheEye
2
XCode 8.1 ten błąd nadal występuje. Pierwotnie spowodowane brakiem nadpisania init, ale utrzymywało się po dodaniu init. Musiałem zabić procesy Interface Builder zgodnie z opisem, a następnie zrestartuj xcode, jak mówi @TheEye
John Fowler
39

W moim przypadku robiłem następny w metodach initWithFrame / initWithCoder, aby utworzyć widok:

className = NSStringFromClass([self class]);
self.view = [[[NSBundle mainBundle] loadNibNamed:className owner:self options:nil] firstObject];

Wygląda na to, że nie powinienem używać pakietu głównego , ale pakiet klasy. Więc zamieniłem ten kod na następujący i zadziałał:

bundle = [NSBundle bundleForClass:[self class]];
className = NSStringFromClass([self class]);
self.view = [[bundle loadNibNamed:className owner:self options:nil] firstObject];

Pomyślałem, że może to komuś pomoże.

jmoukel
źródło
1
To też rozwiązało mój problem! Dzięki @jmoukel!
edopelawi
Ten rozwiązał mój problem. Człowiek!!! nie zauważyłem linii „bundleForClass”, mimo że kilka razy sprawdzałem to rozwiązanie. :(
elk_cloner,
let bundle = Bundle(for: ValidatingTextField.self)w Swift
por
14

Możesz wybrać widok niestandardowy w programie Interface Builder, a następnie użyć Editor , Debug Selected Views. Uruchomi tak zwaną IBDesignableAgentCocoaTouchsesję debugowania, gdy wszystkie punkty przerwania (w tym punkty przerwania wyjątków) będą działać i możesz dokładnie zidentyfikować miejsce awarii widoku.

Fiodor Volchyok
źródło
Idealny! To też znalazło mój problem - niewłaściwa czcionka. To wyjaśnia, dlaczego tylko jeden z sześciu bardzo podobnych IBDesignables zawiódł.
zkarj
13

Dla Xcode 8 - Swift

Dodawanie opcjonalnej wartości jako wartości domyślnej @IBInspectablepowodującej problem.

To nie zadziała:

@IBInspectable var repeatImage: UIImage = UIImage(named:"myImage")!{
      didSet {
       // configureView
      }
}

To powinno działać:

@IBInspectable var repeatImage: UIImage = RepeatImageView.getDefaultImage() {
    didSet {
        // configureView()
    }
}

class func getDefaultImage() -> UIImage {
    if let defaultImage = UIImage(named: "myImage") {
        return defaultImage
    } else {
        return UIImage()
    }
}
Mohammad Zaid Pathan
źródło
@DungTran Z jakim problemem masz do czynienia?
Mohammad Zaid Pathan
1
Opcjonalna obsługa zapobiega zderzeniu. Ale czy wiesz, co powoduje, że UIImage (o nazwie :) konsekwentnie zwraca zero?
ScottyBlades
Skomentowanie tego kodu naprawiło problem dla mnie `@objc @available (*, przestarzałe, zmieniona nazwa:" backgroundColor ") @IBInspectable public var signatureBackgroundColor: UIColor = .white {didSet {backgroundColor = signatureBackgroundColor}}`
PhoneyDeveloper
9

Doświadczyłem podobnych problemów z Interface Builder podczas renderowania projektów.

Korzystając z techniki zaproponowanej w tej odpowiedzi , udało mi się wyśledzić problem z użyciem literałów obrazu.

Błąd renderowania

self.backgroundImage.image =  #imageLiteral(resourceName: "rectangleCenter")

Brak awarii renderowania

self.backgroundImage.image =  UIImage(named: "rectangleCenter")
Nick Cross
źródło
Jesteś bohaterem.
nathangitter
Masz jakiś pomysł, dlaczego literały obrazu są niekompatybilne z IB? Miałem ten sam problem.
SwiftsNamesake
6

W rzeczywistości, jeśli masz jakieś stare atrybuty zdefiniowane przez użytkownika (które nie są ważne dla bieżącego widoku) w dowolnym widoku w swojej serii ujęć, może to spowodować awarię agenta.

Poza tym czasami dzieje się tak z powodu paskudnego błędu Xcode. Aby to sprawdzić, gdy jesteś w scenorysie, odznacz Edytor> Automatycznie odświeżaj widoki, a następnie przejdź do innego pliku, wyczyść i uruchom ponownie projekt. Po ponownym wejściu do scenorysu możesz kliknąć Edytor> Odśwież widoki i ponownie sprawdzić automatyczny. Ten też kiedyś rozwiązał mój problem.

Jeśli oba nie zadziałały, prawdopodobnie zrobiłeś coś złego w swoim widoku IBDesignable, więc wybierz swoje uszkodzone widoki w scenorysie i debuguj, klikając Edytor> Debuguj widoki

Yusuf Kamil AK
źródło
Jesteś darem od Boga.
andrewcar
4

Tak nie jest w przypadku tego pytania, ale może pomogę komuś innemu.

Miałem podobny problem, gdy w mojej klasie @IBDesignable nie zaimplementowałem obu:

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)

    // custom setup
}

override init(frame: CGRect) {
    super.init(frame: frame)

    // custom setup
}
tzaloga
źródło
Zawsze należy implementować obie metody init. Init with frame jest używany, gdy inicjujesz widok z kodu, a init z aDecoder jest używany z InterfaceBuilder.
Skodik.o
4

Miałem ten sam problem i rozwiązałem go, dodając 'use_frameworks!' do pliku Podfile mojego projektu.

Mam nadzieję, że ci to pomoże.

Jimmy Ng
źródło
To zadziałało, gdy miałem ten problem z JVFloatLabeledTextField
saswanb
To właśnie zadziałało w moim przypadku, przyjmując starszy projekt Obj-C, który był dość nieaktualny. Po tym IB zapala się jak choinka! Dziękuję Ci.
zwrócił ..
3

W moim przypadku było to w jakiś sposób związane z frameworkiem kartaginy, którego używałem. Musiałem dodać $ (PROJECT_DIR) / Carthage / Build / iOS do ustawienia kompilacji Runpath Search Paths

AkademiksQc
źródło
Po wypróbowaniu wszystkich innych opublikowanych rozwiązań ... to była jedyna poprawka, która zadziałała! Dzięki!
Joel
3

W moim przypadku był to problem z OneSignal. Najwyraźniej mają błąd w wersji 2.2.0 i nowszych. Przełączono na 2.1.6 i znowu wszystko jest świetnie!

Sprawdź to .

Paul Razvan Berg
źródło
1

Kiedy to debugowałem, odkryłem, że istnieje kilka klas, które modyfikują interfejs użytkownika. Zwykle marquelabel, która jest podklasą UILabel lub dowolnej innej klasy podklasy UIView i rysowania interfejsu użytkownika w czasie wykonywania i koliduje z silnikiem Autolayout. Spróbuj podać stałą szerokość lub wysokość dla tych niestandardowych widoków. Jeśli to nie rozwiąże problemu, wypróbuj następujące rozwiązania: -

Rozwiązanie 1: - Usuń komentarz #use_frameworks z pliku pod.

Rozwiązanie 2: - Spróbuj usunąć dane pochodne. 1. Zamknij okno Edytora swojego Xcode i wyjdź z symulatora -> 2. Przejdź do Xcode Preferences -> Locations -> 3. Kliknij małą szarą strzałkę pokazującą wyprowadzoną ścieżkę danych -> 4. Wybierz swój projekt -> 5. Usuń wszystkie foldery wewnątrz -> 6. Zamknij Xcode i otwórz ponownie

Ashish Pisey
źródło
1

Dodaj go na dole swojego pliku Podfile i uruchom pod install

# Workaround for Cocoapods issue #7606

    post_install do |installer|
        installer.pods_project.build_configurations.each do |config|
            config.build_settings.delete('CODE_SIGNING_ALLOWED')
            config.build_settings.delete('CODE_SIGNING_REQUIRED')
        end
    end
Tissa
źródło
1

Dodaj ten skrypt na końcu mojego Podfilei wykonałem pod installponownie.

post_install do |installer|
    installer.pods_project.build_configurations.each do |config|
        config.build_settings.delete('CODE_SIGNING_ALLOWED')
        config.build_settings.delete('CODE_SIGNING_REQUIRED')
    end
end
Haroldo Gondim
źródło
1

Głównym problemem jest to, że podczas tworzenia @ IBDesignable upewnij się, że plik cocoapod nie jest uwzględniony w UITestach, bo inaczej spowoduje to awarię.

Modesto Cabrera
źródło
0

Uważam, że powodem jest to, że twój xib nie jest tego samego rozmiaru co projekt w scenorysie. Upewnij się, że xib ma taką samą wysokość i szerokość.

user6476366
źródło
0

Brakowało mi tej linii kodu platform :ios, '7.0' i problem został rozwiązany. Tylko ten wiersz w pliku poda i zaktualizuj problem z modułem zostanie rozwiązany.

Shahzaib Maqbool
źródło
0

Dla mnie był to brakujący certyfikat do podpisywania, ponieważ nigdy nie uruchamiałem aplikacji, więc Xcode nie utworzył jeszcze certyfikatu. Po uruchomieniu aplikacji IBDesignablerenderowanie działało dobrze.

Florian Pfisterer
źródło
0

To tak, jakbyś miał kod od innego programisty i otrzymujesz ten błąd. Po prostu biegnij

pod install

To zadziałało dla mnie. Mam nadzieję, że to pomoże.

Dhruv Khatri
źródło
0

Upewnij się, że nie inicjujesz bezpośrednio UIImageaniUIFont używasz zasobów lub czcionek dodanych w projekcie.

Zawsze tworzę private func setUp()w moich @IBDesignablewłasnych UIklasach. która jest wywoływana z init(frame: CGRect), init?(coder aDecoder: NSCoder). Więc w końcu zaktualizowałem setup()w następujący sposób.

private func setUp() {

     //... Doing initial configurations

     // iconImageView.image = UIImage(named: "IconImageName")! // Causing the Crash, use if let OR guard let instead
     if let icon = UIImage(named: "IconImageName") {
          iconImageView.image = icon
          iconImageView.frame.size = icon.size
     }

     // nameLabel.font =  UIFont(name: "Calibri-Light", size: 15.0) // Causing the Crash, use if let OR guard let instead
     if let font = UIFont(name: "Calibri-Light", size: size) {
          nameLabel.font =  font
     } else {
          nameLabel.font = UIFont.systemFont(ofSize: size) 
     }

     // Doing other stuffs
}
Sauvik Dolui
źródło
-1

Po prostu pozwól mu zbudować i uruchomić na symulatorze, jeśli masz błąd w innym miejscu projektu, po prostu zakomentuj go i uruchom najpierw projektowalny, aby zaktualizować projektowalne i odkomentować inne kody. Mi to pasuje.

Daniel
źródło