在 Swift 项目中使用未声明的类型

Posted

技术标签:

【中文标题】在 Swift 项目中使用未声明的类型【英文标题】:Use of undeclared type in Swift project 【发布时间】:2014-07-08 08:55:37 【问题描述】:

我正在尝试在我的 Swift 项目中导入 this library。我从this document 和this answer 一步一步做,但没有任何效果。

这是我的screenshot:

这是我的 Bridging-Header.h:

//
//  Use this file to import your target's public headers that you would like to expose to Swift.
//

#import <UIKit/UIKit.h>

#import "VKUser.h"
#import "VKAccessToken.h"
#import "VKCache.h"
#import "VKStorage.h"
#import "VKStorageItem.h"
#import "VKRequestManager.h"
#import "VKRequest.h"
#import "VKConnector.h"
#import "VKMethods.h"

#import "NSData+toBase64.h"
#import "NSString+Utilities.h"

重要的是我在一个文件中有 VKConnector 类和 VKConnectorDelegate 协议。也许这就是问题所在?

//
// Copyright (c) 2013 Andrew Shmig
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "VKMethods.h"
#import "VKAccessToken.h"
#import "VKStorage.h"
#import "NSString+Utilities.h"
#import "VKStorageItem.h"


@class VKConnector;


static NSString *const kVKErrorDomain = @"kVkontakteErrorDomain";


typedef enum

    kVKApplicationWasDeletedErrorCode
 kVkontakteErrorCode;


/** Protocol incapsulates methods that are triggered during user authorization
 process or access token status changes.
 */
@protocol VKConnectorDelegate <NSObject>

@optional
/**
 @name Show/hide web view
 */
/** Method is called when user needs to perform some action (enter login and
password, authorize your application etc)

@param connector VKConnector instance that sends notifications
@param webView UIWebView that displays authorization page
*/
- (void)VKConnector:(VKConnector *)connector
    willShowWebView:(UIWebView *)webView;

/** Method is called when UIWebView should be hidden, this method is called after
user has entered login+password or has authorized an application (or pressed
cancel button etc).

@param connector VKConnector instance that sends notifications
@param webView UIWebView that displays authorization page and needs to be hidden
*/
- (void)VKConnector:(VKConnector *)connector
    willHideWebView:(UIWebView *)webView;

/**
@name UIWebView started/finished loading a frame
*/
/** Method is called when UIWebView starts loading a frame

@param connector VKConnector instance that sends notifications
@param webView UIWebView that displays authorization page
*/
- (void)VKConnector:(VKConnector *)connector
webViewDidStartLoad:(UIWebView *)webView;

/** Method is called when UIWebView finishes loading a frame

@param connector VKConnector instance that sends notifications
@param webView UIWebView that displays authorization page
*/
- (void) VKConnector:(VKConnector *)connector
webViewDidFinishLoad:(UIWebView *)webView;

/**
 @name Access token
 */
/** Method is called when access token is successfully updated

@param connector VKConnector instance that sends notifications
@param accessToken updated access token
*/
- (void)        VKConnector:(VKConnector *)connector
accessTokenRenewalSucceeded:(VKAccessToken *)accessToken;

/** Method is called when access token failed to be updated. The main reason
could be that user denied/canceled to authorize your application.

@param connector VKConnector instance that sends notifications
@param accessToken access token (equals to nil)
*/
- (void)     VKConnector:(VKConnector *)connector
accessTokenRenewalFailed:(VKAccessToken *)accessToken;

/**
 @name Connection & Parsing
 */
/** Method is called when connection error occurred during authorization process.

@param connector VKConnector instance that sends notifications
@param error error description
*/
- (void)VKConnector:(VKConnector *)connector
    connectionError:(NSError *)error;

/** Method is called if VK application was deleted.

@param connector VKConnector instance that sends notifications
@param error error description
*/
- (void)  VKConnector:(VKConnector *)connector
applicationWasDeleted:(NSError *)error;

@end


/** The main purpose of this class is to process user authorization and obtain
access token which then will be used to perform requests from behalf of current
user.

Example:

    [[VKConnector sharedInstance] startWithAppID:@"12345567"
                                  permissions:@[@"wall"]
                                  webView:webView
                                  delegate:self];
*/
@interface VKConnector : NSObject <UIWebViewDelegate>

/**
@name Properties
*/
/** Delegate
 */
@property (nonatomic, weak, readonly) id <VKConnectorDelegate> delegate;

/** Application's unique identifier
*/
@property (nonatomic, strong, readonly) NSString *appID;

/** Permissions
*/
@property (nonatomic, strong, readonly) NSArray *permissions;

/**
@name Class methods
*/
/** Returns shared instances of VKConnector class.
*/
+ (id)sharedInstance;

