将Objective-C委托方法与swift文件混合

时间:2018-10-25 08:56:21

标签: ios objective-c swift

我开始在Objective-C中开发此应用程序。通过最近遇到的一些问题,我开始对某些功能使用swift。一切正常。现在,我开始构建一个新功能,并决定尽快进行。我在仅Swift项目中编写了代码,以进行测试。在测试版本中,一切正常,但是在我的主项目中实施时,我遇到了问题。

问题是我在委托文件中设置了视图选项,如下所示:

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

    window = UIWindow(frame: UIScreen.main.bounds)
    window?.makeKeyAndVisible()

    let layout = UICollectionViewFlowLayout()
    window?.rootViewController = UINavigationController(rootViewController: HomeController(collectionViewLayout: layout))

    return true
}

但是因为我的主要Project委托文件在Objective-C中,所以我不知道如何在Objective-C Project的Swift文件中使用它。我尝试在viewDidLaunch文件中设置视图。但这不起作用。 所以我问自己,是否真的可以在Objective-C的Objective-C委托方法中为我的swift文件设置代码。但是对于我的项目,我想在swift文件中设置视图选项。所以这是我到目前为止尝试过的:

import UIKit

class HomeController: UICollectionViewController, UICollectionViewDelegateFlowLayout {

var window: UIWindow?

override func viewDidLoad() {
    super.viewDidLoad()

    window = UIWindow(frame: UIScreen.main.bounds)
    window?.makeKeyAndVisible()

    let layout = UICollectionViewFlowLayout()
    window?.rootViewController = UINavigationController(rootViewController: HomeController(collectionViewLayout: layout))

    navigationItem.title = "Home"

    collectionView?.backgroundColor = UIColor.white

    collectionView?.register(VideoCell.self, forCellWithReuseIdentifier: "cellId")
}

//number of items
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return 10
}

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cellId", for: indexPath)

    return cell
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    return CGSize(width: view.frame.width, height: 200)
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
    return 0
}
}

class VideoCell: UICollectionViewCell{
override init(frame:CGRect){
    super.init(frame: frame)
    setupViews()
}

let thumbnailImageView: UIImageView = {
    let imageView = UIImageView()
    imageView.backgroundColor = UIColor.blue
    return imageView
}()

let userProfileImageView: UIImageView = {
    let imageView = UIImageView ()
    imageView.backgroundColor = UIColor.green
    return imageView
}()

let separatorView: UIView = {
    let view = UIView()
    view.backgroundColor = UIColor.black
    return view
}()

let titleLabel: UILabel = {
    let label = UILabel()
    label.backgroundColor = UIColor.purple
    label.translatesAutoresizingMaskIntoConstraints = false
    return label
}()

let subtitleTextView: UITextView = {
    let textView = UITextView()
    textView.backgroundColor = UIColor.red
    textView.translatesAutoresizingMaskIntoConstraints = false
    return textView
}()

func setupViews(){
    addSubview(thumbnailImageView)
    addSubview(separatorView)
    addSubview(userProfileImageView)
    addSubview(titleLabel)
    addSubview(subtitleTextView)

    //Abstand zum Bildschirmrand (Blau)
    addConstraintsWithFormat(format: "H:|-16-[v0]-16-|", views: thumbnailImageView)

    //Grün
    addConstraintsWithFormat(format: "H:|-16-[v0(42)]", views: userProfileImageView)

    //vertical constraints / v0 = Blau höhe / v1 = Grün höhe / v2 = Linie höhe
    addConstraintsWithFormat(format: "V:|-32-[v0(75)]-8-[v1(44)]-16-[v2(1)]|", views: thumbnailImageView, userProfileImageView, separatorView)

    //Abtrennung zwischen Zellen /zweite Zeile wird in "Große Fläche" umgesetzt
    addConstraintsWithFormat(format: "H:|[v0]|", views: separatorView)

    //top constraint
    addConstraint(NSLayoutConstraint(item: titleLabel, attribute: .top, relatedBy: .equal, toItem: thumbnailImageView, attribute: .bottom, multiplier: 1, constant: 8))
    //left constraint
    addConstraint(NSLayoutConstraint(item: titleLabel, attribute: .left, relatedBy: .equal, toItem: userProfileImageView, attribute: .right, multiplier: 1, constant: 8))
    //right constraint
    addConstraint(NSLayoutConstraint(item: titleLabel, attribute: .right, relatedBy: .equal, toItem: thumbnailImageView, attribute: .right, multiplier: 1, constant: 0))
    //height constraint
    addConstraint(NSLayoutConstraint(item: titleLabel, attribute: .height, relatedBy: .equal, toItem: self, attribute: .height, multiplier: 0, constant: 20))


    //top constraint
    addConstraint(NSLayoutConstraint(item: subtitleTextView, attribute: .top, relatedBy: .equal, toItem: titleLabel, attribute: .bottom, multiplier: 1, constant: 4))
    //left constraint
    addConstraint(NSLayoutConstraint(item: subtitleTextView, attribute: .left, relatedBy: .equal, toItem: userProfileImageView, attribute: .right, multiplier: 1, constant: 8))
    //right constraint
    addConstraint(NSLayoutConstraint(item: subtitleTextView, attribute: .right, relatedBy: .equal, toItem: thumbnailImageView, attribute: .right, multiplier: 1, constant: 0))
    //height constraint
    addConstraint(NSLayoutConstraint(item: subtitleTextView, attribute: .height, relatedBy: .equal, toItem: self, attribute: .height, multiplier: 0, constant: 20))

    thumbnailImageView.frame = CGRect(x: 0, y: 0, width: 50, height: 50)

}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}
}

