我开始在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))
}
}
答案 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代码的一行,但这是必需的,因为应用程序委托是执行此操作的唯一安全位置。