Why am I getting an undeclared type 'PubNub' compiler error with Swift Cocoa App and bridging header?
Asked Answered
D

1

12

I am starting a new Cocoa Swift Project that is incorporating the PubNub SDK via CocoaPods with the following Podfile:

target 'myProject' do
source 'https://github.com/CocoaPods/Specs.git'
use_frameworks!
pod 'PubNub', '~>4.0'
pod 'Alamofire', '~> 1.3'
end
target 'myProjectTests' do
end

In my auto-generated bridging header I have the import for PubNub as:

#import <PubNub/PubNub.h>

And my AppDelegate.swift file:

import Cocoa

@NSApplicationMain


class AppDelegate: NSObject, NSApplicationDelegate {

var client:PubNub?

   func applicationDidFinishLaunching(aNotification: NSNotification) {
    let config = PNConfiguration( publishKey: "Your_Pub_Key", subscribeKey:     "Your_Sub_Key")

    client = PubNub.clientWithConfiguration(config)

    client?.addListener(self)

    client?.subscribeToChannels(["Your_Channel"], withPresence: false)

    client?.publish("Swift + PubNub!", toChannel: "demo", compressed: false, withCompletion: nil)    }

func client(client: PubNub!, didReceiveMessage message: PNMessageResult!) {
    println(message)
}

func applicationWillTerminate(aNotification: NSNotification) {
    // Insert code here to tear down your application
}


}

The project fails to build due to compiler errors on use of undeclared type PubNub. I've checked the build settings and the Swift Compiler - Code Generation section shows it's pointed to the bridging header file of the target (auto-populated).

Using Xcode 6.4 and pods version 0.38.2

Dramatize answered 26/7, 2015 at 22:3 Comment(3)
Please contact [email protected] and we can offer you more direct help with this issue.Clothespress
I prefer dealing directly with people when they post a question that does not contain enough information to answer. Plus this Podfile does not follow the syntax specified on Cocoapods docs pagesClothespress
Ah, apparently if you include "use_frameworks!" then you'll be ok, though it's not clearly documented innerexception.com/2015/05/…Clothespress
S
15

No Bridging-Header when Importing External Frameworks

Straight from Apple Developer Documentation:

You can import external frameworks that have a pure Objective-C codebase, a pure Swift codebase, or a mixed-language codebase. [...] You can import a framework into any Swift file within a different target using the following syntax:

import FrameworkName

Fix

Add import PubNub framework.

import UIKit
import PubNub

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    var client:PubNub?
    // ...
}

With a single import, PubNub is declared, auto-completes in Xcode editor, compiles, links, builds and runs.


Step-by-step Swift Framework Tutorial

Since many comments below imply that Bridging-Headers are always required, wrongly so when using External Frameworks as is presently the case with the use_frameworks! directive in the Podfile, find here a pure Swift solution. It is followed by an Xcode project you can download and experience with.

Unambiguously documented in the iOS Developer Library, in concept Using Swift with Cocoa and Objective-C, chapter Mix and Match, section Swift and Objective-C in the Same Project, paragraph Importing External Frameworks:

The process for importing an external framework is the same whether the framework is written in a single language or contains files from both languages.

Podfile

platform :ios, '8.0'
use_frameworks!

target 'SO-31642385' do
pod 'PubNub', '~>4.0'
pod 'Alamofire', '~> 1.3'
end

Install the pods

] pod install

Downloading dependencies
Installing Alamofire (1.3.1)
Installing CocoaLumberjack (2.0.0)
Installing PubNub (4.0.4)
Generating Pods project
Integrating client project

Please close any current Xcode sessions and use `SO-31642385.xcworkspace` for this project from now on.

Import Framework

import UIKit
import PubNub

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    var client:PubNub?

    func application(_ application: UIApplication,
                     didFinishLaunchingWithOptions launchOptions:
                         [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

        self.client = PubNub()
        return true
    }
    // ...
}

► Find this solution on GitHub and additional details on Swift Recipes.

Sabbatarian answered 28/7, 2015 at 5:33 Comment(5)
That's unnecessary if you are using the bridging header correctly.Clothespress
Please take a look at this project: github.com/jzucker2/StackOverflowSwiftBridgingHeader/tree/… It does not import PubNub because it is included in the bridging header. Please feel free to consult Apple docs if you need more info on how this works, there's always more to learn.Clothespress
"Any public Objective-C headers listed in this bridging header file will be visible to Swift. The Objective-C functionality will be available in any Swift file within that target automatically, without any import statements. Use your custom Objective-C code with the same Swift syntax you use with system classes." SourceClothespress
@Clothespress - please consider posting your comments as an answer so we can up vote or Jim Hankins can accept as answer.Beanery
It is the other way around. Bridging Headers are unnecessary if using Frameworks correctly. ` Pubnub` is a Framework. It is included with use_frameworks!. Just add import PubNub and bypass the bridge mechanism entirely.Sabbatarian

© 2022 - 2024 — McMap. All rights reserved.