我的好奇心促使我将View类型作为参数传递给@ViewBuilder. 将模型/基元类型作为参数传递@ViewBuilder是完全有效的。
如下代码所示。
struct TestView<Content: View>: View {
let content: (String) -> Content
init(@ViewBuilder content: @escaping (String) -> Content) {
self.content = content
}
var body: some View {
content("Some text")
}
}
struct ContentTestView: View {
var body: some View {
TestView {
Text("\($0)")
}
}
}
Run Code Online (Sandbox Code Playgroud)
代替String在
let content: (String) -> Content
Run Code Online (Sandbox Code Playgroud)
如果我尝试传递 SwiftUIView类型,则编译器对此不满意。
let content: (View) -> Content
Run Code Online (Sandbox Code Playgroud)
尽管 params for@ViewBuilder接受自定义协议类型Searchable,但不接受View协议。 …
A类提供字符串值.B类本身有两个A类成员,并提供计算属性"v"来选择其中一个.
class A {
var value: String
init(value: String) {
self.value = value
}
}
class B {
var v1: A?
var v2: A = A(value: "2")
private var v: A {
return v1 ?? v2
}
var value: String {
get {
return v.value
}
set {
v.value = newValue
}
}
}
Run Code Online (Sandbox Code Playgroud)
这段代码很简单,很有效.由于A和B都有一个成员"值",我把它作为这样的协议:
protocol ValueProvider {
var value: String {get set}
}
class A: ValueProvider {
var value: String
init(value: String) {
self.value = value
}
}
class …Run Code Online (Sandbox Code Playgroud) 我想创建协议,当它们符合此协议时,它将使我能够向UIViewController及其子类添加活动指示符/从UIViewController及其子类中移除活动指示符。
所以我最终得到了这样的代码
protocol ActivityIndicatorPresenter {
var activityIndicator: UIActivityIndicatorView { get }
func showActivityIndicator()
func hideActivityIndicator()
}
extension ActivityIndicatorPresenter where Self: UIViewController {
func showActivityIndicator() {
dispatch_async(dispatch_get_main_queue()) {
self.activityIndicator.color = UIColor.blackColor()
self.activityIndicator.frame = CGRect(x: 0.0, y: 0.0, width: 80.0, height: 80.0)
self.activityIndicator.center = CGPoint(x:self.view.bounds.size.width / 2, y:self.view.bounds.size.height / 2)
self.view.addSubview(self.activityIndicator)
self.activityIndicator.startAnimating()
}
}
func hideActivityIndicator() {
dispatch_async(dispatch_get_main_queue()) {
self.activityIndicator.stopAnimating()
self.activityIndicator.removeFromSuperview()
}
}
}
Run Code Online (Sandbox Code Playgroud)
并在UIViewController的子类中:
class MyViewController: ActivityIndicatorPresenter {
var activityIndicator: UIActivityIndicator { get {return self.spinner}}
var spinner = UIActivityIndicator()
}
Run Code Online (Sandbox Code Playgroud)
一切正常,但我认为在计算属性的getter中返回存储的属性是一种解决方法。是更漂亮的实现方式吗?
考虑两种私有方法UIColor:
styleString返回颜色的RGB字符串的实例方法_systemDestructiveTintColor返回破坏性按钮使用的红色的类方法.例如方法,我可以创建一个@objc协议并用于unsafeBitCast公开私有方法:
@objc protocol UIColorPrivate {
func styleString() -> UIColor
}
let white = UIColor.whiteColor()
let whitePrivate = unsafeBitCast(white, UIColorPrivate.self)
whitePrivate.styleString() // rgb(255,255,255)
Run Code Online (Sandbox Code Playgroud)
但是,我不确定这对于类方法是如何工作的.
第一次尝试:
@objc protocol UIColorPrivate {
class func _systemDestructiveTintColor() -> String // Error: Class methods are only allowed within classes
}
Run Code Online (Sandbox Code Playgroud)
有道理,我会把它改成static:
@objc protocol UIColorPrivate {
static func _systemDestructiveTintColor() -> String
}
let colorClass = UIColor.self
let privateClass = unsafeBitCast(colorClass, UIColorPrivate.self) // EXC_BAD_ACCESS
Run Code Online (Sandbox Code Playgroud)
这会导致崩溃.好吧,这无处可去.我可以使用桥接头,只是将类方法公开为 …
刚开始在面向协议的协议编程之后迅速工作,我面临着使用计算变量的问题。
我已经制定了一个协议来检查整个应用程序上的Internet可达性(而不是使用已经实现的UIVIewController子类来实现此行为)。但是,当我运行应用程序时,计算变量()的访问集属性崩溃:

