草庐IT

ios - 如果我想给自己分配一个属性怎么办?

coder 2023-07-15 原文

如果我尝试运行以下代码:

photographer = photographer

我得到错误:

Assigning a property to itself.


我想将属性分配给自身以强制运行 photographer didSet block 。

这是一个真实的例子:在 Winter 2013 Stanford iOS course 的“16. Segues and Text Fields”讲座中(13:20),教授推荐写类似下面的代码:

@IBOutlet weak var photographerLabel: UILabel!

var photographer: Photographer? {
    didSet {
        self.title = photographer.name
        if isViewLoaded() { reload() }
    }
}

override func viewDidLoad() {
    super.viewDidLoad()
    reload()
}

func reload() {
    photographerLabel.text = photographer.name
}

注意:我做了以下改动:(1)代码从Objective-C切换到了Swift; (2) 因为在Swift中,我使用了属性的didSet block ,而不是setPhotographer:方法; (3) 而不是 self.view.window 我正在使用 isViewLoaded 因为前者错误地强制 View 在访问 view 属性时加载; (4) reload() 方法(仅)为了简单起见更新标签,因为它更像我的代码; (5) 添加了摄影师IBOutlet 标签以支持这种更简单的代码; (6) 由于我使用的是 Swift,isViewLoaded() 检查不再存在,仅仅是出于性能原因,现在 需要 来防止崩溃,因为 IBOutlet 是定义为 UILabel! 而不是 UILabel? 因此在加载 View 之前尝试访问它会使应用程序崩溃;这在 Objective-C 中不是强制性的,因为它使用空对象模式。

我们两次调用reload的原因是因为我们不知道该属性是在创建 View 之前还是之后设置的。例如,用户可能首先设置属性,然后呈现 View Controller ,或者他们可能呈现 View Controller ,然后更新属性。

我喜欢这个属性对于 View 何时加载是不可知的(最好不要对 View 加载时间做出任何假设),所以我想在我自己的代码中使用相同的模式(仅略微修改):

@IBOutlet weak var photographerLabel: UILabel?

var photographer: Photographer? {
    didSet {
        photographerLabel?.text = photographer.name
    }
}

override func viewDidLoad() {
    super.viewDidLoad()
    photographer = photographer
}

这里不是创建一个从两个地方调用的新方法,我只想要 didSet block 中的代码。我希望 viewDidLoad 强制调用 didSet,所以我将属性分配给它自己。不过,Swift 不允许我这样做。如何强制调用 didSet

最佳答案

Swift 3.1 之前,您可以将属性 name 分配给自身:

name = (name)

但这现在给出了相同的错误:“将属性分配给自身”

还有许多其他方法可以解决这个问题,包括引入临时变量:

let temp = name
name = temp

这太有趣了,不能不分享。我相信社区可以想出更多的方法来做到这一点,越疯狂越好

class Test: NSObject {
    var name: String? {
        didSet {
            print("It was set")
        }
    }

