在Swift 3中无法调用非函数类型'UICollectionView'的值

时间:2021-12-19 18:03:51

Intended Outcome

预期结果

A generic private method for creating tabbbar icons in a custom tabbar controller. Should successfully paint the tabbar icons for each indicated controller.

用于在自定义tabbar控制器中创建tabbbar图标的通用私有方法。应成功绘制每个指示控制器的标签栏图标。

Result

结果

Fails with

失败了

Cannot Call Value of Non-Function Type 'UICollectionView'

无法调用非函数类型'UICollectionView'的值

Failing (Generic) Code:

失败(通用)代码:

private func createNavController(imageName: String, _ controllerName: UICollectionViewController) -> UINavigationController {

               let layout = UICollectionViewFlowLayout()
Thrown Here->  let viewController = controllerName(collectionViewLayout: layout)
               let navController = UINavigationController(rootViewController: viewController)
               navController.tabBarItem.image = UIImage(named: imageName)

               return navController


       }

Working (non-generic) Code

工作(非通用)代码

 let userLayout = UICollectionViewFlowLayout()
let userController = UserController(collectionViewLayout: userLayout)
let navController = UINavigationController(rootViewController: userController)
navController.tabBarItem.image = UIImage(named: "loc-map-route")

Related

有关

class UserController : UICollectionViewController, UICollectionViewDelegateFlowLayout
{
    override func viewDidLoad() {
        super.viewDidLoad()

        collectionView?.backgroundColor = UIColor.green

    }
}

Environment

环境

ios 10 swift 3 xcode 8

ios 10 swift 3 xcode 8

Thanks.

谢谢。

3 个解决方案

#1


1  

In your definition of createNavController your parameter controllerName is of type UICollectionViewController and that is not a function type so you cannot call it as a function, i.e. controllerName(...).

在createNavController的定义中,参数controllerName的类型为UICollectionViewController,它不是函数类型,因此您不能将其称为函数,即controllerName(...)。

If you replace

如果你更换

let viewController = controllerName(collectionViewLayout: layout)

with

let viewController = UserController(collectionViewLayout: layout)

from your working code, it compiles fine. Also, you don't need the controllerName parameter anymore. I don't quite understand what this is for anyway. Did you want to be able to specify the controller type? Then you could do it like dan suggests (although this code requires a UICollectionViewController because you would be using init(collectionViewLayout:)).

从您的工作代码,它编译好。此外,您不再需要controllerName参数。无论如何,我不太明白这是什么。您是否希望能够指定控制器类型?然后你可以像dan建议那样做(尽管这段代码需要一个UICollectionViewController,因为你将使用init(collectionViewLayout :))。

You could also pass an instance of the view controller you want embedded in the navigation controller like this:

您还可以传递要嵌入导航控制器中的视图控制器的实例,如下所示:

private func createNavController(imageName: String, rootViewController: UIViewController) -> UINavigationController
{
           let navController = UINavigationController(rootViewController: rootViewController)
           navController.tabBarItem.image = UIImage(named: imageName)
           return navController
}

and call it like this:

并称之为:

let navController = createNavController(
    imageName: "loc-map-route",
    rootViewController: UserController(collectionViewLayout: UICollectionViewFlowLayout()))

This would indeed not require a UICollectionViewController because UINavigationController.init(rootViewController:) takes a UIViewController. It all depends on what you want to achieve.

这确实不需要UICollectionViewController,因为UINavigationController.init(rootViewController :)采用UIViewController。这一切都取决于你想要达到的目标。

#2


1  

Do you want something like this?

你想要这样的东西吗?

private func createNavController<T: UICollectionViewController>(imageName: String, _ controllerName: T.Type) -> UINavigationController {
    let layout = UICollectionViewFlowLayout()
    let viewController = controllerName.init(collectionViewLayout: layout)
    let navController = UINavigationController(rootViewController: viewController)
    navController.tabBarItem.image = UIImage(named: imageName)
    return navController
}

Then you can do: let nav = createNavController(imageName: "loc-map-route", UserCollectionController.self) and nav will have a UserCollectionController as its root.

然后你可以这样做:让nav = createNavController(imageName:“loc-map-route”,UserCollectionController.self)和nav将以一个UserCollectionController为根。

#3


0  