extension UIView {
func addConstraintsWithFormat(format: String, views: UIView...){
    var viewsDictionary = [String: UIView]()
    for (index, view) in views.enumerated(){
        let key = "v\(index)"
        view.translatesAutoresizingMaskIntoConstraints = false
        viewsDictionary[key] = view
    }

    addConstraints(NSLayoutConstraint.constraints(withVisualFormat: format, options: NSLayoutConstraint.FormatOptions(), metrics: nil, views: viewsDictionary))

}
}

2 个答案:

答案 0 :(得分:0)

通常为make swift classes available in objective-c
对我也有帮助的是another question/answer on stack

但是请考虑一下基本变化: 快速创建一个新应用并通过 brindging标头连接到旧类可能会更好。 documentation真的很有帮助。

将来,迅速添加新元素并使用新功能会更容易。

答案 1 :(得分:0)

在视图控制器的viewDidLoad内部执行此操作绝对是不安全的,而且您甚至都不应尝试。

这是因为viewDidLoad可能被执行多次

如果发生这种情况,它将在应用执行期间将窗口和rootViewController替换为新实例(对用户来说,就像应用已重置一样)。

您需要从应用程序委托初始化窗口和根控制器,没有选择。

但是,您仍然可以在Swift中编写大多数代码。

首先,在UIWindow上创建一个Swift扩展,其中包括一个类函数,该函数初始化并配置您的窗口,然后将其返回。通过在声明中添加@objc,确保Objective-C可访问扩展名:

@objc extension UIWindow {
    class func setRootHomeViewController() -> UIWindow {
        let window = UIWindow(frame: UIScreen.main.bounds)
        window.makeKeyAndVisible()
        let layout = UICollectionViewFlowLayout()
        window.rootViewController = UINavigationController(rootViewController: HomeController(collectionViewLayout: layout))
        return window;
    }
}

然后,在Objective-C应用程序委托中,您需要导入Swift头文件并调用已定义的新UIWindow类方法。将返回的窗口对象分配给应用程序委托的window属性。

#import "YourProjectName-Swift.h"

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    _window = [UIWindow setRootHomeViewController];

    return YES;
}

@end

这只是Objective-C代码的一行,但这是必需的,因为应用程序委托是执行此操作的唯一安全位置。