Swift中的命名空间

作者: YungFan | 来源:发表于2018-12-13 11:12 被阅读30次

命名空间namespace在C++、C#里面是一个常见概念,Swift中也引入了这样一个机制,下面来探索一下这个命名空间的来龙去脉。

一、为什么需要命名空间

简而言之一句话:为了避免命名的冲突

在开发中,尤其是在多模块开发中,很难保证模块之间的类名不会重复,为了保证不同模块下同名的类可以正常使用而不报错,引入命名空间来保证即使创建的类名一样,只要命名空间不一样,这些类也是不一样的,所以,这是一种安全机制,用命名空间来防止冲突。可以看出,Swift中的类名的完整形式其实是“命名空间+类名”。我们可以尝试在类中打印当前类来查看一下完整名字:

override func viewDidLoad() {
    super.viewDidLoad()
    print(self)
}
//打印结果是:<AA.ViewController: 0x7fec6a00e5c0>

二、命名空间查看与修改

从上面的打印结果来看,命名空间是我们项目的名字,那么如果查看呢?我们需要用源代码的形式打开Info.plist,可以看到里面有一个字段CFBundleExecutable,它对应的值就是命名空间。

查看命名空间.png

如果要修改命名空间,注意不要直接编辑Info.plist,可以进入Build Settings中搜索Product Name,然后进行修改。

修改命名空间.png

三、命名空间如何获取

既然知道可以通过Info.plist获取命名空间,那么如何在程序中获取呢?很显然需要解析Info.plist文件,拿到CFBundleExecutable对应的value值。

let namespace = Bundle.main.infoDictionary!["CFBundleExecutable"]
// 返回的是一个可选型      
print(namespace!)

四、命名空间在开发中的使用

开发中有一种常见的情形,就是自定义TabBarController,然后在里面添加一个个子控制器,这里面常常存在一个问题:通过一个控制器名(字符串)来创建一个控制器(类)。下面对比一下Objective-C与Swift两种语言的实现方式。

  • 由于Objective-C中没有命名空间,所以写起来很轻松。
//viewDidLoad中添加一个个控制器
- (void)viewDidLoad {
    [super viewDidLoad];
    [self addNavigationChildVC:@"ContactViewController" :@"联系人" :@"tabbar_contacts" :@"tabbar_contactsHL"];
}

//自定的方法中根据传进来的字符串创建控制器
-(void)addNavigationChildVC: (NSString *) vcName :(NSString *)title :(NSString *)nomalImageName :(NSString *)selectedImageName {
    //创建控制器
    Class class = NSClassFromString(vcName);
    UIViewController *vc = [[class alloc]init];
    ...
}
  • Swift中命名空间的存在,如果按照上述做法得不到想要的结果,这时候就需要想办法进行处理
//viewDidLoad中添加一个个控制器
override func viewDidLoad() {
    super.viewDidLoad()
    addChildViewController(vcName: "ContactsViewController", title: "联系人", image: "tabbar_contacts", selectedImage: "tabbar_contactsHL")
}

//创建一个函数来将控制器的名字转成具体的类
func stringToVC(vcName:String) -> UIViewController? {
    //获取命名空间
    guard let namespace = Bundle.main.infoDictionary!["CFBundleExecutable"] as? String else {
        print("获取失败")
        return nil
    }        
    //拼接完整的类
    guard let vcClass = NSClassFromString(namespace + "." + vcName) else {
        print("拼接失败")
        return nil
    }   
    //转换成UIViewController
    guard let vcType = vcClass as? UIViewController.Type else {
        print("转换失败")
        return nil
    }  
    //根据类型创建对应的控制器
    let vc = vcType.init()
    return vc
}

相关文章

  • Swift中String转Class类名

    String->Class Swift中引入了命名空间的概念,转Class需要拼接命名空间 注意Swift中引入了...

  • Swift学习之通过字符串创建对象

    一、swift的空间命名机制在 Swift 中,由于可以使用命名空间了,即使是名字相同的类型,只要是来自不同的命名...

  • Swift添加命名前缀

    Swift命名前缀 Swift的命名空间是基于模块(module),每一个module代表了一个Swift中的一个...

  • Swift中的命名空间

    命名空间 Objective-C一个一直以来令人诟病的地方就是没有命名空间,在应用开发时,所有的代码和引用的静态库...

  • Swift中的命名空间

    命名空间namespace在C++、C#里面是一个常见概念,Swift中也引入了这样一个机制,下面来探索一下这个命...

  • swift中的命名空间

    OC中没有命名空间,如果直接使用两个不同库,而且这两个库中都使用了同一个流行的三方,那么就会产生冲突。swift中...

  • Swift 基础(3) -- 根据类名创建对象

    1. 基础 Swift中的类名 在Swift中的类名是 : 命名空间 + 类名 .(比如:TestDemo.Per...

  • swift学习之语法基础二

    命名空间 swift中引入了命名空间的概念,只要在同一个命名空间下所有的资源都是共享的,而且默认情况下项目名称就是...

  • swift开发日志(一){命名空间,泛型,闭包}

    swift 的命名空间 涉及到NSClassFromString,在Swift中的使用方式与OC是有区别,并不像O...

  • swift-基础-一些OC与Swift的对照

    OC中的dealloc--Swift中的deinit。对象释放的时候会调用 Swift中如果文件在同一个命名空间下...

网友评论

    本文标题:Swift中的命名空间

    本文链接:https://www.haomeiwen.com/subject/vxdvhqtx.html