2015-11-02 8 views
6

Cercando di ottenere tutte le proprietà di UIView o UIViewController con la follownig:Swift Specchio riflesso non tornare immobili in UIView

func propertysNames()->[String]{ 
    var s = [String]() 
    for c in Mirror(reflecting: self).children 
    { 
     if let name = c.label{ 
      s.append(name) 
     } 
    } 
    return s 
} 

Questo funziona su UIViewController, ma UIView non sembra restituire le proprietà, qualche consiglio?

risposta

5

Non sei sicuro di ciò che si sta cercando di ottenere, ma UIView eredita NSObject. Per questo motivo, hai a disposizione gran parte del tempo di esecuzione objc. Quindi, in alternativa, si potrebbe procedere come segue:

import UIKit 

extension NSObject { 
    func propertysNames() -> [String]{ 
    var count : UInt32 = 0 
    let classToInspect = self.dynamicType 
    let properties : UnsafeMutablePointer <objc_property_t> = class_copyPropertyList(classToInspect, &count) 
    var propertyNames : [String] = [] 
    let intCount = Int(count) 
    for var i = 0; i < intCount; i++ { 
     let property : objc_property_t = properties[i] 
     let propertyName = NSString(UTF8String: property_getName(property))! 
     propertyNames.append(propertyName as String) 
    } 
    free(properties) 
    return propertyNames 
    } 
} 

print(UIView().propertysNames()) 
// prints: "["_mayRemainFocused", "_sensitivitySize", "skipsSubviewEnumeration", "viewTraversalMark", "viewDelegate", "monitorsSubtree", "backgroundColorSystemColorName", "currentScreenScale", "maskView", "_userInterfaceIdiom", "hash", "superclass", "description", "debugDescription", "gesturesEnabled", "deliversTouchesForGesturesToSuperview", "deliversButtonsForGesturesToSuperview", "_shouldReverseLayoutDirection", "leadingAnchor", "trailingAnchor", "leftAnchor", "rightAnchor", "topAnchor", "bottomAnchor", "widthAnchor", "heightAnchor", "centerXAnchor", "centerYAnchor", "firstBaselineAnchor", "lastBaselineAnchor", "_keyboardOrientation", "_touchForceObservable", "_inheritedRenderConfig", "_lightStyleRenderConfig", "_accessoryViewFrame", "unsatisfiableConstraintsLoggingSuspended", "hash", "superclass", "description", "debugDescription", "hash", "superclass", "description", "debugDescription", "userInteractionEnabled", "tag", "layer", "focused", "semanticContentAttribute", "interactionTintColor", "_layoutDebuggingIdentifier", "_countOfMotionEffectsInSubtree", "_maskView", "_ancestorDefinesTintColor", "_ancestorDefinesTintAdjustmentMode", "_presentationControllerToNotifyOnLayoutSubviews", "_rawLayoutMargins", "_inferredLayoutMargins", "_dontUpdateInferredLayoutMargins", "_tracksFocusedAncestors", "_countOfFocusedAncestorTrackingViewsInSubtree", "_mutableLayoutGuides", "_mutableLayoutArrangements", "_hiddenManagedByLayoutArrangementCount", "_pendingHiddenCount", "previewingSegueTemplateStorage", "_continuousCornerRadius", "_canBeParentTraitEnviroment", "_layoutEngine", "_boundsWidthVariable", "_boundsHeightVariable", "_minXVariable", "_minYVariable", "_internalConstraints", "_constraintsExceptingSubviewAutoresizingConstraints", "unsatisfiableConstraintsLoggingSuspended", "_shouldArchiveUIAppearanceTags", "_interactionTintColor", "_backdropMaskViewForGrayscaleTint", "_backdropMaskViewForColorTint", "_backdropMaskViewForFilters", "_backdropMaskViews", "_wantsGeometryChangeNotification", "contentSizeNotificationToken", "layoutMarginsGuide", "readableContentGuide", "hash", "superclass", "description", "debugDescription", "traitCollection", "preferredFocusedView", "center", "bounds", "transform", "collisionBoundsType", "collisionBoundingPath"]\n" 

Inoltre, faccio vedere alcune stranezze applicando il codice per UIKit oggetti. Non sei sicuro di quale sia la variabile che causa il suo fallimento. Sembra funzionare bene su tipi NSObject scritti in Swift:

import UIKit 

class Fruit { 
    var type=1 
    var name="Apple" 
    var delicious=true 
} 

var s = [String]() 
for c in Mirror(reflecting: Fruit()).children 
{ 
    if let name = c.label{ 
    s.append(name) 
    } 
} 

print(s) 
// works: "["type", "name", "delicious"]\n" 

class FruitNSObject: NSObject { 
    var type:NSNumber=1 
    var name:NSString="Apple" 
    var delicious=true 
} 

s = [String]() 
for c in Mirror(reflecting: FruitNSObject()).children 
{ 
    if let name = c.label { 
    s.append(name) 
    } 
} 

print(s) 
// works: "["type", "name", "delicious"]\n" 

s = [String]() 
for c in Mirror(reflecting: UIView()).children 
{ 
    if let name = c.label { 
    s.append(name) 
    } 
} 

print(s) 
// doesn't work: "[]\n" 

s = [String]() 
for c in Mirror(reflecting: UIViewController()).children 
{ 
    if let name = c.label { 
    s.append(name) 
    } 
} 

print(s) 
// doesn't work: "[]\n" 

Quindi, o si tratta di un bug o c'è qualche limitazione nel Swift < -> objC nella versione corrente di Swift. Forse ha a che fare con ciò che @ user3441734 ha sottolineato nella sua risposta.

BTW, tutto il codice è stato eseguito sulla versione più recente di Xcode (ovvero 7.1.1) in un parco giochi.

+0

Grazie per l'ottima risposta! Il problema con questo è come se tu triste che funzioni solo su ereditari di NSObjects, e stavo cercando qualcosa di generico che funzionasse su qualsiasi stregone. Inoltre (e non ne sono sicuro al 100%) questo modo sembra un po '"pesante" rispetto al modo rapido. Accetto la tua risposta perché è la migliore. Grazie ancora. – MCMatan

4
import UIKit 

let viewController = UIViewController() 
let view = UIView() 
class MyViewController: UIViewController { 
    let i = 1 
    let myView = MyView() 
} 
class MyView : UIView { 
    let label = UILabel() 
    let i = 1 
} 

Mirror(reflecting: MyViewController()).children.count // 2 
Mirror(reflecting: MyView()).children.count    // 0 

Hai ragione! Basta compilare la segnalazione di bug ...

o è sabotaggio, perché ho trovato questo

extension UIView : _Reflectable { 
} 
+0

È sicuramente "sabotaggio", sono d'accordo. –