这是代码:
import UIKit
protocol ReachabilityProtocol: class {
var reachability: NetReach? { get set }
func startReachability()
func stopReachability()
func internetIsAccessible()
func internetIsNotAccessible()
}
extension ReachabilityProtocol where Self: UIViewController {
var reachability: NetReach? {
get { return reachability }
set { reachability = newValue }
}
func startReachability() {
do {
reachability = try NetReach.reachabilityForInternetConnection()
} catch {
print("Unable to create Reachability")
return
}
NSNotificationCenter.defaultCenter().addObserverForName(ReachabilityChangedNotification, object: reachability, queue: nil, usingBlock: { notification in
let reachable = notification.object as! NetReach …Run Code Online (Sandbox Code Playgroud) 我写了一个包含基本资产数据的结构:
struct Asset: AssetProtocol {
init (id: Int = 0, url: String) {
self.id = id
self.url = URL(string: url)
}
var id: Int
var url: URL?
}
Run Code Online (Sandbox Code Playgroud)
它订阅 AssetProtocol
protocol AssetProtocol {
var id: Int { get }
var url: URL? { get }
}
Run Code Online (Sandbox Code Playgroud)
我希望扩展Array(Sequence),其中该Array中的元素是订阅AssetProtocol的项目.此外,这些函数能够在适当的位置改变数组.
extension Sequence where Iterator.Element: AssetProtocol {
mutating func appendUpdateExclusive(element newAsset: Asset) {
...
Run Code Online (Sandbox Code Playgroud)
我怎样才能迭代并改变这个序列?我已经尝试了六种方法,似乎无法做到正确!
假设存在一个通用结构:
public struct Matrix<T> where T: FloatingPoint, T: ExpressibleByFloatLiteral {
// some methods...
}
Run Code Online (Sandbox Code Playgroud)
是否可以扩展struct以符合约束T使用where子句的协议?比如像
extension Matrix where T: SpecificClass : SomeProtocol {
// This does not compile :(
}
Run Code Online (Sandbox Code Playgroud) 我正在尝试创建UIViewController可用于初始化新实例的扩展。对于项目中的每个视图控制器,我都有一个相应的情节提要。
即
EditSomethingViewController.swift
EditSomethingViewController.storyboard
Run Code Online (Sandbox Code Playgroud)
这是我到目前为止的内容:
extension UIViewController {
static func initalize() -> UIViewController? {
let name = String(self)
let storyboard = UIStoryboard(name: name, bundle: nil)
return storyboard.instantiateInitialViewController()
}
}
Run Code Online (Sandbox Code Playgroud)
但是,这意味着当我使用它时,我仍然必须强制转换响应。
即
if let viewController = EditSomethingViewController.initalize() as? EditSomethingViewController {
// do something with view controller here
}
Run Code Online (Sandbox Code Playgroud)
是否可以通过这种方式创建扩展名,这意味着我不必强制响应?
ps在一个用Swift 2.3编写的旧项目上工作,将不胜感激所支持的答案。
我的项目中有几个不同的枚举,符合相同的协议.compareEnumType协议中的方法比较忽略关联值的枚举案例.这是我在游乐场的代码:
protocol EquatableEnumType {
static func compareEnumType(lhs: Self, rhs: Self) -> Bool
}
enum MyEnum: EquatableEnumType {
case A(Int)
case B
static func compareEnumType(lhs: MyEnum, rhs: MyEnum) -> Bool {
switch (lhs, rhs) {
case (.A, .A): return true
case (.B, .B): return true
default: return false
}
}
}
enum MyEnum2: EquatableEnumType {
case X(String)
case Y
static func compareEnumType(lhs: MyEnum2, rhs: MyEnum2) -> Bool {
switch (lhs, rhs) {
case (.X, .X): return true
case (.Y, …Run Code Online (Sandbox Code Playgroud) 我习惯使用扩展在协议内部使用默认参数,因为协议声明本身不能使用它们,如下所示:
protocol Controller {
func fetch(forPredicate predicate: NSPredicate?)
}
extension Controller {
func fetch(forPredicate predicate: NSPredicate? = nil) {
return fetch(forPredicate: nil)
}
}
Run Code Online (Sandbox Code Playgroud)
为我工作完美.
现在我有下一个情况,我有一个特定类型的控制器的特定协议:
protocol SomeSpecificDatabaseControllerProtocol {
//...
func count(forPredicate predicate: NSPredicate?) -> Int
}
Run Code Online (Sandbox Code Playgroud)
和协议扩展以及控制器的默认方法的实现:
protocol DatabaseControllerProtocol {
associatedtype Entity: NSManagedObject
func defaultFetchRequest() -> NSFetchRequest<Entity>
var context: NSManagedObjectContext { get }
}
extension DatabaseControllerProtocol {
func save() {
...
}
func get() -> [Entity] {
...
}
func count(forPredicate predicate: NSPredicate?) -> Int {
...
}
//..... …Run Code Online (Sandbox Code Playgroud) swift-protocols ×10
swift ×9
ios ×5
generics ×2
afnetworking ×1
arrays ×1
enums ×1
objective-c ×1
properties ×1
sequence ×1
struct ×1
swift3 ×1
swift4 ×1
swiftui ×1
uicolor ×1
viewbuilder ×1
xcode ×1