将 Objective-C 委托方法与 swift 文件混合
Posted
技术标签:
【中文标题】将 Objective-C 委托方法与 swift 文件混合【英文标题】:Mix Objective-C delegate method with swift file 【发布时间】:2018-10-25 08:56:20 【问题描述】:我开始在 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
但是因为我的主要项目委托文件在 Objective-C 中,所以我不知道如何让它在我的 Swift 文件中工作在 Objective-C 项目中。我尝试在 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))
【问题讨论】:
【参考方案1】:一般到make swift classes available in objective-c.another question/answer on stack 对我也有帮助。
但是考虑一下根本的变化: 最好是在 swift 中创建一个新应用程序并通过 brindging header 连接到旧类。 documentation 真的很有帮助。
将来,在 swift 中添加新元素和使用新功能会更容易。
【讨论】:
【参考方案2】:在视图控制器的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 代码,但这是必要的,因为应用程序委托是唯一安全的地方。
【讨论】:
以上是关于将 Objective-C 委托方法与 swift 文件混合的主要内容,如果未能解决你的问题,请参考以下文章