    func testit() {
        // name = (name)    // No longer works with Swift 3.1 (bug SR-4464)
        // (name) = name    // No longer works with Swift 3.1
        // (name) = (name)  // No longer works with Swift 3.1
        (name = name)
        name = [name][0]
        name = [name].last!
        name = [name].first!
        name = [1:name][1]!
        name = name ?? nil
        name = nil ?? name
        name = name ?? name
        name = {name}()
        name = Optional(name)!
        name = ImplicitlyUnwrappedOptional(name)
        name = true ? name : name
        name = false ? name : name
        let temp = name; name = temp
        name = name as Any as? String
        name = (name,0).0
        name = (0,name).1
        setValue(name, forKey: "name") // requires class derive from NSObject
        name = Unmanaged.passUnretained(self).takeUnretainedValue().name
        name = unsafeBitCast(name, to: type(of: name))
        name = unsafeDowncast(self, to: type(of: self)).name
        perform(#selector(setter:name), with: name) // requires class derive from NSObject
        name = (self as Test).name
        unsafeBitCast(dlsym(dlopen("/usr/lib/libobjc.A.dylib",RTLD_NOW),"objc_msgSend"),to:(@convention(c)(Any?,Selector!,Any?)->Void).self)(self,#selector(setter:name),name) // requires class derive from NSObject
        unsafeBitCast(class_getMethodImplementation(type(of: self), #selector(setter:name)), to:(@convention(c)(Any?,Selector!,Any?)->Void).self)(self,#selector(setter:name),name) // requires class derive from NSObject
        unsafeBitCast(method(for: #selector(setter:name)),to:(@convention(c)(Any?,Selector,Any?)->Void).self)(self,#selector(setter:name),name) // requires class derive from NSObject 
        _ = UnsafeMutablePointer(&name)
        _ = UnsafeMutableRawPointer(&name)
        _ = UnsafeMutableBufferPointer(start: &name, count: 1)
        withUnsafePointer(to: &name) { name = $0.pointee }

        //Using NSInvocation, requires class derive from NSObject
        let invocation : NSObject = unsafeBitCast(method_getImplementation(class_getClassMethod(NSClassFromString("NSInvocation"), NSSelectorFromString("invocationWithMethodSignature:"))),to:(@convention(c)(AnyClass?,Selector,Any?)->Any).self)(NSClassFromString("NSInvocation"),NSSelectorFromString("invocationWithMethodSignature:"),unsafeBitCast(method(for: NSSelectorFromString("methodSignatureForSelector:"))!,to:(@convention(c)(Any?,Selector,Selector)->Any).self)(self,NSSelectorFromString("methodSignatureForSelector:"),#selector(setter:name))) as! NSObject
        unsafeBitCast(class_getMethodImplementation(NSClassFromString("NSInvocation"), NSSelectorFromString("setSelector:")),to:(@convention(c)(Any,Selector,Selector)->Void).self)(invocation,NSSelectorFromString("setSelector:"),#selector(setter:name))
        var localVarName = name
        withUnsafePointer(to: &localVarName) { unsafeBitCast(class_getMethodImplementation(NSClassFromString("NSInvocation"), NSSelectorFromString("setArgument:atIndex:")),to:(@convention(c)(Any,Selector,OpaquePointer,NSInteger)->Void).self)(invocation,NSSelectorFromString("setArgument:atIndex:"), OpaquePointer($0),2) }
        invocation.perform(NSSelectorFromString("invokeWithTarget:"), with: self)
    }
}

let test = Test()
test.testit()

关于ios - 如果我想给自己分配一个属性怎么办?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31930257/

有关ios - 如果我想给自己分配一个属性怎么办?的更多相关文章

  1. ruby - 使用 Vim Rails,您可以创建一个新的迁移文件并一次性打开它吗? - 2

    使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta

  2. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

    我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

  3. ruby-on-rails - 渲染另一个 Controller 的 View - 2

    我想要做的是有2个不同的Controller,client和test_client。客户端Controller已经构建,我想创建一个test_clientController,我可以使用它来玩弄客户端的UI并根据需要进行调整。我主要是想绕过我在客户端中内置的验证及其对加载数据的管理Controller的依赖。所以我希望test_clientController加载示例数据集,然后呈现客户端Controller的索引View,以便我可以调整客户端UI。就是这样。我在test_clients索引方法中试过这个:classTestClientdefindexrender:template=>

  4. ruby-on-rails - 如果为空或不验证数值,则使属性默认为 0 - 2

    我希望我的UserPrice模型的属性在它们为空或不验证数值时默认为0。这些属性是tax_rate、shipping_cost和price。classCreateUserPrices8,:scale=>2t.decimal:tax_rate,:precision=>8,:scale=>2t.decimal:shipping_cost,:precision=>8,:scale=>2endendend起初,我将所有3列的:default=>0放在表格中,但我不想要这样,因为它已经填充了字段,我想使用占位符。这是我的UserPrice模型:classUserPrice回答before_val

  5. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  6. Ruby Koans about_array_assignment - 非平行与平行分配歧视 - 2

    通过ruby​​koans.com,我在about_array_assignment.rb中遇到了这两段代码你怎么知道第一个是非并行赋值,第二个是一个变量的并行赋值?在我看来,除了命名差异之外,代码几乎完全相同。4deftest_non_parallel_assignment5names=["John","Smith"]6assert_equal["John","Smith"],names7end45deftest_parallel_assignment_with_one_variable46first_name,=["John","Smith"]47assert_equal'John

  7. ruby - 多个属性的 update_column 方法 - 2

    我有一个具有一些属性的模型:attr1、attr2和attr3。我需要在不执行回调和验证的情况下更新此属性。我找到了update_column方法,但我想同时更新三个属性。我需要这样的东西:update_columns({attr1:val1,attr2:val2,attr3:val3})代替update_column(attr1,val1)update_column(attr2,val2)update_column(attr3,val3) 最佳答案 您可以使用update_columns(attr1:val1,attr2:val2

  8. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

  9. ruby - 为什么 SecureRandom.uuid 创建一个唯一的字符串? - 2

    关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion为什么SecureRandom.uuid创建一个唯一的字符串?SecureRandom.uuid#=>"35cb4e30-54e1-49f9-b5ce-4134799eb2c0"SecureRandom.uuid方法创建的字符串从不重复?

  10. ruby - 如果指定键的值在数组中相同,如何合并哈希 - 2

    我有一个这样的哈希数组:[{:foo=>2,:date=>Sat,01Sep2014},{:foo2=>2,:date=>Sat,02Sep2014},{:foo3=>3,:date=>Sat,01Sep2014},{:foo4=>4,:date=>Sat,03Sep2014},{:foo5=>5,:date=>Sat,02Sep2014}]如果:date相同,我想合并哈希值。我对上面数组的期望是:[{:foo=>2,:foo3=>3,:date=>Sat,01Sep2014},{:foo2=>2,:foo5=>5:date=>Sat,02Sep2014},{:foo4=>4,:dat

随机推荐