/**
@name User authorization
*/
/** Starts user authorization process.

@param appID application's unique identifier
@param permissions array of permissions (wall, friends, audio, video etc)
@param webView UIWebView which will be used to display VK authorization page
@param delegate delegate which will receive notifications
*/
- (void)startWithAppID:(NSString *)appID
            permissons:(NSArray *)permissions
               webView:(UIWebView *)webView
              delegate:(id <VKConnectorDelegate>)delegate;

/**
@name Cookies
*/
/** Removes all cookies which were obtained after user has authorized VK
application. This method is used to log out current user.
*/
- (void)clearCookies;

@end

我曾尝试将 VKConnector 头文件拆分为两个 - VKConnector 类和 VKConnectorDelegate,但这不起作用。

我做错了什么?

【问题讨论】:

您是否将所需的标头 (VkontakteSDK.h) 导入到 swift 桥接头中? 检查桥接头。 @Anil,是的,我已经导入了 VkontakteSDK.h 但它没有用,之后我尝试导入在 VkontakteSDK.h 头文件中导入的所有头文件 - 没有... 专门查找桥接头。听起来你设置得不对,还请观看关于 swift & Objective C 的 WWDC 会议 与这个问题完全无关,但你应该放弃你的 base64 库,转而支持Apple's base64 methods,因为它们已经被公开了。 【参考方案1】:

您的委托函数名称是VKConnector,并且您还有一个名为VKConnector 的类。那是你的冲突。在 Objective C 中,您的委托方法是 VKConnector:withBool:,但在 Swift 中,它只是 VKConnector,并且 withBool 不是名称的一部分。

如果你遵循 Cocoa 模式,你的委托方法应该被称为- (void) connector:(VKConnector *)connector withBool:(BOOL)boolean;

【讨论】:

但我没有使用除 UIKit 和 Foundation 之外的任何其他框架。为什么它在 ObjC 项目中有效,而在 Swift 项目中无效? 好的,假设我没有某些库的源代码。我怎么能在 Swift 项目中使用我向您展示的(在测试项目和 SDK 中)编写的 ObjC 代码?谢谢你的帮助,真的很有道理。需要考虑一下。 好吧,命名委托方法的约定背后的想法是对象正在做某事而不是类。你不会看到像UITableView:numberOfRowsInSection: 这样的东西,因为numberOfRowsInSectionUITableView 的实例不会响应类,所以方法是tableView:numberofRowsInSection: 我认为如果你没有库的源代码并且有这个问题,也许你可以创建一个目标 c 类来使用委托,并像“桥梁”一样快速使用这个类 这正是我的问题。感谢您的帮助!【参考方案2】:

你的桥接头文件是 XCode 创建的还是你自己创建的?

如果您自己创建了桥接头文件,请确保构建设置指向您的文件:

【讨论】:

请再次阅读我的问题。有两个链接:来自 docs 和来自 SO,当然我已经在我的项目中添加了该设置(我自己和 XCode 也) 你提醒我需要在我的桥接文件中添加一个导入 - 解决了 :)【参考方案3】:

混合项目中的“未声明类型”错误几乎总能得到解决,正如我在这里解释的那样:

https://***.com/a/24216718/341994

基本上,无论您将自动生成的 "...-Swift.h" 头文件导入到 Objective-C 代码中的何处,您都需要将 "VKConnector.h" 导入该文件中,在导入列表的前面.

这是违反直觉且令人讨厌的,但它解决了问题,如果仔细观察,实际上它实际上已记录在案。

【讨论】:

谢谢,但它不起作用:(我什至在 Apple Dev 论坛上创建了这个主题:devforums.apple.com/message/1002447 和测试项目 (yadi.sk/d/QxPhrnysWFDGt),你可以看到它不起作用。 【参考方案4】:

如果它对任何人有帮助,那么在我们的项目中,这个问题是因为我们在主项目目标上有一个桥接头,而在扩展目标上有一个桥接头。

我们的扩展目标正在使用我们主项目中定义的类。这个类是在扩展桥接头中定义的,并且适用于我们的大多数类。

但是,当我们将其中一个类的目标成员资格授予主项目目标时,我们在该单个文件中收到此错误。修复是为了确保使用的文件在两个桥接头文件中。

【讨论】:

我有同样的情况,两个目标并试图将我的 Objective-C 项目导入另一个目标,即 Swift 类。你能解释一下吗,也许它会解决我的问题..

以上是关于在 Swift 项目中使用未声明的类型的主要内容,如果未能解决你的问题,请参考以下文章

Objective-C 库的 Swift “使用未声明的类型”

Objective-C 库的 Swift “使用未声明的类型”

升级到 Swift 3 时使用未声明的类型

在 Swift 中声明任何类型的数组时使用未声明的类型“T”

使用未声明的类型“JSONDictionary”

当我想在目标 c 项目中使用 swift 文件时使用未声明的标识符