Can't make User Defined Runtime Attributes work - ios

I would really like to be able to use the "User Defined Runtime Attributes " from xcode Storyboard to build a nice pop up through a container view.
Unfortunately, I can't make it works and can't figure out why !
I found many topics (eg: Is it possible to set UIView border properties from interface builder?) which deal about it but this doesn't work for me... !
Here is the attribute inspector of the containerView embed UIView (I also tried to implement into containerView UIView too with no success).
I added an extension to transform UIColor to CGColor as expected :
extension CALayer {
var borderUIColor: UIColor {
set {
self.borderColor = newValue.CGColor
}
get {
return UIColor(CGColor: self.borderColor!)
}
}
}
Does someone could think about something missing ?
Thank you very much in advance ;)

Instead of layer.borderColor, use layer.borderUIColor in your user defined runtime attributes. Just double click the key name and add UI.

Related

Set all back button titles in UINavigationController

I'm trying to be clever about setting all title properties of the the "Back" buttons in a UINavigationController so that I don't have to do self.navigationController.navigationBar.backButtonItem.title = "Back" everywhere or subclass a UINavigationController and set it everywhere, so I've created this extension:
extension UINavigationItem {
open var backBarButtonItem: UIBarButtonItem? {
get {
return self.backBarButtonItem
}
set {
newValue?.title = "Back"
backBarButtonItem = newValue?
}
}
}
But it says 'backBarButtonItem' used within its own type.
Has anybody done this before or can think of a way to make it work?
You are getting this error because you cannot create a variable with the name which is similar to those variables which are defined in the SDK.
You can't override the existing functionality
Like in your case you are naming it as backBarButtonTitle which is defined as open var backBarButtonItem: UIBarButtonItem? in UINavigationBar class of UIKit
As it is mentioned in doc of Apple
Extensions can add new functionality to a type, but they cannot
override existing functionality.
Please follow this Screen shot Image then run your project . I think you can solved your problem easily :)

Storyboard Designtime Layout Attributes

This is a feature a like a lot when defining layouts for Android and that allows to define attributes just to design.
http://tools.android.com/tips/layout-designtime-attributes
But I didn't find any equivalent way to do the same when using storyboard to make iOS Apps.
At the moment I a cleaning all the design values on a viewDidLoad of my ViewController. Is there a way to define layout attributes as design placeholders and avoid making this setupClean step in all my view controllers?
When You want Instant Reflect of attributes/properties of particular componet in storyboard then you can achieve using #IBDesignable.
To achieve this You have to subcalss of that type of which you want to be reflected on storyboard.
Steps
Make a subclass of the type you want be reflected on storyboard, as in example here i am going to subclass UILabel as DGlabel
Make that calss as #IBDesignable, see the example
Assign that subclassed to the component from Identity Inspector, see screen shot
In subclassed calss (here in example DGLabel) declare variables of properties/attributes which you want be reflected on design as #IBInspectable, see example here i have decalred borderColor as #IBInspectable, this means this property will be listed on property inspector of Xcode
now you can change the value of that property from story board as screen shot below
import UIKit
#IBDesignable
class DGLabel: UILabel {
#IBInspectable var borderColor:UIColor = UIColor.red {
didSet {
reflectChange()
}
}
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
func reflectChange() {
self.layer.borderWidth = 1
self.layer.borderColor = borderColor.cgColor
}
}
Hope this will allow you to understand the process.
Yes you can do that by providing runtime attribute in "User defined runtime attributes" section under storyboard's Identity inspector. See below screenshot for setting UILabel's "text" keypath's runtime value as blank.
I think you can achieve something similar by using IBDesignable for your views. Then you may use prepareForInterfaceBuilder() and TARGET_INTERFACE_BUILDER to generate mock data for display in Interface Builder.
Did you mean this?
You can change Label Text value in storyboard from the "Attribute Inspector".

Swift2 override of highlighted/selected doesn't work

I'm creating a custom UIButton class and i'm trying to override the highlighted/selected methods but they aren't called. After a bit of searching i found that this code should be working:
override var highlighted: Bool {
didSet {
if highlighted {
self.backgroundColor = UIColor.whiteColor()
} else {
self.backgroundColor = UIColor.blackColor()
}
}
}
I did the same for selected. I also tried using willSet but no luck. I'm using swift2.0. Could that make the difference? Anyone knows why it isn't called?
You're going about this all wrong. No need to subclass. Just call setBackgroundImage:forState: with a black image for one state and a white image for the other.
Issue fixed. Due to the fact that i'm wokrking on an SDK shared library, I had to define the Module of my view controller and the Module of my button class. Once I did those, everything was working fluently.

