如果您对如何创建符合Swift和Objective-C之间共享协议的类方法?和swift创建对象感兴趣,那么这篇文章一定是您不可错过的。我们将详细讲解如何创建符合Swift和Objective-C之间
如果您对如何创建符合Swift和Objective-C之间共享协议的类方法?和swift创建对象感兴趣,那么这篇文章一定是您不可错过的。我们将详细讲解如何创建符合Swift和Objective-C之间共享协议的类方法?的各种细节,并对swift创建对象进行深入的分析,此外还有关于ios – NSManagedObject无法符合Swift中的协议、ios – Swift中的Objective-C协议 – 显示不符合错误、ios – Xcode 8与混合Swift和Objective-c项目生成的“ModuleName-Swift.h”头没有找到、ios – 使swift类符合定义属性的objective c协议的实用技巧。
本文目录一览:- 如何创建符合Swift和Objective-C之间共享协议的类方法?(swift创建对象)
- ios – NSManagedObject无法符合Swift中的协议
- ios – Swift中的Objective-C协议 – 显示不符合错误
- ios – Xcode 8与混合Swift和Objective-c项目生成的“ModuleName-Swift.h”头没有找到
- ios – 使swift类符合定义属性的objective c协议
如何创建符合Swift和Objective-C之间共享协议的类方法?(swift创建对象)
我最近一直在学习Swift。
我决定编写一个混合的Swift / Objective-C应用程序,该应用程序使用两种语言实现的相同算法来完成计算密集型任务。
该程序将计算大量的质数。
我定义了一个计算对象的Swift版本和Objective-C版本都应该遵守的协议。
这些对象都是单例,因此我在Objective-C中创建了一个典型的单例访问方法:
+ (NSObject <CalcPrimesProtocol> *) sharedInstance;
整个协议如下所示:
#import <Foundation/Foundation.h>@class ComputeRecord;typedef void (^updateDisplayBlock)(void);typedef void (^calcPrimesCompletionBlock)(void); @protocol CalcPrimesProtocol <NSObject>- (void) calcPrimesWithComputeRecord: (ComputeRecord *) aComputeRecord withUpdateDisplayBlock: (updateDisplayBlock) theUpdateDisplayBlock andCompletionBlock: (calcPrimesCompletionBlock) theCalcPrimesCompletionBlock; @optional //Without this @optional line, the build fails. + (NSObject <CalcPrimesProtocol> *) sharedInstance; @end
该类的Objective-C版本完全实现上述定义的方法,无需担心。
快速版本有一个方法:
class func sharedInstance() -> CalcPrimesProtocol
但是,如果将该方法作为协议的必需方法,则会出现编译器错误“类型” CalcPrimesSwift不符合协议“ CalcPrimesProtocol”。
但是,如果我在协议中将单例类方法sharedInstance标记为可选,那么它将起作用,并且可以在我的Swift类或Objective-C类上调用该方法。
我在Swift类方法的定义中是否错过了一些微妙之处?考虑到我能够在Swift类或Objective-
C类上调用sharedInstance()类方法,这似乎不太可能。
您可以从Github下载该项目,然后查看是否需要。它称为
SwiftPerformanceBenchmark
。(链接)
答案1
小编典典在Objective-C中,我们总是在传递指针,而指针始终可以是nil
。Objective-
C的程序员很多利用的事实,将消息发送给nil
什么也没做,返回0
/ nil
/NO
。Swift的处理方式nil
完全不同。对象要么存在(从不存在nil
),要么不知道它们是否存在(这是Swift可选对象起作用的地方)。
因此,在Xcode 6.3之前,这意味着任何使用Objective-
C代码的Swift代码都必须将所有对象引用视为Swift可选对象。关于Objective-C的语言规则,并没有阻止对象指针成为nil
。
使用Swift的Objective-C协议,类等意味着什么,这是一个很大的混乱。我们必须选择非完美的解决方案。
给定以下Objective-C协议:
@protocol ObjCProtocol <NSObject>@required + (id<ObjCProtocol>)classMethod;@required - (id<ObjCProtocol>)instanceMethod;@required - (void)methodWithArgs:(NSObject *)args;@end
我们可以接受方法定义为包含隐式解包的可选内容:
class MyClass: NSObject, ObjCProtocol { func methodWithArgs(args: NSObject!) { // do stuff with args }}
这样可以使生成的代码更干净(我们永远不必在体内拆包),但是,我们始终会面临“发现nil的同时拆开可选包装”错误的风险。
或者,我们可以将方法定义为真正的可选方法:
class MyClass: NSObject, ObjCProtocol { func methodWithArgs(args: NSObject?) { // unwrap do stuff with args }}
但这给我们留下了很多混乱的代码。
Xcode 6.3解决了此问题,并为Objective-C代码添加了“可空性注释”。
新引入的两个关键字是nullable
和nonnull
。它们在为Objective-C代码声明返回类型或参数类型的地方使用。
- (void)methodThatTakesNullableOrOptionalTypeParameter:(nullable NSObject *)parameter;- (void)methodThatTakesNonnullNonOptionalTypeParameter:(nonnull NSObject *)parameter;- (nullable NSObject *)methodReturningNullableOptionalValue;- (nonnull NSObject *)methodReturningNonNullNonOptionalValue;
除了这两个注释关键字之外,Xcode 6.3还引入了一组宏,这些宏使将Objective-
C代码的大部分内容标记为容易nonnull
(完全不带注释的文件被假定为nullable
)。为此,我们NS_ASSUME_NONNULL_BEGIN
在本节的顶部和NS_ASSUME_NONNULL_END
我们要标记的底部使用。
因此,例如,我们可以将整个协议包装在该宏对中。
NS_ASSUME_NONNULL_BEGIN@protocol CalcPrimesProtocol <NSObject>- (void) calcPrimesWithComputeRecord: (ComputeRecord *) aComputeRecord withUpdateDisplayBlock: (updateDisplayBlock) theUpdateDisplayBlock andCompletionBlock: (calcPrimesCompletionBlock) theCalcPrimesCompletionBlock;+ (id <CalcPrimesProtocol> ) sharedInstance;@endNS_ASSUME_NONNULL_END
这与将所有指针参数和返回类型标记为的效果相同nonnull
(有一些例外,如Apple的Swift博客中的此项记为)。
Xcode 6.3之前的版本
符合Objective-C协议的Swift类必须将该协议中的所有Objective-C类型都视为可选。
为了弄清楚这一点,我创建了以下Objective-C协议:
@protocol ObjCProtocol <NSObject>@required + (id<ObjCProtocol>)classMethod;@required - (id<ObjCProtocol>)instanceMethod;@required - (void)methodWithArgs:(NSObject *)args;@end
然后,创建一个Swift类,该类继承自NSObject
并且声明自己与this兼容ObjCProtocol
。
然后,我继续键入这些方法名称,并让Swift为我自动完成方法,这就是我所得到的(我放入方法主体中,其余的则为自动完成):
class ASwiftClass : NSObject, ObjCProtocol { class func classMethod() -> ObjCProtocol! { return nil } func instanceMethod() -> ObjCProtocol! { return nil } func methodWithArgs(args: NSObject!) { // do stuff }}
现在,如果需要,我们可以使用常规的可选选项(带有?
)来代替这些自动解包的可选选项。编译器完全满意。关键是,尽管我们必须考虑使用的可能性nil
,因为无法阻止Objective-
C协议的nil
通过。
如果此协议是在Swift中实现的,我们将选择返回类型是否为可选,而Swift将阻止我们返回nil
未定义非可选返回类型的方法。
ios – NSManagedObject无法符合Swift中的协议
协议产品{
var code:String {get set}
var sp:String {get set}
}
class Stock: NSManagedobject,Product { @NSManaged var code: String @NSManaged var sp: String
}
错误:架构i386的未定义符号:
“__TFC11YellowPages5Stockg2spSS”,引自:
Stock.o中的__TFC11YellowPages5Stockm2spSS
“__TFC11YellowPages5Stockg4codeSS”,引自:
Stock.o中的__TFC11YellowPages5Stockm4codeSS
ld:找不到架构i386的符号
clang:错误:链接器命令失败,退出代码为1(使用-v查看调用)
解决方法
class MyEntity: NSManagedobject { @NSManaged var testAttribute: String } @objc protocol MyProtocol { var testAttribute: String { get set } } extension MyEntity: MyProtocol { } class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() let appDelegate = UIApplication.sharedApplication().delegate as AppDelegate let myContext = appDelegate.managedobjectContext! let entity: MyEntity = NSEntityDescription.insertNewObjectForEntityForName("MyEntity",inManagedobjectContext: myContext) as MyEntity foo(entity) println(entity.testAttribute) } func foo(var object: MyProtocol) { object.testAttribute = "bar" } }
下面也有用,但我认为以上是更好的方法:
@objc protocol MyProtocol { var testAttribute: String { get set } } class MyEntity: NSManagedobject,MyProtocol { @NSManaged var testAttribute: String } class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() let appDelegate = UIApplication.sharedApplication().delegate as AppDelegate let myContext = appDelegate.managedobjectContext! let entity: MyEntity = NSEntityDescription.insertNewObjectForEntityForName("MyEntity",inManagedobjectContext: myContext) as MyEntity foo(entity) println(entity.testAttribute) } func foo(var object: MyProtocol) { object.testAttribute = "bar" } }
ios – Swift中的Objective-C协议 – 显示不符合错误
“Type’PhotoLibrary’不符合协议’MWPhotobrowserDelegate’”
Cocoa协议似乎工作正常.有没有人遇到过这个问题?
以下是示例代码:
class PhotoLibrary: UIImageView,MWPhotobrowserDelegate { init() { super.init(frame: CGRectZero) } func numberOfPhotosInPhotobrowser(photobrowser: MWPhotobrowser!) -> Int { return 0 } func photobrowser(photobrowser: MWPhotobrowser!,photoAtIndex index: Int) -> MWPhoto! { return nil } }
协议定义如下:
@protocol MWPhotobrowserDelegate <NSObject> - (NSInteger)numberOfPhotosInPhotobrowser:(MWPhotobrowser *)photobrowser; - (id <MWPhoto>)photobrowser:(MWPhotobrowser *)photobrowser photoAtIndex:(NSInteger)index; @optional - (id <MWPhoto>)photobrowser:(MWPhotobrowser *)photobrowser thumbPhotoAtIndex:(NSUInteger)index; - (MWCaptionView *)photobrowser:(MWPhotobrowser *)photobrowser captionViewForPhotoAtIndex:(NSUInteger)index; - (Nsstring *)photobrowser:(MWPhotobrowser *)photobrowser titleForPhotoAtIndex:(NSUInteger)index; - (void)photobrowser:(MWPhotobrowser *)photobrowser diddisplayPhotoAtIndex:(NSUInteger)index; - (void)photobrowser:(MWPhotobrowser *)photobrowser actionButtonpressedForPhotoAtIndex:(NSUInteger)index; - (BOOL)photobrowser:(MWPhotobrowser *)photobrowser isPhotoSelectedAtIndex:(NSUInteger)index; - (void)photobrowser:(MWPhotobrowser *)photobrowser photoAtIndex:(NSUInteger)index selectedChanged:(BOOL)selected; - (void)photobrowserDidFinishModalPresentation:(MWPhotobrowser *)photobrowser; @end
解决方法
func showFullScreenImage(image:UIImage) { let photo:MWPhoto = MWPhoto(image:image) self.photos = [photo] let browser:MWPhotobrowser = MWPhotobrowser(delegate: self) browser.displayActionButton = true browser.displayNavArrows = false browser.displaySelectionButtons = false browser.zoomPhotosToFill = true browser.alwaysShowControls = false browser.enableGrid = false browser.startOnGrid = false browser.enableSwipetodismiss = true browser.setCurrentPhotoIndex(0) self.navigationController?.pushViewController(browser,animated: true) } func numberOfPhotosInPhotobrowser(photobrowser: MWPhotobrowser!) -> UInt { return UInt(self.photos.count) } func photobrowser(photobrowser: MWPhotobrowser!,photoAtIndex index: UInt) -> MWPhotoProtocol! { if Int(index) < self.photos.count { return photos.objectAtIndex(Int(index)) as! MWPhoto } return nil } func photobrowserDidFinishModalPresentation(photobrowser:MWPhotobrowser) { self.dismissViewControllerAnimated(true,completion:nil) }
我将照片设置为类var,例如private var photos = [],并在我的应用程序的Bridging-Header.h文件中添加了以下导入:
#import <MWPhotobrowser/MWPhoto.h> #import <MWPhotobrowser/MWPhotobrowser.h>
我从https://github.com/mwaterfall/MWPhotoBrowser/issues/325#issuecomment-64781477获得了上面的大部分代码.
ios – Xcode 8与混合Swift和Objective-c项目生成的“ModuleName-Swift.h”头没有找到
“词汇或预处理器问题:’ModuleName-Swift.h文件未找到’”
该项目编译很好,但是预处理器会为头部找不到错误,并且对于类中调用的任何Swift类,都没有语法突出显示或代码完成.这是一个使用Xcode 8无法识别的Objective-c中的Swift类的工作,但是编译也很好.
关于如何安抚Xcode 8中的预处理器的任何想法?
解决方法
ios – 使swift类符合定义属性的objective c协议
协议是
@protocol ATLParticipant <NSObject> @property (nonatomic,readonly) Nsstring *firstName; @property (nonatomic,readonly) Nsstring *lastName; @property (nonatomic,readonly) Nsstring *fullName; @property (nonatomic,readonly) Nsstring *participantIdentifier; @end
我已经制作了这个应该符合它的快速类,但是Xcode说它没有.
class ConversationParticipant: NSObject,ATLParticipant { var firstName: Nsstring? var lastName: Nsstring? var fullName: Nsstring? var participantIdentifier: Nsstring? override init() { super.init() } }
我已经尝试使成员变量可选(如上所述),并解包,并使用private(set)作为前缀,以使它们只读,但这些变体都不起作用.
解决方法
class ConversationParticipant: NSObject,ATLParticipant { var firstName: String! var lastName: String! var fullName: String! var participantIdentifier: String! var avatarImage: UIImage! override init() { super.init() } }
今天关于如何创建符合Swift和Objective-C之间共享协议的类方法?和swift创建对象的讲解已经结束,谢谢您的阅读,如果想了解更多关于ios – NSManagedObject无法符合Swift中的协议、ios – Swift中的Objective-C协议 – 显示不符合错误、ios – Xcode 8与混合Swift和Objective-c项目生成的“ModuleName-Swift.h”头没有找到、ios – 使swift类符合定义属性的objective c协议的相关知识,请在本站搜索。
本文标签: