2015-11-02 8 views
6

Starając się uzyskać wszystkie właściwości UIView lub UIViewController z follownig:Swift Odbicie lustrzane nie wraca właściwości na UIView

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

Działa to na UIViewController, ale UIView nie wydaje się, aby powrócić właściwości, jakieś rady?

Odpowiedz

5

nie wiesz, co staramy się osiągnąć, ale UIView dziedziczy NSObject. Z tego powodu masz do dyspozycji dużą część środowiska wykonawczego objc. Więc jako alternatywę, można wykonać następujące czynności:

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" 

Również widzę niektóre niesamowitość stosowania kodu do UIKit obiektów. Nie jestem pewien, która zmienna powoduje niepowodzenie. Wydaje się działać prawidłowo w sprawie rodzajów NSObject pisanych w 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" 

Więc albo jest to błąd lub istnieje pewne ograniczenie w Swift < -> ObjC w aktualnej wersji Swift. Być może ma to związek z tym, co @ użytkownik3441734 wskazał w swojej odpowiedzi.

BTW, cały kod został uruchomiony na najnowszej wersji Xcode (to 7.1.1) na placu zabaw.

+0

Dzięki za wspaniałą odpowiedź! Problem polega na tym, że jesteś smutny, że działa tylko w przypadku dziedzin NSObjects, a ja szukałem czegoś, co zwykła czarownica będzie działała na dowolnym. Plus (i nie jestem tego w 100% pewny) w ten sposób wydaje się nieco "ciężki" w porównaniu do sposobu Swift .. Przyjmuję twoją odpowiedź, ponieważ jest najlepsza. Dzięki jeszcze raz. – 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 

Masz rację! Wystarczy wypełnić raport o błędzie ...

czy to sabotaż, ponieważ uważam, że ten

extension UIView : _Reflectable { 
} 
+0

To z pewnością "sabotaż", zgadzam się. –

Powiązane problemy