与无法识别的选择器对抗时学习目标C

与无法识别的选择器对抗时学习目标C

前提:

我试图在我的项目中实施AdManager单例类,但遇到一个问题,试图使其调用广告SDK。

好吧,那不是很漂亮。

一些其他背景。 我选择单例方法的想法是,我们不能在这个类中制造多个对象。 当我们引用此类时,我们都希望引用该对象。 我不认为问题在单例实现的背后,但是我不知道代码是如何工作的..那是个问题。

我的最终目标-我只希望有一位广告经理可以引用广告展示位置,广告信息,并在不同的视图中展示它们。 为此,我希望能够在我的任何控制器中调用AdManager并将其分配给我一个广告。 简单。 然后,插入各种其他货币化SDK,并即时进行交换,这样我就可以很好地划分游戏和货币化分区。

因此,事不宜迟,让我们深入研究如何首先声明单例,以确保我正确地做到了。

这是在做什么

+(id)sharedInstance {
静态AdManager * sharedInstance = nil;
静态dispatch_once_t OnceToken;
dispatch_once(&onceToken,^ {
sharedInstance = [[self alloc] init];
});
返回sharedInstance;
}

逐行细分:

+(id)sharedInstance

“ +”号表示这是类函数,而不是实例函数。

类方法以+开头,而实例方法以-开头。
可以将类方法与类名一起使用。
实例方法要求存在该类的实例。
实例(或对象)是您根据蓝图建造的实际房屋。

一堂课就像一栋房子的蓝图:您只有一个蓝图,并且(通常)您不能仅凭蓝图就做那么多。

https://stackoverflow.com/questions/1053592/what-is-the-difference-between-class-and-instance-methods

(id)表示指向任何Objective-C对象的指针。
作为目标c,这意味着我们需要确保保留/释放。
编译器非常高兴您可以将任何对象隐式转换为id。

这意味着这是一个类方法,它返回指向某个对象的指针。

https://stackoverflow.com/questions/7987060/what-is-the-意思-of-id
http://www.peachpit.com/articles/article.aspx?p=377302&seqNum=2

静态AdManager * sharedInstance = nil;

此方法定义了指向静态AdManager的指针,并将其设置为nil。

静态变量是分配给程序整个生命周期的变量
静态变量对于声明该文件的文件中的所有内容都是可见的。
如果在函数或方法中声明它,则仅在该函数或方法中可见,在两次调用之间保留值。

因此,在这种情况下,此sharedInstance仅存在于此函数的上下文中。
这就是为什么我们返回指向此sharedInstance的指针的原因。 我们不希望它可全局访问。
该函数充当“ GETTER”服务器,以将内存地址返回到该共享实例。

https://stackoverflow.com/questions/4965048/static-variables-in-objective-c-what-do-they-do

Nil!= null —主要区别是nil是指向NOTHING而不是NOTHING本身的对象指针。
它们全为零,但是NULL是void *,nil是id,而Nil是Class指针。

一般的经验法则是尽可能使用nil。

什么时候在Objective-C中使用nil和NULL?

是与对象(Objective-C中的id类型)绑定/对应的空值。 没有参考/地址,只是…

stackoverflow.com

静态dispatch_once_t OnceToken;

苹果医生说,这是与dispatch_once函数一起使用的谓词。
它应与下一行dispatch_once结合使用。
正如某些人所说,这实际上是确保只运行一次。

dispatch_once(&onceToken,^ {
sharedInstance = [[self alloc] init];
});

dispatch_once是线程安全的。 如果我们多次(从多个来源)多次调用dispatch_once,则this一次令牌可确保我们仅调用一次。

整个代码块实际上只是执行以下操作:

  • 制作令牌以供使用一次
  • 使用对该令牌的引用(无论哪个线程首先调用它并阻塞其余线程)来调用dispatch_once
  • 在将仅执行一次的块内,通过调用init函数初始化sharedInstance(然后将仅调用一次)。

我们可以将任何只想执行一次的东西放在init块中。

https://stackoverflow.com/questions/26513886/bool-vs-dispatch-once-t

返回sharedInstance;

完成所有这些操作后,我们将指针返回到存在于此函数中的sharedInstance。 它是静态指针,因此不会被清除。

只要有很强的指针指向对象,该对象就保持“活动”状态。

https://stackoverflow.com/questions/14469966/is-static-pointer-a-strong-pointer

所以整个代码块的摘要
*返回指向某个目标c对象的指针的类函数
*创建指向AdManager对象的静态指针(最初为nil)
*确保线程安全的初始化

但说完所有话之后,这看起来似乎并不能解决所有问题。 恰恰相反,看起来它正在做它的工作。

此外,仅当我从AerServ调用init SDK函数时,该问题才会显现出来。

看起来这不是在引起我们的问题,该问题抱怨无法识别的选择器。

现在,深入研究这个问题,我(从我们的文档中)还注意到我缺少编译器标志。
不好了!

所以我加入了它们。但是它们是什么意思呢?

-奥比西
将-ObjC选项传递给链接器会使链接器加载实现任何Objective-C类或类别的静态库的所有成员。
这将实现任何类别方法的实现。 但这会使生成的可执行文件更大,并可能拾取不必要的对象。
因此,默认情况下未启用。

啊。 这就是为什么。

这很可能是AerServ SDK的依赖项,这就是为什么我每次在其中调用任何内容时都会遇到该问题的原因。

从堆栈溢出:
无法识别的选择器错误意味着在某处某个对象上调用了一个方法,而该对象没有该方法,因此它崩溃了。 “选择器”是方法的另一个术语。

由于连接不正确,这就是为什么它将自身运行到死亡的原因。

这不是我的代码的问题,我只需要指出,这需要在加载静态库时全力以赴,而不是这种更为简约的默认方法(这也不起作用)。

-fobjc-arc

如果要排除使用ARC编译文件的方法,可以通过在.m文件(-fno-objc-arc)上设置标志来实现
同样,如果要在ARC中包含文件,则可以使用-fobjc-arc标志。

ARC =自动参考计数。
我如何看待这表示应该向哪个目标添加此标志,所有文件都应使用ARC进行编译。

https://developer.apple.com/library/archive/qa/qa1490/_index.html
https://www.codeography.com/2011/10/10/making-arc-and-non-arc-play-nice.html
https://stackoverflow.com/questions/39131512/add-fobjc-arc-flag-to-new-files-created-in-xcode-automatically

摘要:

好像发生了我的问题,因为我错过了这两个标志。

具体来说,不带-ObjC标志。

我确实了解了有关多线程,内存和指针的细微差别以及ObjC如何处理这些细微差别的更多信息,因此无论如何这都是福音。

最后的想法-为什么在没有这些标志的情况下不能提供SDK?
也许这是未来的另一个问题。