在尝试了几个小的Swift程序后,我决定下一步是将Objective-C程序中的单个模块移植到Swift中,看看需要哪些步骤。我有很多问题,所以我想我会在这里发布我的流程和结果,以防其他人发现它有用。
我还创建了一个表来帮助我记住不同的转换。很遗憾,StackOverflow不支持表格,因此我将这些转化发布为Github gist here。
虽然Apple无疑会提供一个Xcode Refactor来从Objective-C转换为Swift,但手动转换它是熟悉这两种语言之间差异的好方法。你熟悉的语言中有很多“肌肉记忆”,这是熟悉新语法的好方法。正如苹果公司所承诺的那样,这些语言共享了许多共同的想法,它主要是一个机械过程(而不是移植,比如C ++,甚至传统的C)。
请注意,此过程不使用Swift令人兴奋的新功能,它只能直接获取代码。我应该提一下,转移到Swift将限制任何向后兼容iOS 7或OS X 10.9。我还遇到了一些问题(下面有解决方法),我确信这只是项目的第一个测试版发布状态,因此未来版本可能不需要。
我选择了iPhoneCoreDataRecipes
并选择了一个不依赖于其他许多模块的模块:IngredientDetailViewController
。如果您想跟随,请查看下面的“答案”。
希望这是有用的。
答案 0 :(得分:2)
0)下载项目here的副本并在Xcode版本6中打开Recipes.xcodeproj
。
1)选择File>New File…>iOS Source>Swift File> IngredientDetailViewController
(文件夹:类,组:配方视图控制器)
2)回复是“你想配置一个Objective-C桥接头吗?”
3)将Recipes_Prefix.pch
下面的前三行和IngredientDetailViewController.m
中的后三行复制到Recipes-Bridging-Header.h
。如果您执行其他文件,显然不会重复行,并删除您已转换为Swift的所有文件。鉴于它们已经在swift文件中导入,我还没有找到任何记录Cocoa系列需求的地方,但是......
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <CoreData/CoreData.h>
#import "Recipe.h"
#import "Ingredient.h"
#import "EditingTableViewCell.h"
4)将IngredientDetailViewController.h
文件和IngredientDetailViewController.m
文件中的文本复制/粘贴到IngredientDetailViewController.swift
。
5)从项目中删除IngredientDetailViewController.h
和.m
个文件。
6)从#import "IngredientDetailViewController.h"
到#import "Recipes-Swift.h"
执行全局查找和替换(在这种情况下只进行一次转换,对于其他文件,请不要在目标中复制此行) -C模块。)
7)检查项目&gt;目标&gt;食谱&gt;构建设置Runpath Search Paths
。如果它显示$(inherited)
,请删除此行,否则您在发布时会收到错误&#34;未找到图像&#34;
8)将IngredientDetailViewController.swift
中的Objective-C语法转换为Swift。请参阅所需的GitHub Gist mentioned above替换,或转换后的版本。
9)您可能需要更新IB链接。在IngredientDetailViewController
上执行查找&gt;在文件中查找,然后在Interface Builder中选择一个。在右侧列中打开Identity Inspector。在类别字段中选择IngredientDetailViewController
,输入xxx
或其他内容和标签。
10)构建并运行。请注意,进入配方后,您必须点击编辑,然后点击成分的信息按钮以激活IngredientDetailViewController
12)祝贺您构建第一个混合的Swift / Objective-C程序!
这是我对这个特定模块的切入:
``
class IngredientDetailViewController: UITableViewController {
var recipe: Recipe!
var ingredient: Ingredient! {
willSet {
if let newIngredient = newValue {
self.ingredientStr = newIngredient.name
self.amountStr = newIngredient.amount
} else {
self.ingredientStr = ""
self.amountStr = ""
}
}
}
init(nibName nibNameOrNil: String!, bundle nibBundleOrNil: NSBundle!) {
super.init(nibName:nibNameOrNil, bundle: nibBundleOrNil?)
}
init(coder aDecoder: NSCoder!) {
super.init(coder: aDecoder)
}
init(style: UITableViewStyle) {
super.init(style: style)
}
// MARK: table's data source
var ingredientStr: String?
var amountStr: String?
// view tags for each UITextField
let kIngredientFieldTag = 1
let kAmountFieldTag = 2
override func viewDidLoad () {
super.viewDidLoad()
self.title = "Ingredient"
self.tableView.allowsSelection = false
self.tableView.allowsSelectionDuringEditing = false
}
override func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int {
return 2
}
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
let IngredientsCellIdentifier = "IngredientsCell"
let cell = tableView.dequeueReusableCellWithIdentifier(IngredientsCellIdentifier, forIndexPath: indexPath ) as EditingTableViewCell
if (indexPath.row == 0) {
// cell ingredient name
cell.label.text = "Ingredient"
cell.textField.text = self.ingredientStr
cell.textField.placeholder = "Name"
cell.textField.tag = kIngredientFieldTag
}
else if (indexPath.row == 1) {
// cell ingredient amount
cell.label.text = "Amount"
cell.textField.text = self.amountStr
cell.textField.placeholder = "Amount"
cell.textField.tag = kAmountFieldTag
}
return cell
}
@IBAction func save (sender: AnyObject!) {
if let context = self.recipe.managedObjectContext {
if (!self.ingredient) {
self.ingredient = NSEntityDescription.insertNewObjectForEntityForName("Ingredient",
inManagedObjectContext:context) as Ingredient
self.recipe.addIngredientsObject(self.ingredient)
self.ingredient.displayOrder = self.recipe.ingredients.count
}
// update the ingredient from the values in the text fields
let cell = self.tableView.cellForRowAtIndexPath(NSIndexPath(forRow:0, inSection:0)) as EditingTableViewCell
self.ingredient.name = cell.textField.text
// save the managed object context
var error: NSError? = nil
if !context.save( &error) {
/*
Replace this implementation with code to handle the error appropriately.
abort() causes the application to generate a crash log and terminate.
You should not use this function in a shipping application, although it may be
useful during development. If it is not possible to recover from the error, display
an alert panel that instructs the user to quit the application by pressing the Home button.
*/
println("Unresolved error \(error), \(error!.userInfo)")
abort()
}
}
// if there isn't an ingredient object, create and configure one
self.parentViewController.dismissViewControllerAnimated(true, completion:nil)
}
@IBAction func cancel(sender: AnyObject!) {
self.parentViewController.dismissViewControllerAnimated(true, completion:nil)
}
func textFieldDidEndEditing(textField:UITextField) {
// editing has ended in one of our text fields, assign it's text to the right
// ivar based on the view tag
//
switch (textField.tag)
{
case kIngredientFieldTag:
self.ingredientStr = textField.text
case kAmountFieldTag:
self.amountStr = textField.text
default:
break
}
}
}