GVKun编程网logo

如何创建符合Swift和Objective-C之间共享协议的类方法?(swift创建对象)

10

如果您对如何创建符合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创建对象)

如何创建符合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代码添加了“可空性注释”。

新引入的两个关键字是nullablenonnull。它们在为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中的协议

ios – NSManagedObject无法符合Swift中的协议

我需要一个NSManagedobject和一个常规NSObject的共享接口.在 Objective-c中,我可以使用协议来实现这一目标.但是在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协议 – 显示不符合错误

ios – Swift中的Objective-C协议 – 显示不符合错误

我正在尝试在我的 Swift应用程序中使用Objective-C库(MWPhotobrowser).我的Swift类通过实现所需的方法符合MWPhotobrowserDelegate协议.但是,我不断收到以下错误:

“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

解决方法

我使用以下代码在我的Swift应用程序中使用MWPhotobrowser,而无需更改MWPhotobrowser代码库.

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”头没有找到

ios – Xcode 8与混合Swift和Objective-c项目生成的“ModuleName-Swift.h”头没有找到

我在Xcode 8中有一个使用混合Swift和Objective-C的项目,它使用生成的“ModuleName-Swift.h”头文件将swift导入到Objective-c类中,但预处理器不能找到生成的头文件并抛出导入错误.

“词汇或预处理器问题:’ModuleName-Swift.h文件未找到’”

enter image description here

该项目编译很好,但是预处理器会为头部找不到错误,并且对于类中调用的任何Swift类,都没有语法突出显示或代码完成.这是一个使用Xcode 8无法识别的Objective-c中的Swift类的工作,但是编译也很好.

关于如何安抚Xcode 8中的预处理器的任何想法?

解决方法

我有完全一样的问题.在添加一个仅仅一个目标(错误)的新文件之后找到解决方案,并注意到读取Swift类没有问题.所以,如果你有多个目标,并且由于迁移你没有必要构建和运行它们,建议你这样做.

ios – 使swift类符合定义属性的objective c协议

ios – 使swift类符合定义属性的objective c协议

我无法使快速类符合目标c协议.在 swift中很容易在目标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)作为前缀,以使它们只读,但这些变体都不起作用.

解决方法

找到解决方案,在Swift中你不应该使用Nsstring,而是使用String类型.
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协议的相关知识,请在本站搜索。

本文标签: