Set defaultTextAttributes using User Defined Runtime Attributes? - ios

Say you are setting
field
.defaultTextAttributes
.updateValue(20.0, forKey: NSAttributedStringKey.kern.rawValue)
(BTW you do that to space out text, like t h i s.)
in fact, is there a way to set that using User Defined Runtime Attributes,
right on the storyboard in Xcode?

No, there is not. User Defined Runtime Attributes works only where key-value coding would work, with a limited range of value types. A moment's thought will reveal that your code can't be expressed in that way.
You could, however, subclass to define a custom property and set it to 20 in User Defined Runtime Attributes, and respond with a setter observer to run the code you've shown. That way, different fields can have different kern values depending on a setting in the storyboard.
(If you're going to do that, you might as well make this property IBInspectable; IBInspectable effectively is User Defined Runtime Attributes, with a different interface.)

Related

Can we access the objects in Storyboard by ObjectID

I have a bunch of static objects (UILabel, buttons, views) in multiple Scenes. They are not connected to any IBOutlet. But I'd like to access them at appdelegate (or first VC), and change their properties before it is loaded.
Anyway to do this?
EDIT: Adding my intention:
I actually wanted to make a custom "multi-language" app. I want to be able to change language from within the app. I can get a list of all the objects by applying built in localization of storyboard (Main.strings is autogenerated). Then I disable localization again. Then from this autogenerated file, I want to be able to connect it to a json data based on language that I select.
Of course you can. For example, you can use tags of UIView. Just set tags in Storyboard. It's easy but not so good. Another way to do this is using Accessibilities. Enable and set for it in Storyboard.
And then you can access it by accessibilityIdentifier property.
I will post my choice of "solution". So what I did was make use of accessibilityIdentifier to set the "key" for the multilanguage phrase translation purpose.
And I make use of the UIView+Recursion class (you can find this simple class somewhere in SO), and basically iterate all the objects in a particular Scene and if the text matches, set the key in accessibilityIdentifier property (either in viewDidload or viewWillAppear or viewDidlayoutSubviews).
This way you can have language changes "on-the-fly" within the app, without restarting.

Storyboard user defined runtime attributes with enum

Does anyone know if it's possible to set user defined runtime attributes in Xcode's storyboard with an enum's name (not value).
I tried String and Number types, neither of them works.
Setting it programatically is an option, I know.
In other words, for example I want to able to set the textAlignment attribute of UILabel to NSTextAlignmentCenter without knowing NSTextAlignmentCenter's real numeric value (1).
It is possible only if Xcode provides you with interface for that. For example, there're buttons to switch between NSTextAlignment for UILabel.
And, no, there's no way to set any enum values - as long as Xcode doesn't provide functionality like that for editing property lists.
It will become possible, when property lists will support enums

XCUIElement - Obtain Image value

I have an variable that's of type .Image and class XCUIElement. Something like this:
var image = app.descendantsMatchingType(.Image).elementAtIndex(0)
Is there a way I can extract the actual image so I can compare it to another image?
I've tried caling the value method, but it returns a string. Casting it to a UIImage always fails.
I have had a conversation about this with the Apple Developer Tools evangelist recently. There is currently no way of accessing the actual image from an image view, button, etc. Similarly, there is no way to access other properties of views that might be of interest, like "isHidden" or "attributedText", etc. I was told that the engineers on the UI Testing team are interested in the use cases that people are wanting access to these properties for, so it would be very helpful -- both for them and for the other people who want this feature -- if you would file a bug report / feature request asking for it at https://bugreport.apple.com
As a tip regarding the "value" property on an XCUIElement, at least for now this appears to map to the "accessibilityValue" property of whatever view the XCUIElement is referencing. So if you set that accessibilityValue of a view you are interested in to contain some information you are interested in verifying, then this can possibly help in testing. Two things to be aware of though:
1) Even though the "value" property of an XCUIElement is of type "id", the type of the accessibilityValue property is "NSString". I don't know what would happen if you try to force some non-string value (like an image) into accessibilityValue and then try to retrieve it from the "value" property of XCUIElement, but I suspect it wouldn't work well. Partially because:
2) The accessibilityValue property of a view is actually used by Apple's VoiceOver feature for the vision impaired. When the value is set, it will be read out loud when the user taps on that element (which is why it's supposed to be a string).
I also covered the issue with not being able to access properties of view via XCUIElement in more detail here: http://www.danielhall.io/exploring-the-new-ui-testing-features-of-xcode-7
I know it may be not exactly what you're looking for, but I managed to write a test that checks if the visual representation of a UIImage on the screen has changed.
I'm using a screenshot() method of XCUIElement which returns an instance of XCUIScreenshot:
let myImage = XCUIApplication().images["myAccessibilityIdentifier"]
let screenshotBefore = myImage.screenshot()
//...
//do some actions that change the image being displayed
//...
let screenshotAfter = myImage.screenshot()
//Validating that the image changed as intended
XCTAssertNotEqual(screenshotBefore.pngRepresentation, screenshotAfter.pngRepresentation)
The screenshots will be the size of the image as rendered on the screen which may be different to the original image of course.
It's important to compare the PNG representations using the pngRepresentation property, but not the XCUIScreenshot objects because the two objects will always be different internally.
This technique can't test that the image displayed on the screen is exactly what is needed but at least can detect changes in the image.

