{"id":17093439,"url":"https://github.com/jiongxing/namespacedemo","last_synced_at":"2026-03-11T14:35:20.395Z","repository":{"id":89320069,"uuid":"90736669","full_name":"JiongXing/NamespaceDemo","owner":"JiongXing","description":"Swift Namespace, Swift创建命名空间","archived":false,"fork":false,"pushed_at":"2017-05-09T12:18:10.000Z","size":11,"stargazers_count":4,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-01T01:01:47.639Z","etag":null,"topics":["namespace","swift"],"latest_commit_sha":null,"homepage":"http://www.jianshu.com/p/527ca32ef380","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/JiongXing.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-05-09T11:09:50.000Z","updated_at":"2020-03-17T07:47:37.000Z","dependencies_parsed_at":null,"dependency_job_id":"f47d42b8-0177-49b3-be9c-5c10eb35fbee","html_url":"https://github.com/JiongXing/NamespaceDemo","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JiongXing%2FNamespaceDemo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JiongXing%2FNamespaceDemo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JiongXing%2FNamespaceDemo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JiongXing%2FNamespaceDemo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/JiongXing","download_url":"https://codeload.github.com/JiongXing/NamespaceDemo/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253786158,"owners_count":21964099,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["namespace","swift"],"created_at":"2024-10-14T14:07:01.634Z","updated_at":"2026-03-11T14:35:20.347Z","avatar_url":"https://github.com/JiongXing.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003e 相比于OC时代的完全没有命名空间，Swift可以通过巧妙的办法，实现几乎等同于命名空间的效果。\n\n# 需求\n\n现在我们希望为`UIColor`类增加一个扩展方法，根据其自身颜色生成图像`UIImage`。\n在没有命名空间的时代，可能结果是这样子的：\n```swift\nlet image = UIColor.blue.image\n```\n或者为避免与其它框架API同名，可能结果会变成这样子：\n```swift\nlet image = UIColor.blue.jx_image\n```\n当然这种风格非常地OC。\n\n那有没有优雅一点的办法来代替OC Style？比如能写成这样子就好了：\n\n```swift\nlet image = UIColor.blue.jx.image\n```\n\nSwift3绕一下路，也是可以做到的。姑且把中间的`.jx`叫做命名空间(Namespace)，没错，抄了一下C#们的叫法。\n\n# 定义命名空间\n\n具体的做法通过扩展特定的协议来达到目的。\n我们需要定义两个协议，其中一个是固定的写法：\n```swift\n/// 类型协议\nprotocol TypeWrapperProtocol {\n    associatedtype WrappedType\n    var wrappedValue: WrappedType { get }\n    init(value: WrappedType)\n}\n\nstruct NamespaceWrapper\u003cT\u003e: TypeWrapperProtocol {\n    let wrappedValue: T\n    init(value: T) {\n        self.wrappedValue = value\n    }\n}\n```\n\n另一个协议基本上也是固定的写法，只是根据我们的需要，更改其内的命名空间名字即可。\n比如我需要一个名为`jx`的命名空间，就可以这样写：\n```swift\n/// 命名空间协议\nprotocol NamespaceWrappable {\n    associatedtype WrapperType\n    var jx: WrapperType { get }\n    static var jx: WrapperType.Type { get }\n}\n\nextension NamespaceWrappable {\n    var jx: NamespaceWrapper\u003cSelf\u003e {\n        return NamespaceWrapper(value: self)\n    }\n    static var jx: NamespaceWrapper\u003cSelf\u003e.Type {\n        return NamespaceWrapper.self\n    }\n}\n```\n\n需要什么样的命名空间，就把其中的`jx`改成你希望的名字。\n\n# 使用命名空间\n\n实际上我们需要扩展的类不是`UIColor`，而是协议。\n这里分两步，第一步是让需要扩展的类遵循协议`NamespaceWrappable`：\n```swift\nextension UIColor: NamespaceWrappable {}\n```\n\n第二步是扩展协议`TypeWrapperProtocol`：\n```swift\nextension TypeWrapperProtocol where WrappedType == UIColor {\n    /// 用自身颜色生成UIImage\n    var image: UIImage? {\n        let rect = CGRect(x: 0, y: 0, width: 1, height: 1)\n        UIGraphicsBeginImageContext(rect.size)\n        let context = UIGraphicsGetCurrentContext()\n        context?.setFillColor(wrappedValue.cgColor)\n        context?.fill(rect)\n        let image = UIGraphicsGetImageFromCurrentImageContext()\n        return image\n    }\n}\n```\n\n在扩展的方法中，`self`代表的是协议，而不是目标扩展类。那要用到`self`怎么办？用`wrappedValue`吧，它就是我们的目标类/实例。\n\n# 验证\n现在可以愉快地玩耍了：\n```swift\nlet image = UIColor.blue.jx.image\n```\n\n使用了命名空间后，还有一个优点就是可以利用Xcode的代码补全。\n\n![Xcode代码补全](http://upload-images.jianshu.io/upload_images/2419179-7532c9e6518addba.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)\n\n相比在打出`.im`后Xcode会弹出一大堆匹配到`im`两字母的方法，使用了命名空间后，点出`.jx.`时，Xcode就只会提示此命名空间内的方法/属性。特别是`String`和`UIView`这种有巨量方法的类，只要打出命名空间就可以快速过滤不需要的方法。\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjiongxing%2Fnamespacedemo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjiongxing%2Fnamespacedemo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjiongxing%2Fnamespacedemo/lists"}