I have problem with xcframwork.when i create xcframwork my properties not display in my main project storyboard. When i create framework it display all properties in my storyboard.
I have created Following code
#objc
public extension UIView {
// Note : Corner radius and shadow not work both side by side so you need to outlet and set layer radius
// other wise you can set layer.cornerradius in user defines
//MARK: Border COLOR
#IBInspectable
var borderColor: UIColor? {
get {
return self.borderColor
}
set {
self.layer.borderColor = newValue?.cgColor
}
}
}
1 using framework
It display all Properties
now i created xcframework. all properties not display Now i am stuck with this.
anyone help me how can i create xcframwork and display all properties like normal framework. Please help me on this.
The properties in your framework are internal. When no access modifier is specified then Swift defaults to internal.
enter image description here
so in your code:
var radTopLeft:CGFloat = 0 {
didSet {
self.setNeedsLayout()
}
}
is equivalent to:
internal var radTopLeft:CGFloat = 0 {
didSet {
self.setNeedsLayout()
}
}
Therefore no code outside the framework can access this property. In order to make it accessible to the framework consumer you have to mark the property public. i.e.
public var radTopLeft:CGFloat = 0 {
didSet {
self.setNeedsLayout()
}
}
Test it out: https://drive.google.com/file/d/1_WSGKRKNt4lytrVEuozn8W4WYRR6nPif/view?usp=sharing
Related
Without any experience with iOS, I have been asked to upgrade to Swift 4 an application that is using Swift 3. I updated the language to use in "Swift language version" and I followed the recommendations made by xCode (explicitly use #objc).
Once all errors fixed the application works, but one UI-related feature is not working anymore. The app has a custom UITextField that is used to enter a password. Depending on the value of a #IBInspectable class field of the custom text field the text is hidden or not.
The value of this variable is correctly set in MainStoryboard but when the class is instantiated this value is not set to the value in the storyboard, and as a result, the custom text field does not behave how it should. The log does not mention any error.
Does anybody experience the same problem?
I checked storyboard and class, I did not find any problems, I also compared the code of the version with Swift 3 and the one I updated with Swift 4 and there are no differences (except the #objc ones).
Are there something else to look that can help me to find why the value set in MainStoryboard is not propagated to the class?
Edit
Below is the code involved in the problem:
a variable isPassword is declared to reflect the value of the IBInspectable variable
the variable IBInspectable is declared
when awakeFromNib depending on the value of isPassword a method to either hide the text or not is called
#IBDesignable class CustomEditText: UITextField {
var isPassword = false
// Inspector variable determining if the text must be hidden or not
#IBInspectable var isAPasswordField: Bool {
get{
return self.isPassword
}
set{
self.isPassword = isAPasswordField
}
}
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
setup() // Set borders, font, ...
}
override func awakeFromNib() {
super.awakeFromNib()
if isPassword { // isPassword does not reflect the value of isAPasswordField set in storyboard
self.isSecureTextEntry = true
setRevealButton() // the text is hidden
} else {
setCustomClearButton() // the text is not hidden
}
}
...
Answer
#Alladinian gave the good answer.
Below for completeness, another solution that I found:
#IBInspectable var isPasswordField: Bool = false {
didSet{
self.isPassword = isPasswordField
if isPassword {
self.isSecureTextEntry = true
setRevealButton()
} else {
setCustomClearButton()
}
}
}
The correct form would be (note the setter assignment):
#IBInspectable var isAPasswordField: Bool {
get {
return self.isPassword
}
set {
self.isPassword = newValue
}
}
since the actual value have not been (and will not be - at least 'directly') set on isAPasswordField (remember, we are implementing the setter of a computed property after all...)
Also, why don't you just use isPassword directly by marking it as inspectable, avoiding the need for an extra ivar?
PS: newValue is the default name for the to-be-set value. You can read more about it under Shorthand Setter Declaration section in the Swift Programming Language book
The following code works fine for me for newer versions:
#IBInspectable var isAPass: Bool {
get {
return self.isSecureTextEntry
}
set {
self.isSecureTextEntry = newValue
}
}
Is there any way to add section name in newly added #IBDesignable properties for better readability.
//
//MARK: - Badge
//
#IBInspectable
var badgeColor:UIColor = UIColor.darkGray {
didSet {
updateView()
}
}
#IBInspectable
var showBadgeOnIndex:Int = 0 {
didSet {
if showBadgeOnIndex >= buttons.count {
showBadgeOnIndex = 0
}
updateView()
}
}
#IBInspectable
var showAllBadge:Bool = false {
didSet {
updateView()
}
}
#IBInspectable
var hideAllBadge:Bool = true {
didSet {
updateView()
}
}
ex:
In the picture above, the view properties have the section name View.
Any help would be appreciated.
I already know that the name of the custom class will appear as the section name in the Attributes Inspector.
Sections and their titles in the Attributes inspector are generated based on what exact classes the properties in that section belong to. There is no way to change this behavior.
However, Xcode automatically groups the inspectable properties that have similar names. Those groups are separated with a line. This behavior is also visible in your example picture:
By default your classname (A name of your custom class) becomes a title for IBDesignable properties
Here is reference documents, what you want. IBInspectable / IBDesignable
I've been playing with the IBInspectable/IBDesignable like in this article: http://nshipster.com/ibinspectable-ibdesignable/.
It shows how you can make an extension to add extra editing options in storyboard. The problem however is that you can't see these changes reflected in the preview. For this you need to subclass, use IBDesignable and do the didset{} stuff.
The problem with this is that you need to make a subclass of every stock UIView subclass. So a subclass of UILabel, UITextField and so on. Every time you have to copy/paste the regular UIView stuff like borders and corner radius.
I don't believe Swift supports multiple inheritance, which would have made this much easier.
Let's say your IBDesignable subclass of UIView is called IBView. Is there a way to make e.g. UILabel be a subclass of IBView instead of UIView?
In the end I'm looking if there is a way to make IBDesignable less tedious.
Like you, I'm trying to find a better solution to work with IBDesignable.
What I did to avoid repeat the same code:
I made an extension of UIView to insert all the #IBInspectables I want (like corder radius, border width...).
I created my #IBDesignables that only inherit from UIView, UIButton (or any subclass of UIView I want) in order to render on Interface Builder.
Check this code:
extension UIView {
#IBInspectable var cornerRadius: CGFloat {
get {
return layer.cornerRadius
}
set {
layer.cornerRadius = newValue
layer.masksToBounds = newValue > 0
}
}
#IBInspectable var borderColor: UIColor? {
get {
return UIColor(cgColor: layer.borderColor ?? UIColor.clear.cgColor)
}
set {
layer.borderColor = newValue?.cgColor
}
}
#IBInspectable var borderWidth: Double {
get {
return Double(layer.borderWidth)
}
set {
layer.borderWidth = CGFloat(newValue)
}
}
}
#IBDesignable
class BorderView: UIView { }
#IBDesignable
class BorderButton: UIButton { }
I hope it helps you!
So I'm fairly new to the whole UIAppearance approach to doing things, and doing it with swift. Hurray for not a ton of documentation out there.
I'm trying to set my border radius through UIAppearance with something along the lines of:
CircleButton.appearance.roundBorderRadius = 9
My CircleButton class implementation:
public class CircleButton : UIButton{
#nonobjc var roundBorderRadius: CGFloat? {
get { return self.layer.cornerRadius }
set {
self.layer.cornerRadius = newValue!
}
}
}
And I hook everything up in Storyboard to a ViewController that contains a CircleButton. No Compilation or Build errors.
However, at runtime I'm getting a:
"Thread 1: EXC_BAD_ACCESS" error on:
CircleButton.appearance.roundBorderRadius = 9
Any advice?
Remove #nonobjc and add dynamic, then change the type from CGFloat? to CGFloat and remove the ! after newValue in the setter, like so:
public class CircleButton: UIButton {
dynamic var roundBorderRadius: CGFloat {
get {
return layer.cornerRadius
}
set {
layer.cornerRadius = newValue
}
}
}
Is it possible to set a design-time text for UILabel (or image if using UIImageView) on iOS 8? if so, how to?
Basically what I need is not to empty all of my labels before compiling so that it doesn't show dummy data before loading from the network the actual data. An algorithm to programatically clear all outlets isn't really a good solution as it is unnecessary code.
You could try subclassing the classes you want to have design-time attributes. Here is an example of that for UILabel:
import UIKit
class UIPrototypeLabel: UILabel {
#IBInspectable var isPrototype: Bool = false
override func awakeFromNib() {
if (isPrototype) {
self.text = "test"
}
}
Then, in IB, you will see isPrototype, and you can set it to true or false.
You can also change the default from false to true in the isPrototype:Bool = false line if you want. You can also change what happens if isPrototype is true. I had it make the text "test" so I could see feedback when testing this out, so you could change it to nil or "" or whatever.
You can also just eschew the isPrototype bool and have this class always reset the text. I just thought the IBInspectable attribute was cool, but if you just want this class to always clear the label text then you would just delete the bool and the check and just self.text=nil every time.
The con to this approach is you need to make all of your labels UIPrototypeLabel to get this functionality.
There is a second, scarier approach, that will add this functionality to all of your UILabels, and that is extending UILabel.
import ObjectiveC
import UIKit
// Declare a global var to produce a unique address as the assoc object handle
var AssociatedObjectHandle: UInt8 = 0
extension UILabel {
#IBInspectable var isPrototype:Bool {
get {
var optionalObject:AnyObject? = objc_getAssociatedObject(self, &AssociatedObjectHandle)
if let object:AnyObject = optionalObject {
return object as! Bool
} else {
return false // default value when uninitialized
}
}
set {
objc_setAssociatedObject(self, &AssociatedObjectHandle, newValue, objc_AssociationPolicy(OBJC_ASSOCIATION_RETAIN_NONATOMIC))
}
}
public override func awakeFromNib() {
if (isPrototype) {
self.text = "test"
}
}
}
credit to Is there a way to set associated objects in Swift? for some of that code