I think that controllerName is an instance of UICollectionViewController, so it is an already initialized UICollectionViewController. It is not the name of the UICollectionViewController subclass. So if you just want to set the collectionViewLayout of that UICollectionViewController, I'd do:

我认为controllerName是UICollectionViewController的一个实例,所以它是一个已初始化的UICollectionViewController。它不是UICollectionViewController子类的名称。因此,如果您只想设置该UICollectionViewController的collectionViewLayout,我会这样做:

private func createNavController(imageName: String, _ controllerName: UICollectionViewController) -> UINavigationController
{
    let layout = UICollectionViewFlowLayout()
    let viewController = controllerName.collectionViewLayout = layout
    let navController = UINavigationController(rootViewController: viewController)
    navController.tabBarItem.image = UIImage(named: imageName)

    return navController
}

The you would call it like this:

你会这样称呼它:

let navController = createNavController(imageName: "my_image", myCreatedUserController)

#1


1  

In your definition of createNavController your parameter controllerName is of type UICollectionViewController and that is not a function type so you cannot call it as a function, i.e. controllerName(...).

在createNavController的定义中,参数controllerName的类型为UICollectionViewController,它不是函数类型,因此您不能将其称为函数,即controllerName(...)。

If you replace

如果你更换

let viewController = controllerName(collectionViewLayout: layout)

with

let viewController = UserController(collectionViewLayout: layout)

from your working code, it compiles fine. Also, you don't need the controllerName parameter anymore. I don't quite understand what this is for anyway. Did you want to be able to specify the controller type? Then you could do it like dan suggests (although this code requires a UICollectionViewController because you would be using init(collectionViewLayout:)).

从您的工作代码,它编译好。此外,您不再需要controllerName参数。无论如何,我不太明白这是什么。您是否希望能够指定控制器类型?然后你可以像dan建议那样做(尽管这段代码需要一个UICollectionViewController,因为你将使用init(collectionViewLayout :))。

You could also pass an instance of the view controller you want embedded in the navigation controller like this:

您还可以传递要嵌入导航控制器中的视图控制器的实例,如下所示:

private func createNavController(imageName: String, rootViewController: UIViewController) -> UINavigationController
{
           let navController = UINavigationController(rootViewController: rootViewController)
           navController.tabBarItem.image = UIImage(named: imageName)
           return navController
}

and call it like this:

并称之为:

let navController = createNavController(
    imageName: "loc-map-route",
    rootViewController: UserController(collectionViewLayout: UICollectionViewFlowLayout()))

This would indeed not require a UICollectionViewController because UINavigationController.init(rootViewController:) takes a UIViewController. It all depends on what you want to achieve.

这确实不需要UICollectionViewController,因为UINavigationController.init(rootViewController :)采用UIViewController。这一切都取决于你想要达到的目标。

#2


1  

Do you want something like this?

你想要这样的东西吗?

private func createNavController<T: UICollectionViewController>(imageName: String, _ controllerName: T.Type) -> UINavigationController {
    let layout = UICollectionViewFlowLayout()
    let viewController = controllerName.init(collectionViewLayout: layout)
    let navController = UINavigationController(rootViewController: viewController)
    navController.tabBarItem.image = UIImage(named: imageName)
    return navController
}

Then you can do: let nav = createNavController(imageName: "loc-map-route", UserCollectionController.self) and nav will have a UserCollectionController as its root.

然后你可以这样做:让nav = createNavController(imageName:“loc-map-route”,UserCollectionController.self)和nav将以一个UserCollectionController为根。

#3


0  

I think that controllerName is an instance of UICollectionViewController, so it is an already initialized UICollectionViewController. It is not the name of the UICollectionViewController subclass. So if you just want to set the collectionViewLayout of that UICollectionViewController, I'd do:

我认为controllerName是UICollectionViewController的一个实例,所以它是一个已初始化的UICollectionViewController。它不是UICollectionViewController子类的名称。因此,如果您只想设置该UICollectionViewController的collectionViewLayout,我会这样做:

private func createNavController(imageName: String, _ controllerName: UICollectionViewController) -> UINavigationController
{
    let layout = UICollectionViewFlowLayout()
    let viewController = controllerName.collectionViewLayout = layout
    let navController = UINavigationController(rootViewController: viewController)
    navController.tabBarItem.image = UIImage(named: imageName)

    return navController
}

The you would call it like this:

你会这样称呼它:

let navController = createNavController(imageName: "my_image", myCreatedUserController)