iOS Interface Builder: How to make templates

I've recently started developing an iOS app, which I've never done before, so it's been going a bit slow, but I'm learning, so that's understandable.
I want to make a custom interface, so I've been making subclasses of the default view classes (like UIButton) so that I can define custom drawing. I've been told this is the best way to define custom interface elements that can be reusable. It definitely seems to be working that way. However, I haven't been able to make elements completely reusable by just using a subclass.
For example, in order to prevent a button's text from changing color when it is clicked, I have to manually go into the interface builder and set the button type to "Custom." After that, code that I enter into the subclass's constructor to change attributes seems to work. But I have to do this for every button I add, and in code the "buttonType" attribute is read only. Is there a way for me to define (just once) certain attributes for every instance of my button subclass that I add to the interface?
My goal is to be able to have a button subclass or template that defines all attribute values that I want my buttons to have, and every instance that I add automatically reflects those properties without me having to change anything. More so, I want to be able to modify that subclass/template and have those changes reflected in every existing instance. I have to imagine that this is possible in iOS. There is simply no way to build sophisticated interfaces without this capability.
Define a custom Button class (inherited from UIButton) in your project and in the init set the properties which you wanted to be set across.
In the interface builder go to the the class inspector and enter the button to be of the previously declared button.
buttonType needs to be set for all the button as this is defined at initialization time and exposed as read only property. If you want absolute reusability for your case, create a view, with an embedded button in code. when you create a button, create using the static method buttonWithType.
Wherever you need, drag and drop a UIView and set the view type to be the custom view.

Do the User defined runtime Attributes works only on custom classes?

I am using storyboard and there are 5 view controllers in it. Each ViewController has only 1 UIButton. I want to set button's background color using User Defined Runtime Attributes. So I defined a keyPath "bgColor" and set corresponding hex color code "#ffaa11". But application crashes before loading the view. It gives exception:
[<UIRoundedRectButton 0x713fdb0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key bgColor.
I dont want to create custom class. Please suggest how can I paas value through IB. Please check the snapshot.
NOTE: In real my requirement is to get a string value which has been entered in Interface Builder. Very similar to User Defined Runtime attributes. I have taken example of bg color.
Why are you using User Defined Runtime Attributes anyway? Switch to the Attributes Inspector and choose button's background from there.
First thing first.
Obviously it crashes. Because there is no bgColor property on the button. Hence when you are trying to set it as button.bgColor = #yourValue. It is crashing.
If you are using ios7 try setting the button's tintColor property. and for styles go through tintAdjustmentMode values.
And after these . If it still doesn't solve your issue. We will discuss something else :) :)
cheers. Have fun.

Resources