Swift编程语言有关于扩展的访问控制的说法:
您可以在类,结构或枚举可用的任何访问上下文中扩展类,结构或枚举.扩展中添加的任何类型成员具有与要扩展的原始类型中声明的类型成员相同的默认访问级别.如果扩展公共或内部类型,则添加的任何新类型成员都将具有内部的默认访问级别.如果扩展私有类型,则添加的任何新类型成员都将具有私有的默认访问级别.
或者,您可以使用显式访问级别修饰符(例如,专用扩展名)标记扩展,以为扩展中定义的所有成员设置新的默认访问级别.仍可以在单个类型成员的扩展中覆盖此新默认值.
我不完全理解上述说法.是说以下内容:
public struct Test { }
extension Test {
// 1. This will be default to internal because Test is public?
var prop: String { return "" }
}
public extension Test {
// 2. This will have access level of public because extension is marked public?
var prop2: String { return "" }
extension Test {
// 3. Is this the same as the above public extension example?
public var prop2: String { return "" } …Run Code Online (Sandbox Code Playgroud) open在Swift 3.0中引入了关键字(Swift 中的'open'关键字是什么?).
注意:仅限于NSObject派生类或@objc属性方法/属性的扩展.
在模块/框架的扩展中声明和使用public(class)方法/属性的代码破坏了,因为在定义模块之外不再意味着"可覆盖".public
例:
public extension UIManagedDocument {
public class func primaryDocumentName() -> String {
return "Document"
}
public class func primaryStoreURL() -> URL {
let documentsURL = FileManager.default.userDocumentsURL
return URL(fileURLWithPath: self.primaryDocumentName(), isDirectory: false, relativeTo: documentsURL)
}
public class func primaryModelName() -> String? {
return "Model"
}
}
Run Code Online (Sandbox Code Playgroud)
open关键字(你不能写得open extension NSObject那么好open func Method())问题:是否有解决方案能够跨模块/框架覆盖扩展提供的方法/属性?
我无法从objective-c访问我的swift扩展.
我在.swift文件中有以下代码:
extension NSDictionary {
func dictionaryAsJsonString() -> NSString {
var err: NSError?
var data = NSJSONSerialization.dataWithJSONObject(self, options: NSJSONWritingOptions.PrettyPrinted, error: &err)
var string = NSString(data: data, encoding: NSUTF8StringEncoding)
return string
}
}
Run Code Online (Sandbox Code Playgroud)
我希望能够在我的.m文件中执行以下操作:
[dictionary dictionaryAsJsonString];
Run Code Online (Sandbox Code Playgroud)
但它找不到我的方法,也没有自动完成.
我知道我的导入工作正常,因为我能够访问我的其他swift对象.
我开始在视图控制器上编写Swift扩展.所以我现在有三个文件:
我的头文件,ViewController.h:
@interface MyViewController : UIViewController
@end
Run Code Online (Sandbox Code Playgroud)
我的Obj-C实现文件,ViewController.m:
@interface MyViewController () <UIScrollViewDelegate>
@property (strong, nonatomic) UIScrollView *scrollView;
@end
@implementation MyViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.scrollView = [[UIScrollView alloc] init];
[self customiseScrollView]; //This is Swift method called from Obj-C file
}
@end
Run Code Online (Sandbox Code Playgroud)
最后,ViewController.swift:
extension MyViewController {
func customiseScrollView() {
}
}
Run Code Online (Sandbox Code Playgroud)
我的问题是,是否可以从我的Swift实现文件中访问我的Obj-C属性?每次我提到它,我都会收到一个错误:
Value of type 'MyViewController' has no member 'scrollView'
Run Code Online (Sandbox Code Playgroud)
奖励1:有人也可以澄清Swift组件是否能够看到.m是代表的内容.(澄清scrollView.delegate = self一下,在Swift中执行是一个编译错误,因为Swift文件没有意识到.m文件是UIScrollViewDelegate).
Bonus 2:Swift扩展文件可以调用从.m对应方声明的Obj-C方法吗?
我想延长Dictionary与String键(JSON字典),以便与任何下标enum,有一个RawValue类型的String.最终目标是多个enums可用于下标JSON词典的目标.
enum JSONKey: String {
case one, two, three
}
enum OtherJSONKey: String {
case a, b, c
}
if let one = jsonDictionary[.one] { /* ... */ }
if let b = jsonDictionary[.b] { /* ... */ }
Run Code Online (Sandbox Code Playgroud)
但我无法弄清楚如何实现这一点.我知道我需要扩展Dictionary,但无法弄清楚通用扩展约束或方法扩展约束.
我的第一个想法是尝试向下标方法添加通用约束.不过,我认为下标方法不允许使用泛型.
extension Dictionary {
subscript<T: RawRepresentable>(key: T) -> Value? { /* ... */ }
}
Run Code Online (Sandbox Code Playgroud)
即使将泛型约束放在下标上,我仍然需要一种方法来嵌套我的泛型约束.或者将字典约束为基于字符串的枚举的键.要把它放在无效的代码中,我想这样做:
extension Dictionary where Key: RawRepresentable where RawValue == String { …Run Code Online (Sandbox Code Playgroud) 我希望 Swift 使我能够在where块中为具有指定条件的类型创建扩展。我想象我可以使用依赖于具体泛型类型值 ( T) 的不同扩展来扩展相同的泛型类型。但不是。以下示例演示了我的问题:
protocol P {
associatedtype Prop
var property: Prop { get }
}
enum E<T: P> {
case single(T)
case double(T)
}
extension E: P where T.Prop == Int {
var property: Int {
switch self {
case .single(let o): return o.property
case .double(let o): return o.property * 2
}
}
}
extension E: P where T.Prop == String {
var property: String {
switch self {
case .single(let o): return o.property …Run Code Online (Sandbox Code Playgroud) 我正在尝试创建Fabric方法来创建具有正确nib名称的UIViewController(以修复iOS8默认初始化问题).要做到这一点,我添加了扩展名:
extension UIViewController {
class func create() -> Self {
if #available(iOS 9.0, *) {
return self.init()
} else {
let clsName = NSStringFromClass(self).componentsSeparatedByString(".").last!
return self.init(nibName: clsName, bundle: nil)
}
}
}
Run Code Online (Sandbox Code Playgroud)
但编译器发出错误:Cannot convert value of type 'Self.Type' to expected argument type 'AnyClass' (aka 'AnyObject.Type')in NSStringFromClass(self).
要修复它,可以添加另一个扩展方法并将代码重写为:
extension UIViewController {
private class var nibNameForInitializer:String {
return NSStringFromClass(self).componentsSeparatedByString(".").last!
}
class func create_() -> Self {
if #available(iOS 9.0, *) {
return self.init()
} else {
return self.init(nibName: self.nibNameForInitializer, …Run Code Online (Sandbox Code Playgroud) 从Swift 2.2转换为3.0后,我的Array扩展不再编译,因为它包含对全局标准库函数的调用min<T>(T,T)并显示编译器错误extra argument in call.
这是重现错误的简单方法:
extension Array {
func smallestInt(first: Int, second: Int) -> Int {
return min(first, second) // compiler error: "Extra argument in call"
}
}
Run Code Online (Sandbox Code Playgroud)
将相同的函数添加到扩展名时Dictionary,我得到相同的错误,而完全相同的代码在其他类型的扩展中编译得很好(例如String或AudioBuffer):
看着的文件Array和Dictionary,我发现有关于实例方法Sequence命名public func min() -> Element?和public func min(by areInIncreasingOrder: (Element, Element) throws -> Bool) rethrows -> Element?.虽然两者String并AudioBuffer没有任何形式的min(...)功能.
这可能是我无法调用全局函数的原因吗?编译器无法区分全局func min<T>(T,T),self.min(...)尽管它们具有完全不同的签名? …
Swift协议可以通过向它们添加扩展来为函数和计算属性提供默认实现.我做了很多次.我的理解是,默认实现仅用作"后备":当类型符合协议但不提供自己的实现时执行.
至少我是如何阅读Swift编程语言指南的:
如果符合类型提供其自己的必需方法或属性的实现,则将使用该实现而不是扩展提供的实现.
现在我遇到了这样一种情况:我实现特定协议的自定义类型确实为特定函数提供了一个实现,但它没有被执行 - 而是执行协议扩展中定义的实现.
作为示例,我定义了一个Movable具有函数move(to:)和扩展的协议,该协议为此函数提供了一个默认实现:
protocol Movable {
func move(to point: CGPoint)
}
extension Movable {
func move(to point: CGPoint = CGPoint(x: 0, y: 0)) {
print("Moving to origin: \(point)")
}
}
Run Code Online (Sandbox Code Playgroud)
接下来,我定义一个Car符合的类,Movable但为move(to:)函数提供了自己的实现:
class Car: Movable {
func move(to point: CGPoint = CGPoint(x: 0, y: 0)) {
print("Moving to point: \(point)")
}
}
Run Code Online (Sandbox Code Playgroud)
现在我创建一个新的Car并将其向下转换为Movable:
let castedCar = …Run Code Online (Sandbox Code Playgroud) extension-methods protocols swift swift-extensions swift-protocols
是否有特定原因限制我们在protocol声明中提供计算属性?因为我们只有机会将这些计算属性设置extension为protocol.
单词 -> 代码:
为什么这不起作用-(背后的逻辑是什么)
protocol GridableGraph {
var yTick: Float { get }
var yTicksCount: Int { get }
var xTick: Float{ get }
var xTicksCount: Int { get }
var maxYValue: Float { return Float(yTicksCount - 1) * yTick }
var maxXValue: Float { return Float(xTicksCount - 1) * xTick }
}
Run Code Online (Sandbox Code Playgroud)
虽然这确实
protocol GridableGraph {
var yTick: Float { get }
var yTicksCount: Int { get }
var xTick: Float{ get …Run Code Online (Sandbox Code Playgroud) swift ×10
swift-extensions ×10
ios ×3
objective-c ×3
generics ×2
arrays ×1
dictionary ×1
enums ×1
protocols ×1
swift3 ×1
syntax ×1