2015-12-10 3 views
23

J'ai demandé à l'origine this question. J'avais supposé que la raison pour le temps de chargement lent de ma vue personnalisée était en raison de la superposition de plusieurs vues les unes sur les autres ou peut-être à cause de certains recursion problem. Cependant, après avoir coupé le code de plus en plus pour voir ce qui ferait une différence, il s'agissait de savoir si j'avais un UITextView présent ou non. Parce que la source apparente de mon problème est si différente de ce à quoi je m'attendais dans ma première question, j'ai décidé de commencer une nouvelle question plutôt que d'ajouter une longue mise à jour à l'ancienne.Temps de chargement lent pour UIView personnalisé avec propriété UITextView dans Swift

J'ai configuré mon projet de test avec deux contrôleurs de vue. Un bouton sur le premier contrôleur d'affichage appelle une séquence d'affichage au second contrôleur d'affichage. Le deuxième contrôleur de vue a ma vue personnalisée dessus. (En utilisant le second contrôleur de vue me laisser un sentiment de combien de temps il a fallu pour charger la vue personnalisée.)

code de la vue personnalisée:

import UIKit 

@IBDesignable class UIMongolTextView: UIView { 

    var textView = UITextView() // key line 

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

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

Comme vous pouvez le voir, la seule différence par rapport à un UIView est que j'ai ajouté une propriété UITextView. Et c'est cette vue personnalisée qui se charge très lentement. Exécution de l'outil Les allocations d'instruments que je reçois les résultats suivants (un nombre de 997):

enter image description here

Cependant, si je commente la ligne

//var textView = UITextView() 

je les charges de vues personnalisées très rapidement et ne dispose que d'un nombre de 7.

enter image description here

que se passe ici? Est-il possible d'utiliser une propriété UITextView dans une vue personnalisée et d'éviter ce temps de chargement lent?

+0

J'ai le même problème, mais j'utilise un UIPageViewController, et il y a un décalage lorsque je tente de passer à la page suivante parce que l'affichage du texte prend du temps pour init. – Jacob

+0

Note à moi-même (pour essayer plus tard): Que se passe-t-il si je le déclare comme un 'UIView', puis le transtyper dans un' UITextView' plus tard? – Suragch

Répondre

2

Essayé quelque chose de similaire où une étiquette et un champ de texte ont été ajoutés en tant que sous-vues à une sous-classe uiview.La façon dont je l'ai fait était la suivante:

@interface CustomTextField : UIView 

@property (weak, nonatomic) IBOutlet UITextField *valueField; 

@end 

Donc, nous avons eu un fichier sur lequel nous xib fait ajouter l'étiquette et le champ de texte. Dans le fichier xib, le propriétaire du fichier est "CustomTextField" et les prises sont liées à partir du fichier d'en-tête.

La méthode constructeur ressemble à ceci:

- (id)initWithValue:(NSString *)value 
{ 
    self = [super initWithFrame:CGRectZero]; 
    if (self) { 
     NSArray *nibs = [[NSBundle mainBundle] loadNibNamed:NSStringFromClass([self class]) owner:self options:nil]; 
     UIView *view = nibs[0]; 
     self.valueField.frame = view.bounds; 
     [self setFrame:view.bounds]; 
     [self addSubview:view]; 
     [self.valueField setText:value]; 
    } 

    return self; 
} 

fonctionne bien pour moi.

+0

Mettre le 'UITextView' dans un xib et ensuite charger le xib (selon [cette réponse] (http://stackoverflow.com/a/34524346/3681880)) et décocher' selectable' s'est débarrassé du long délai pour mon exemple inventé dans ma question (mais obtenir ma [vue originale] (http://stackoverflow.com/questions/34134593/slow-load-time-for-custom-uiview-in-swift) pour tourner correctement avec le xib a toujours pas travaillé). Quoi qu'il en soit, c'est une solution à ma question ici. – Suragch

1

téléchargé votre code depuis github, pourquoi ne pas simplement écrire une sous-classe de UITextView au lieu de l'UIView?

// 
// UIMongolTextView-A.swift 
// Mongol App Componants 
// 
// Created by Allen Zhang on 12/13/15. 
// Copyright © 2015 MongolSuragch. All rights reserved. 
// 

import UIKit 

class UIMongolTextView_A: UITextView { 

    override func awakeFromNib() { 
     super.awakeFromNib() 
     self.setup() 
    } 

    func setup() { 
     // 1-10: ᠨᠢᠭᠡ ᠬᠤᠶᠠᠷ ᠭᠤᠷᠪᠠ ᠳᠦᠷᠪᠡ ᠲᠠᠪᠤ ᠵᠢᠷᠭᠤᠭ᠎ᠠ ᠳᠤᠯᠤᠭ᠎ᠠ ᠨᠠᠢ᠌ᠮᠠ ᠶᠢᠰᠦ ᠠᠷᠪᠠ 

     self.transform = translateRotateFlip() 


    } 

    /* 
    // Only override drawRect: if you perform custom drawing. 
    // An empty implementation adversely affects performance during animation. 
    override func drawRect(rect: CGRect) { 
     // Drawing code 
    } 
    */ 
    func translateRotateFlip() -> CGAffineTransform { 

     var transform = CGAffineTransformIdentity 

     // translate to new center 
     transform = CGAffineTransformTranslate(transform, (self.bounds.width/2)-(self.bounds.height/2), (self.bounds.height/2)-(self.bounds.width/2)) 
     // rotate counterclockwise around center 
     transform = CGAffineTransformRotate(transform, CGFloat(-M_PI_2)) 
     // flip vertically 
     transform = CGAffineTransformScale(transform, -1, 1) 

     return transform 
    } 
} 
+0

A l'origine c'est ce que j'ai essayé de faire (puisque c'est ce que j'avais fait pour Android). Le problème est que la rotation d'un 'UITextView' gâche à la fois le texte et la mise en page automatique. Voir [cette question] (http://stackoverflow.com/questions/30907710/rotating-a-view-in-layoutsubviews) pour plus de détails. Je vous remercie de faire l'effort de télécharger le projet, cependant. – Suragch

21

Le goulot d'étranglement est la propriété de votre selectable UITextView. Il existe un problème de performances inexplicable dans la création d'un UITextView avec selectable défini sur sa valeur par défaut true. La manière la plus simple de contourner le problème consiste à ajouter votre vue de texte à l'aide du storyboard, en vous assurant de décocher la propriété selectable. Il semble n'y avoir aucun moyen documenté de créer une vue de texte non sélectionnable dans le code (en tant que paramétrer selectable sur false après la création n'évite pas le problème de performance lors de la création). Si vous avez besoin d'une vue de texte sélectionnable, commencez par créer une vue de texte non sélectionnable, puis définissez selectable sur true dans viewDidAppear.

Si vous ne pouvez pas utiliser le storyboard, vous pouvez envisager d'utiliser une classe tierce telle que TTTAttributedLabel.

Il semble qu'Apple utilise une API privée pour éviter ce problème. D'autres développeurs entreprenants ont discovered que, dans ChatKit, les vues de texte semblent être créées en utilisant une méthode privée appelée initReadonlyAndUnselectableWithFrame:textContainer:.

+2

Ce n'est pas la réponse que j'espérais, mais elle répond à la question (dans une certaine mesure) de la raison pour laquelle cela se produit. – Suragch

+0

Vous devriez pouvoir faire tout ce que vous devez faire en utilisant un contrôleur de vue personnalisé, qui possède sa propre propriété 'view', et auquel vous pouvez ajouter une propriété' textView' personnalisée connectée à UITextView dans votre storyboard. Si vous ne voulez pas que la vue soit en plein écran, utilisez un objet "Vue Conteneur" dans votre storyboard pour limiter votre contrôleur de vue personnalisé à une région particulière. Ensuite, appliquez les transformations nécessaires à la vue dans viewDidLayoutSubviews (pour l'apparence par défaut) et 'viewWillTransitionToSize: withTransitionCoordinator' (pour un changement d'orientation). – jamesk

+0

Bonne réponse. Cela s'applique également à la propriété 'enabled' de UITextField. –

1

J'ai eu un problème de performance très similaire avec un UITextView mais je pense que la cause et la solution étaient différentes pour moi.

J'ai eu un UITextView avec du texte statique sur un storyboard. Ce n'était pas modifiable ou sélectionnable. Sur un iPod Touch lent, le ViewController prendrait 5 secondes à charger.

Il s'avère que j'avais un emoji dans le texte statique. Quand j'ai enlevé l'emoji le problème est parti! J'ai utilisé des instruments pour creuser ce qui se passait et environ 25 niveaux de profondeur dans la trace, il entrait dans un tas de ... polices ... méthodes. J'utilisais la police du système sans attributs, donc la première idée qui me vint à l'esprit était le caractère emoji dans mon texte.