Failed to set (cornerRadius) user defined inspected property on (UIView)

Details
I was watching the video of Session 411 on WWDC 2014 referring to "What's new on Interface Builder", and I was trying out how to create Frameworks in order to make #IBDesignable classes to preview my changes in Storyboard without having to run the application.
#IBInspectable properties are showing correctly when I add my class to a specific view and are rendering the view correctly with the below code:
Code
#IBDesignable
class MyView: UIView {
#IBInspectable var borderColor: UIColor = UIColor.clearColor() {
didSet {
layer.borderColor = borderColor.CGColor
}
}
#IBInspectable var borderWidth: CGFloat = 0 {
didSet {
layer.borderWidth = borderWidth
}
}
#IBInspectable var cornerRadius: CGFloat = 0 {
didSet {
layer.cornerRadius = cornerRadius
}
}
#IBInspectable var masksToBounds: Bool = false {
didSet {
layer.masksToBounds = masksToBounds
}
}
}
Log
I noticed that these attributes were being added on User Defined Runtime Attributes (Under Identity Inspector). Now what I am expecting from this is when I run the code to keep these changed I made with a specific view.
I run the application and the view doesn't load the User Defined Runtime Attributes, and gives this error on output (not crash):
Unknown class MyClass in Interface Builder file
Failed to set (cornerRadius) user defined inspected property on (UIView)
Question
What is causing the application not to load User Defined Runtime Attributes that I added under Identity Inspector?
The code is correct.
When you declare a # IBDesignable all the #IBInspectable properties are exposed to the Interface Builder as User Defined Runtime Attributes.
The problem -
Unknown class MyClass in Interface Builder file
Is means that Interface Builder couldn't find some class. You have set wrong class that doesn't exist in your app.
Your customView class is MyView but in the Interface Builder you have MyClass
Solution to fix-
Set correct class in interface Builder, in your case MyView
Check Designable status. It should be Up to date , if it's not than something is wrong.
Also If you decided to remove customer Designable you should
Remove custom class
Remove User Defined Runtime Attributes
Based on the question title, a few people may come here with a slightly different problem (like I did). If you
added an #IBInspectible
and then deleted it in code
Then you may also get an error similar to
Failed to set (xxx) user defined inspected property on [Your Custom
View] ...: this class is not key value coding-compliant for the key
[xxx].
The solution is to delete the the old property.
Open the Identity inspector for your class, select the property name under User Defined Runtime Attributes, and press the minus button (-).
Again, this is not the answer to the OP's question, but it might be the answer to someone else's problem who comes here.
in Indentity inspector add in user Defined runtime attributes
layer.cornerRadius - type string
after go to Attibutes inspector and select "Clip Subviews"

Live Render IBOutlet Connected Subviews Via IBInspectable Properties

I'm using storyboards for the first time in iOS 8 and so far have been loving the live rendering aspect of things on the storyboard. However, I seem to have hit a snag in getting my views to render properly on the storyboard.
I have a container UIView that contains a connection to a UILabel on the storyboard, I am attempting to set the label's text based on an IBInspectable attribute on the label's parent container view.
#IBDesignable class ContainerView : UIView {
#IBOutlet weak var : titleLabel : UILabel!
#IBInspectable var title : String = "" {
didSet {
titleLabel?.text = title
}
}
/* Init functions */
prepareForInterfaceBuilder() {
self.titleLabel?.text = title
}
}
If I set the attribute in the storyboard it renders as expected while the program is executing but fails to render in the storyboard as I would expect. I've checked my connections and everything appears to be hooked up properly.
My question is: Is it possible to affect the contents of an IBOutlet connected view via IBInspectable attributes and have them live render on the storyboard, and if so, what am I missing or doing wrong?
Unfortunately you can't see IBOutlet objects in interface builder for your custom views which are marked as IBDesignable. If you want to see your outlets in interface builder, you have to use regular variables instead IBOutlet and you have to create your objects programmatically.
Also please note that, if you need to change something from interface builder for your objects, you have to define your properties as IBInspectable. Currently following variables types are valid for IBInspectable:
Bool, CGFloat, CGPoint, CGRect, CGSize, NSInteger, NSString, UIColor, UIImage
I hope this answer is adequately clear for you.
Edit: I found following article which is describing a way how to do what you need:
http://justabeech.com/2014/07/27/xcode-6-live-rendering-from-nib/
2nd Edit: I tried the article and it works. Now I can see my outlets on interface builder

Resources