如何在Swift扩展属性不一致怎么办中添加存储属性

如何在Swift扩展中添加存储属性 - 简书
如何在Swift扩展中添加存储属性
.一般而言,swift的扩展Extension只能添加计算属性,不能添加存储属性。当然,如果利用run time也可以实现extension添加存储属性的效果.
.如我给UIButton这个类添加了如下属性:
private var key: Void?
func createImageWithColor(_ color: UIColor) -& UIImage? {
let rect = CGRect(x: 0.0, y: 0.0, width: 1.0, height: 1.0)
UIGraphicsBeginImageContext(rect.size)
let context = UIGraphicsGetCurrentContext()
context?.setFillColor(color.cgColor)
context?.fill(rect)
let theImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return theImage
extension UIButton {
@IBInspectable var normalColor: UIColor? {
return objc_getAssociatedObject(self, &key) as? UIColor
set(newValue) {
objc_setAssociatedObject(self, &key, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
setBackGroundColor(normalColor ?? UIColor.white, state: UIControlState())
@IBInspectable var highlightedColor: UIColor? {
return objc_getAssociatedObject(self, &key) as? UIColor
set(newValue) {
objc_setAssociatedObject(self, &key, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
setBackGroundColor(highlightedColor ?? UIColor.lightGray, state: .highlighted)
fileprivate func setBackGroundColor(_ backGroundColor: UIColor, state: UIControlState) {
let image = createImageWithColor(backGroundColor)
setBackgroundImage(image, for: state)Object-C---&Swift之(十)存储属性 - CSDN博客
Object-C---&Swift之(十)存储属性
计算属性相当于Object-C的getter、setter合成的属性,在Swift中结构体、类都可以定义计算属性
定义计算属性
[修饰符] var 计算属性名:属性类型{
//getter方法执行体,该方法必须有返回值
[set(形参名)
//setter方法执行体,该方法一定不能有返回值
注意:var计算属性只能定义成变量形式
enum Season
case Spring,Summer,Fall,Winter
var info:String
print("正在执行getter方法")
switch(self)
case .Spring:
return "春暖花开"
return "此恨绵绵无绝期"
set(newValue)
print("正在执行setter方法,传入参数为:\(newValue)")
var s=Season.Spring
)//访问info属性,实际就是调用对应的getter方法
s.info="秋高气爽"//对info属性赋值,实际就是调用对应的setter方法
再举一个类的例子
class User
var first:String=""
var last:String=""
var fullName:String
return first + "-" + last
set(newValue)
var ponentsSeparatedByString("-")
self.first=names[0]
self.last=name[1]
init(first:String,last:String)
self.first=first
self.last=last
let s=User(first:"六小龄童",last:"孙悟空")
print(s.fullName)
s.fullName="甄子丹-悟空"
print(s.first)//输出甄子丹
print(s.last)//输出悟空
setter方法简化
计算属性的setter方法总是只有一个形参,且该形参的类型与该计算属性的类型相同,因此Swift允许在定义计算属性时省略set部分的形参名。
如果程序省略计算属性的set部分的形参名,程序将为该形参提供一个隐式的形参名:newValue。所以可以改为
var ponentsSeparatedByString("-")
self.first=name[0]
self.last=name[1]
只读的计算属性
只有get部分的话称为只读的计算属性。我们可以省略get关键字和花括号
如上面的可以改为
var fullName:String{
return first + "-" + last
注意即使是只读属性也必须用var关键字
本文已收录于以下专栏:
相关文章推荐
属性观察者机制能让程序在属性被赋值时获得执行代码的机会,用来监视属性的除初始化之外的属性值变化,当属性值发生改变时可以对此作出响应
具体包括两个特殊的回调方法:willSet(newValue):被观...
原创文章,欢迎转载。转载请注明:关东升的博客  Swift中的属性分为存储属性和计算属性,存储属性就是Objective-C中的数据成员,计算属性不存储数据,但可以通过计算其他属性返回数据。存储属性可...
属性将值跟特定的类、结构体和枚举关联。
swift中的属性分为存储属性和计算属性两种。
存储属性:
一个存储属性就是存储在特定类或结构体的实例里的一个常量或变量。存储属性可以是变量存...
构造函数的主要作用是初始化实例,其中包括:初始化存储属性和其它的初始化。在Rectangle类或结构体中,如果在构造函数中初始化存储属性width和height后,那么在定义他们时就不需要初始化了。
...
属性是依赖于某个特定的类、结构体或者枚举类型的值。Swift有两种属性:存储类型和计算类型。其中存储类型可以作为实例的一部分存放变量或者常量的值,而计算类型的属性值是通过运算的来的。计...
原创文章,欢迎转载。转载请注明:关东升的博客  构造函数的主要作用是初始化实例,其中包括:初始化存储属性和其它的初始化。在Rectangle类或结构体中,如果在构造函数中初始化存储属性width和he...
写了12个Person来复习,不过完成同样的代码需要敲键盘的次数相比OC确实少了很多,这很多应该归功于Swift中不写分号,以及少了OC中的中括号。
一、类与结构体
两者在Swift中差不...
属性将值跟特定的类、结构或枚举关联。存储属性存储常量或变量作为实例的一部分,计算属性计算(而不是存储)一个值。计算属性可以用于类、结构体和枚举里,存储属性只能用于类和结构体。
存储属性和计算属性通...
属性将值跟特定的类、结构或枚举关联。存储属性存储常量或变量作为实例的一部分,计算属性计算(而不是存储)一个值。计算属性可以用于类、结构体和枚举里,存储属性只能用于类和结构体。
存储属性和计算属性通常...
一、类与结构体
两者在Swift中差不了多少了
类与结构体有很多相同的地方: (第2,3点是其他语言中不存在的)
1)都可以定义属性/方法/下标(结构体也可以定义方法了)
2)都能初始化(...
他的最新文章
讲师:何宇健
讲师:董岩
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)Swift给系统的类扩展属性 - CSDN博客
Swift给系统的类扩展属性
OC的类别和扩展一般用来给类扩展方法,但有时我们需要给系统的类加一个额外的属性,这需要用到runtime机制。
Runtime是一套底层的C语言API(包含强大的C语言数据类型和函数)OC代码都是基于Runtime实现的,即编写的OC代码最终都会转成Runtime的代码
Runtime的作用:
1、获取类的私有变量
2、动态产生类,成员变量和方法
3、动态修改类,成员变量和方法
4、对换两个方法的实现(swizzle)
同样,在Swift中使用extension也可以为系统的类扩展属性:
private var key: Void?
extension UIViewController {
@IBInspectable var laxTabBarController: LAXTabBarController? {
return objc_getAssociatedObject(self, &key) as? LAXTabBarController
set(newValue) {
objc_setAssociatedObject(self, &key, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
本文已收录于以下专栏:
相关文章推荐
一起连带前面几篇Playground小结代码都转到github上了,注释写了很多,主要方便自己以后可以翻翻看。Swift语法主要部分差不多就这些了。当然还有泛型、运算符重载、ARC、闭包之类的补充。
...
一起连带前面几篇Playground小结代码都转到github上了。Swift语法主要部分差不多就这些了。当然还有泛型、运算符重载、ARC、闭包之类的补充。
一、扩展(extension)
首先看到swift扩展的时候,我就想起了OC的扩展和类别;于是我就在找swift的扩展和OC的扩展和类别是什么关系。经过几番查阅资料,发现swift的扩展和OC的类别是如出一辙。但是我又很一根筋地去查...
扩展就是向一个已有的类、结构体、枚举类型或者协议类型添加新功能(functionality)。Swift中的扩展就类似于ObjC中的分类(事实上在其他高级语言中更多的称之为扩展而非分类),但是它要比分...
import UIKit
* 本节主要内容:存储属性 / 计算型属性 / 类型属性 / 延迟加载属性
// 类型属性(Type Property)
// 声明描述玩家类, 记录每个...
原创文章,欢迎转载。转载请注明:关东升的博客  可以在原始类型上扩展计算属性,包括实例计算属性和静态计算属性。添加计算属性的定义,与普通的计算属性的定义是一样的。实例计算属性示例:在网络编程时,为了减...
类定义我们通过关键字class和struct来分别表示类和结构体,并在一对大括号中定义它们的具体内容/*
class SomeClass {
// class definition goes he...
// 结构体 和 类
// 在Swift中,结构体被做了很对强化 几乎所有的数据类型都是用结构体实现的
// 相同点: 1.都可以定义变量 2.都可以定义方法 3.都可以定义构造器 Int
main.swift
Created by lanou on 16/10/27.
Copyright (c) 2016年 lanou. ...
Swift中类的结构和OC , JS都差不多 , 不难理解 , 上手也非常快//定义类
class 类名 : superClass {
//定义属性和方法
他的最新文章
讲师:何宇健
讲师:董岩
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)Swift中通过OC运行时给系统类添加闭包属性 - 简书
Swift中通过OC运行时给系统类添加闭包属性
Swift中通过OC的运行时给系统的类添加闭包属性 | 使用类扩展(extension)
Swift中使用typealias定义一个闭包(无返回值,有一个数组类型参数)
typealias XYRearrangeNewDataBlock = (_ newData: [Any]) -& Void
OC 使用typedef定义(无返回值,有一个数组类型参数)
typedef void(^XYRollNewDataBlock)(NSArray * newData);
在Swift类扩展中声明闭包属性由于Swift扩展不接受这些存储的属性,所以可以通过关联属性存储属性,比如下面给UICollectionView的扩展增加两个闭包属性(错误写法,如果非闭包属性可以这么,由于写习惯了OC,由于Swift不熟练,下面这个错误我搞了3个小时才解决,记录是为了自己不再次出错)
public extension UICollectionView {
typealias XYRearrangeNewDataBlock = () -& Void
typealias XYRearrangeOriginaDataBlock = () -& [String]
// MARK:- 关联属性的key
struct xy_associatedKeys {
static var originalDataBlockKey = "originalDataBlockKey"
static var newDataBlockKey = "newDataBlockKey"
// 声明闭包属性,并通过set函数与当前类产生关联,get函数获取关联
var originalDataBlock : XYRearrangeNewDataBlock? {
if let originalDataBlock = objc_getAssociatedObject(self, &xy_associatedKeys.originalDataBlockKey) as? XYRearrangeNewDataBlock {
return originalDataBlock
return nil
set(newValue) {
? 总是在set函数中报编译错误
objc_setAssociatedObject(self, &xy_associatedKeys.originalDataBlockKey, newValue, .OBJC_ASSOCIATION_COPY_NONATOMIC)
var newDataBlock: XYRearrangeNewDataBlock? {
if let newDataBlock = objc_getAssociatedObject(self, &xy_associatedKeys.newDataBlockKey) as? XYRearrangeNewDataBlock {
return newDataBlock
return nil
set(newValue) {
objc_setAssociatedObject(self, xy_associatedKeys.newDataBlockKey, newValue, .OBJC_ASSOCIATION_COPY_NONATOMIC)
// 将闭包属性作为便利构造函数的参数
convenience init(collectionVewFlowLayout : UICollectionViewFlowLayout, originalDataBlock: XYRearrangeOriginaDataBlock, newDataBlock: XYRearrangeNewDataBlock) {
self.init()
错误信息:Command failed due to signal: Segmentation fault: 11在Swift的类扩展中关联闭包block属性时,总是报编译失败错误,最终把错误定义在objc_setAssociatedObject关联闭包属性时
解决方法:要先定义一个类属性作为闭包容器,专门存放闭包的属性,以下是正确的在extension中给类添加闭包属性的方法注意: 如果便利构造函数中有闭包参数,外界调用这个方法时,需要自己把闭包参数改为大括号{}
以下是正确添加关联闭包属性的方法
import UIKit
public extension UICollectionView {
typealias XYRearrangeNewDataBlock = () -& Void
typealias XYRearrangeOriginaDataBlock = () -& [String]
// MARK:- 关联属性的key
private struct xy_associatedKeys {
static var originalDataBlockKey = "xy_originalDataBlockKey"
static var newDataBlockKey = "xy_newDataBlockKey"
// 定义一个类属性作为闭包的容器,专门存放闭包的属性
private class BlockContainer: NSObject, NSCopying {
func copy(with zone: NSZone? = nil) -& Any {
return self
var rearrangeNewDataBlock: XYRearrangeNewDataBlock?
var rearrangeOriginaDataBlock: XYRearrangeOriginaDataBlock?
// 定义个一个计算属性,通过OC的运行时获取关联对象和设置关联对象
private var newDataBlock: BlockContainer? {
if let newDataBlock = objc_getAssociatedObject(self, &xy_associatedKeys.newDataBlockKey) as? BlockContainer {
return newDataBlock
return nil
// 如果计算属性的setter没有定义表示新值的参数名,则可以用默认值newValue
set(newValue) {
objc_setAssociatedObject(self, xy_associatedKeys.newDataBlockKey, newValue, .OBJC_ASSOCIATION_COPY_NONATOMIC)
// 通过外界调用便利构造函数时,给闭包属性赋值
convenience init(collectionVewFlowLayout : UICollectionViewFlowLayout, originalDataBlock: @escaping XYRearrangeOriginaDataBlock, newDataBlock:
@escaping XYRearrangeNewDataBlock) {
self.init()
// 创建blockContainer,将外界传来的闭包赋值给类属性中的闭包变量
let blockContainer: BlockContainer = BlockContainer()
blockContainer.rearrangeNewDataBlock = newDataBlock
blockContainer.rearrangeOriginaDataBlock = originalDataBlock
self.newDataBlock = blockContainer
以下是与今天遇到的错误有关的Swift基础知识点
计算属性1.Swift中的计算属性不直接存储值跟存储属性不同,没有任何的”后端存储与之对应”2.计算属性用于计算, 提供一个getter和一个可选的setter来间接获取、设置其他属性和变量的值。如果计算属性的setter没有定义表示新值的参数名,则可以用默认值3.枚举不可以有存储属性, 但是允许有计算属性
结构体和类常量与存储属性的关系结构体和枚举是值类型 ,因此不能修改结构体常量中的属性不能修改结构体/枚举常量对象中的值, 因为他指向的对象是一个常量类是引用类型 ,可以修改类常量中属性的值, 因为他指向的对象不是一个常量
struct Person2 { // 结构体
var name: String
var age: Int
let p2: Person2 = Person2(name: "cdh", age: 20)
//因为结构体是值类型, 所以不能修改结构体常量中的属性
//不能修改结构体/枚举常量对象中的值, 因为他指向的对象是一个常量
//以下写法错误
//p2.name = "CDH" //不能修改结构体常量对象的值
//以下写法错误
//p2 = Person2(name: "CDH", age: 50)
class Person3 { // 类属性
var name: String = "cdh"
var age: Int = 20
let p3:Person3 = Person3()
//可以修改类常量中属性的值, 因为他指向的对象不是一个常量
p3.name = "CDH"
//不可以修改类常量的指向
//以下写法是错误的
//p3 = Person4()
在结构体和枚举中用static在类中使用class, 并且类中不允许将存储属性设置为类属性
struct Person4 {
普通的属性是每个对象一份
var name: String = "cdh"
类属性是所有相同类对象共用一份
static var gender:String = "man"
static var age:Int{
func show()
print("gender = \(Person4.gender) name = \(name)")
var p4 = Person4()
print("gender = \(Person4.gender)")
//输出结果: gender = man
var p5 = Person4()
//类属性是所有对象共用一份
print("gender = \(Person4.gender)")
//输出结果:
//gender = man
//gender = man name = cdh
//可以将计算属性设置为类属性
print("age = \(Person4.age)")
//输出结果:age = 20
class Person5 {
普通的属性是每个对象一份
var name: String = "cdh"
类中不允许将存储属性定义为类属性
下面为错误写法
class var gender:String = "man"
类中只能将计算属性定义为类属性
class var age:Int{
func show()
print("age = \(Person5.age)")
var p6 = Person5()
print("age = \(Person5.age)")
//输出结果:
//age = 20
//age = 20
GitHub:/Ossey

我要回帖

更多关于 kotlin 扩展属性 的文章

 

随机推荐