ios – 为什么,将nil作为参数从Objc C发送到swift类初始化器,用新对象替换nil参数

ios – 为什么,将nil作为参数从Objc C发送到swift类初始化器,用新对象替换nil参数,第1张

概述我创建了这个 Swift类: @objc public class Tester: NSObject { private var name: String private var user: Users init(string:String, user: Users) { print(user.empId) print(user.name) 我创建了这个 Swift类:
@objc public class Tester: NSObject {    private var name: String    private var user: Users    init(string:String,user: Users) {        print(user.empID)        print(user.name)        self.user = user        self.name = string        super.init()    }}

我从Obj C调用初始化程序,如下所示:

- (BOol)application:(UIApplication *)application dIDFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    // OverrIDe point for customization after application launch.    Nsstring * nilString = nil;    Users * nilUser = nil;    Tester * test = [[Tester alloc] initWithString:nilString user:nilUser];    return YES;}

在这里,我将nil参数传递给Swift初始化器.理想情况下,我希望这会崩溃,因为初始化程序只接受非零值.

但实际发生的是,当执行点到达初始化程序内部时,会创建新的参数对象

nil字符串变为“”,而nil的User变量现在指向一个对象.

但是对于像这样的房产

@property(nonatomic,strong) SomeClass * object;

哪里

object = nil;

当我从swift调用这个对象时,

let x = object.someGetter;

这崩溃了.

有一次,如果我将nil传递给某些非null,它会起作用,而在另一点上,它会崩溃.为什么存在这种奇怪的行为?如果由于某些原因,我的参数是nil,并传递给nonnull,我希望这会崩溃.这样我就能解决问题.

编辑:这变得如此意外,进一步尝试使用此代码.

字符串参数实际上是字符串,但是User显示未初始化,因此对字符串的 *** 作运行良好,但是用户对象接受了更改,但没有显示它们.

解决方法 所以有三个问题:

>首先,为什么访问用户属性不会崩溃,
>第二,为什么有一个空字符串而不是一个空字符串,
>第三,为什么分配属性(自定义类)崩溃

我会回答所有这些:-)

1.访问“用户”属性

当访问Users类的属性时,Swift使用Objective C消息传递(我假设 – 用户是调试器输出中看到的ObjC-Class;基类NSObject).
在反汇编视图中,可以看到:

0x1000018be <+78>:   movq   0x3e6e2b(%rip),%rsi      ; "empID"   ....0x1000018d7 <+103>:  callq  0x100361b10               ; symbol stub for: objc_msgSend

由于objc_msgSend支持nil消息传递,因此调用不会失败.

2.空字符串魔法

从Objective C调用Swift初始化程序时,桥接代码会创建以下内容:

0x100001f45 <+53>: callq  0x100021f50               ; static (extension in Foundation):;Swift.String._unconditionallyBrIDgeFromObjectiveC (Swift.Optional<__ObjC.Nsstring>) -> Swift.String   ....0x100001f5b <+75>: callq  0x100001870               ; TestCalling.Tester.init (string : Swift.String,user : __ObjC.ObjCUser) -> TestCalling.Tester at SwiftClass.swift:14

这里有趣的部分是_unconditionallyBrIDgeFromObjectiveC调用.这将在内部调用Swift.String函数_cocoaStringToSwiftString_NonASCII,并检查源代码(here,line 48),您可以看到以下内容:

@inline(never) @_semantics("stdlib_binary_only") // HIDe the CF dependencyfunc _cocoaStringToSwiftString_NonASCII(  _ source: _CocoaString) -> String {  let cfImmutableValue = _stdlib_binary_CFStringCreatecopy(source)  let length = _stdlib_binary_CFStringGetLength(cfImmutableValue)  let start = _stdlib_binary_CFStringGetCharactersPtr(cfImmutableValue)  return String(_Stringcore(    baseAddress: start,count: length,elementShift: 1,hasCocoaBuffer: true,owner: unsafeBitCast(cfImmutableValue,to: Optional<AnyObject>.self)))}

该函数总是返回一个新的Swift.String对象,在我们的例子中是一个空对象!所以,再没有崩溃.

3.财产准入

访问自定义属性时,例如将其分配给变量:

let x:SomeClass = object.someGetter;

发生以下情况:

> someGetter的返回值将被保留(objc_retainautoreleasedReturnValue) – 这不会崩溃
>返回的对象将被隐式解包 – 然后崩溃

如果x是弱属性或可选,则代码不会崩溃.即使使用类型推断,它也不会崩溃(在我的机器上,swift 4):

let x = object.someGetter;

这是因为推断的x类型是可选的SomeClass?除非属性本身被声明为nonnull:

@property(nonatomic,strong,nonnull) SomeClass * object;
总结

以上是内存溢出为你收集整理的ios – 为什么,将nil作为参数从Objc C发送到swift类初始化器,用新对象替换nil参数全部内容,希望文章能够帮你解决ios – 为什么,将nil作为参数从Objc C发送到swift类初始化器,用新对象替换nil参数所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://www.54852.com/web/1100427.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-28
下一篇2022-05-28

发表评论

登录后才能评论

评论列表(0条)

    保存