2016-11-15 17:41:47 zhonggaorong 阅读数 6156
  • iOS/Swift/OC/Objective-C/Xcode/0基础/入门

    这是一门快速入门iOS开发的课程,目的是让大家快速学会,iOS开发环境搭建,和iOS一些基础知识,最后完成一个小项目。 项目信息 提供完整的Git提交历史,和每节视频一一对应,目前有41次提交,355行注释,271行代码(不包含可视化布局文件,纯Swift和Objective-C代码)。

    2911 人正在学习 去看看 任苹蜻

最新一些学妹问起,所以抽点时间来写的,适合入门级别的swift 与 OC 混编 的程序猿。  

本文章将从两个方向分别介绍 OC 与 swift 混编  


1. 第一个方向从 swift工程 中引入 oc类 

    1. 1 如何在swift的类中使用oc类
    1.2  如何在swift中实现oc的代理方法
    1.3   如何在swift中实现oc的Block回调

2. 第二个方向从OC工程中引入swift类

    2.1  如何在OC类中使用swift类
    2.2   如何在OC中实现swift的代理方法
    2.3   如何在OC中实现swift中类似Block回调


下面是具体的实现过程:

 1.1  如何在swift的类中使用oc类? 

1.  swift工程中引入OC类。 具体实现过程。

    1.1 新建一个swift工程类。 取名 swiftOrOC

    1.2  实现的功能为 :  从swift. viewController.swift 中 push到 OC语言 secondViewController 控制器

1.2.1  新建SecondViewController 类 。

        

     1.2.2 建立桥接文件。 (很重要)


    一定要记得点击这个按钮。 

       1.2.3  接下来工程目录如下:

       

     1.2.4 接下来就可以实现具体的跳转功能了。 

      ViewController.swift中具体实现

     

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var hintLabel: UILabel!  //稍后用来显示回调
    
    // push 到 oc controller
    @IBAction func pushAction(_ sender: AnyObject) {
        let secondVC = SecondViewController.init()
        self.navigationController?.pushViewController(secondVC, animated: true)
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}


1.2 如何在swift中实现oc的代理方法

       1.2.1 首先在 SecondViewController.h 中声明一个协议。具体代码

        

#import <UIKit/UIKit.h>

@protocol SecondDelegate <NSObject>

-(void)refreshHintLabel:(NSString *)hintString;

@end

@interface SecondViewController : UIViewController

@property (nonatomic,weak)id<SecondDelegate> secondDelegate;
@end
     1.2.2 然后在SecondViewController.m中,通过一个UITextField,让用户输入内容,当用户点击返回的时候把输入框中的内容返回给对应的代理。具体代码如下

    

#import "SecondViewController.h"
#import "UIViewController+BackButtonHandler.h"

@interface SecondViewController ()
{
    UITextField *textField;
}
@end

@implementation SecondViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.title = @"oc";
    
    self.view.backgroundColor  = [UIColor whiteColor];
    
    textField = [[UITextField alloc]initWithFrame:CGRectMake(100, 100, 200, 200)];
    textField.placeholder = @"请输入用户名";
    [self.view addSubview:textField];
    [textField.layer setBorderColor:[UIColor blackColor].CGColor];
    [textField.layer setBorderWidth:1.0];

    
}

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    [self.view endEditing:YES];
}
#pragma mark 返回上一页回调 ,将用户输入的用户名传回给 ViewController.swift
-(BOOL)navigationShouldPopOnBackButton{
    if ([_secondDelegate respondsToSelector:@selector(refreshHintLabel:)]) {
        [_secondDelegate refreshHintLabel: textField.text];
    }
    
    return YES;
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

@end
  1.2.3 接下来就非常简单了,让ViewController.swift只需要成为SecondViewController的代理,然后遵循她的协议,就可以了。 具体代码如下。

       1.2.3.1 遵循协议

  

     1.2.3.2 成为代理,并实现协议方法,更改controller.swift中hintLabel的text。

    // push 到 oc controller
    @IBAction func pushAction(_ sender: AnyObject) {
        let secondVC = SecondViewController.init()
        secondVC.secondDelegate = self;
        self.navigationController?.pushViewController(secondVC, animated: true)
    }
    
    // SecondViewControll的代理方法
    func refreshHintLabel(_ hintString: String!) {
        hintLabel.text = "secondView textView.text = " + hintString;
    }
    

 1.3   如何在swift中实现oc的Block回调

1.3.1 具体过程与1.2小节一样。 直接上代码。

        1.3.2 声明block;

         

typedef void(^RefreshHintLabelBlock)(NSString *hintString);

@interface SecondViewController : UIViewController
@property (nonatomic, copy) RefreshHintLabelBlock hintBlock;
@end

        1.3.3 block的回调。 SecondViewController.m中

#pragma mark 返回上一页回调 ,将用户输入的用户名传回给 ViewController.swift
-(BOOL)navigationShouldPopOnBackButton{    
    if (_hintBlock) {
        _hintBlock(textField.text);
    }
    return YES;
}

        1.3.4 在swift类中调用 oc的block.

    // push 到 oc controller
    @IBAction func pushAction(_ sender: AnyObject) {
        let secondVC = SecondViewController.init()
//        secondVC.secondDelegate = self;
        secondVC.hintBlock = {(t:String?)in
            self.hintLabel.text = "secondView textView.text = " + t!
        }
        self.navigationController?.pushViewController(secondVC, animated: true)
    }


   工程已上传到git上,git地址: https://github.com/zhonggaorong/SwiftOrOc/tree/master

2.  OC工程中引入swift类。 具体实现过程。

    耽误了不少时间, 今天才开始写oc工程中引入swift类。

    demo地址: 

  

     2.1  如何在OC类中使用swift类


       2.1.1   新建一个基于OC语言的工程 ,取名 OcOrSwiftTwo
       2.1. 2  实现的功能为 : 从oc类 viewcontroller中, push 至 swift语言 SecondViewController  ,然后SecondViewController可以通过代理或者swift闭包把值传回viewcontroller. 
       2.1.3   当前文件目录看下图:  (第四个箭头: 桥接文件)
        
  
    2.2   如何在OC中实现swift的代理与闭包Block方法
            
    2.2.1 如何在oc中引入swift类。#import "工程名-swift.h"
#import "OcOrSwiftTwo-swift.h"
   2.2.2 在secondViewController.swift 中实现代理与闭包,代码如下:
    注意: @objc(代理名)  才能在外部可见这个代理
 
import UIKit
import Foundation

// 必须加上@objc 代理才能在oc类中可见。
@objc(EditTextFieldDelegate)
protocol EditTextFieldDelegate:NSObjectProtocol {
    func editTextField(_ str: String) -> Void
}

@objc(SecondViewController)
class SecondViewController: UIViewController {

    var editorDelegate:EditTextFieldDelegate?
    var textField:UITextField?
    var addButton:UIButton?
    var pushButton:UIButton?
    
    typealias editorBlock = (_ t:String) -> Void
    var myEidtorBlock:editorBlock?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.backgroundColor = UIColor.white
        textField = UITextField.init(frame: CGRect.init(x: 50, y: 60, width: 200, height: 50))
        textField?.placeholder = "输入返回首页的内容"
        self.view.addSubview(textField!)
        
        addButton = UIButton.init(type: .custom)
        addButton?.setTitleColor(UIColor.black, for: .normal)
        addButton?.setTitle("pop", for: .normal)
        addButton?.frame = CGRect.init(x: 50, y: 150, width: 200, height: 50)
        addButton?.layer.borderColor = UIColor.black.cgColor
        addButton?.layer.borderWidth = 1.0
        addButton?.addTarget(self, action: #selector(popAction), for: .touchUpInside)
        self.view.addSubview(addButton!)
        
        
        
        pushButton = UIButton.init(type: .custom)
        pushButton?.setTitleColor(UIColor.black, for: .normal)
        pushButton?.setTitle("push", for: .normal)
        pushButton?.frame = CGRect.init(x: 50, y: 250, width: 200, height: 50)
        pushButton?.layer.borderColor = UIColor.black.cgColor
        pushButton?.layer.borderWidth = 1.0
        pushButton?.addTarget(self, action: #selector(pushAction), for: .touchUpInside)
        self.view.addSubview(pushButton!)
        
    }
    
    func popAction() -> Void {
        
        if editorDelegate != nil {
            editorDelegate?.editTextField((textField?.text)!)
        }
        
        if ((self.myEidtorBlock) != nil){
            self.myEidtorBlock!((textField?.text!)!)
        }
        
        self.navigationController?.popViewController(animated: true)
    }
    
    
    func pushAction() -> Void {
        let three = ThreeViewController.init()
        self.navigationController?.pushViewController(three, animated: true)
        
    }     
    2.2.3   在oc类中viewcontroller.m 文件中实现SecondviewController.swift的相关代理与闭包(block). 代码如下:
   
#import "ViewController.h"
#import "OcOrSwiftTwo-swift.h"

@interface ViewController ()<EditTextFieldDelegate>
@property (nonatomic, strong) UITextField *showTextField;
@property (nonatomic, strong) UIButton *pushButton;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    _showTextField = [[UITextField alloc]initWithFrame:CGRectMake(50, 100 , 200, 50)];
    _showTextField.placeholder = @"swift传回的文本内容";
    _showTextField.adjustsFontSizeToFitWidth = YES;
    _showTextField.enabled = NO;
    [self.view addSubview:_showTextField];
    
    _pushButton = [UIButton buttonWithType:UIButtonTypeCustom];
    [_pushButton.layer setBorderColor:[UIColor blackColor].CGColor];
    [_pushButton.layer setBorderWidth:1.0];
    [_pushButton setFrame:CGRectMake(50, 200, 200, 50)];
    [_pushButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    [_pushButton setTitle:@"push" forState:UIControlStateNormal];
    [_pushButton addTarget:self action:@selector(pushAction) forControlEvents:UIControlEventTouchUpInside];
    
    [self.view addSubview:_pushButton];
}




-(void)pushAction{
    SecondViewController *second = [[SecondViewController alloc]init];
    // second.editorDelegate = self;
    
    /*
      swift中的闭包回滴
     */
    second.myEidtorBlock = ^(NSString *str) {
        _showTextField.text = [NSString stringWithFormat:@"second传回信息: %@",str];
    };
    [self.navigationController pushViewController:second animated:YES];
}

#pragma mark swift中的代理
-(void)editTextField:(NSString *)str{
    _showTextField.text = [NSString stringWithFormat:@"second传回信息: %@",str];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


2018-08-24 16:14:12 u010960265 阅读数 52
  • iOS/Swift/OC/Objective-C/Xcode/0基础/入门

    这是一门快速入门iOS开发的课程,目的是让大家快速学会,iOS开发环境搭建,和iOS一些基础知识,最后完成一个小项目。 项目信息 提供完整的Git提交历史,和每节视频一一对应,目前有41次提交,355行注释,271行代码(不包含可视化布局文件,纯Swift和Objective-C代码)。

    2911 人正在学习 去看看 任苹蜻

一、数据

Swift 是类型安全的语言:

  • Swift 必须明确数据类型
  • 如果取值错误会直接报错
  • Swift 会进行溢出检查 (OC 也会检查)
  • Swift 没有隐式类型转换, 不允许不同类型的数据类型进行运算

1.1 简单使用

Swift 很接近脚本语言,尤其是在数据类型方面。定义数据类型只允许使用 let 与 var,let 标识的是常量, var 标识的是变量。那么问题来了:那应该如何使用?在 Swift 中有可变类型么?

let name = "CoderHG"
print(name)

上面简单的定义了一个 name,如果没有看到后面具体的值,根本就不知道 name 是一个字符串类型。但是打断点查看,name 就是一个 String 类型的数据。将上面的代码中的 let 换成 var,会发现在上面的使用上没有任何的区别, 能正常使用。

var name = "CoderHG"
print(name)

但是还是有区别的,上面已经介绍 let 标识的是常量, var 标识的是变量。尽然是变量,可否将一个数字类型的 2 赋值给 name 呢?答案肯定是不可以的。在 Swift 中的定义,必须在定义的那一刻就要决定其数据类型。所以下面的这种定义是错误的:

var name
print(name)

这样的话,Xcode 是会直接报错的,因为在定义的时候没有指明 name 是什么类型。那么问题又来了,如何定义一个字符串,而又不希望有初始值呢?

var name: String
name = "CoderHG"
print(name)

这样,name 就是一个字符串类型的了。那么又出先了一个新问题,我可否这样定义:

let name: String
name = "CoderHG"
print(name)

使用 OC 的套路来思考上面的代码,肯定是不行的,因为一个常量只可能在定义的那一刻赋值,以后都是能读取其值,即为 只读。但是在 Swift 中有点不一样,Swift 在意的是第一次赋值,而不是定义时。所以上面的代码是没有问题的,但是如果再次给 name 赋值,那么肯定就出错了。

接下来主要介绍一下:在 Swift 中的可变类型。,在 OC 中一般使用 NSMutable¥ 来表示一个可变类型,那么在 Swift 中如何表示呢?其实 var 不仅代表一个变量,也代表着 OC 中的可变性。比如,可以这么使用:

var name = "CoderHG"
name.append(", Very GOOD!")
print(name)

如果换成 let 肯定是不行的。

上面简单的介绍了一下 let 与 var 的简单用法与注意事项。

看到这里,是否会不由自主的想到 OC 中这样的代码:

id obj = [[NSObject alloc] init];
   obj = [[HGPerson alloc] init];

然后 Swift 中也来了这么一段:

var obj = NSObject()
// var obj:HGPerson = NSObject() as! HGPerson
print(obj)
obj = HGPerson()
print(obj)

以上两段代码说明在 Swift 中的 var 也有 OC 中 id 的影子,所以在 Swift 中做类型检测也是很有必要的。所以在 Swift 中会经常看类似这样的代码:

var obj = NSObject()
print(obj)
obj = HGPerson()
print(obj)

let person = obj as! HGPerson
print(person)

在上面用到了一个类型转换的标识 as!,在 Swift 中的全部类型转换标识,如下:

is : 用于判断一个实例是否是某一种类型
as : 将实例转成某一种类型 (比如子类->父类转换)
as?:将某个类型转成可选类型,通过判断可选类型是否有值,来决定是否转化成功
as!: 将某个类型转成具体的类型,但是注意:如果不是该类型,那么程序会崩溃

1.2 数据类型

在 OC 中的数据类型主要分成两种:基本数据类型与对象类型,在 Swift 中也一样。但是在 Swift 中最为常见的是 结构体(基本数据类型),比如 String 与 Int8:

public struct String
public struct Int8 : FixedWidthInteger, SignedInteger

在 OC 中字符串是对象类型,数字是基本数据类型(NSNumber 除外)。当然这些结构体类型的数据,都是可以无缝衔接到对象类型,比如 NSString,一般使用 String 就能满足很多的场景。

1.3 可选与非可选数据类型

在 Swift 中,一个变量没有 默认值 这种说法。一个变量要么是有值、要么没有值,这就叫做 可选类型。Swift 中的可选类型,是一种单独的数据类型。有可选类型,那么就有非可选类型。
关于这部分,前不久在简书上简单的总结了一下,可以参考 对 Swift 中可选类型的理解。

有值与没值、是两种状态,而不是两种具体的值。

1.4 结构体

先看一个简单的结构体:

// 定义一个结构体
struct HGStruct {
    var name:String?
    var des:String?

    func desFunc() -> Void {
        print(name! + "_" + des!)
    }
}

// 可以这样使用:
// 无参构造函数
var st = HGStruct()
// 逐一构造函数
st = HGStruct(name: "HG", des: "Good")
// 调用结构体函数
st.desFunc()

对于一个结构体来说,只要是有属性,系统默认生成两个构造函数,一个是无参构造函数,一个是 逐一构造函数。

逐一构造函数: 将所有的属性作为参数的构造函数。

构造函数:不用 func 作为修饰,函数名统一为 init。

以上的两种构造函数是自动生成的,也可以自定义构造函数。比如:

// 自定义构造函数
init(name:String) {
    self.name = name
    des = "Good!"
}

自定义的构造函数有一个明显的特点,不需要加 func 关键字。还有一个特点是:一旦自定义了构造函数,那么自动生成的构造函数都将失效。
这里有一个方法可以做到构造函数的随意组合,就是重写 逐一构造函数,将所有的参数都弄一个默认值。如下:

// 重写 逐一构造函数
init(name:String = "", des:String = "") {
    self.name = name
    self.des = des
}

关于结构体,也是属于基本数据类型,是 值 类型,是不能直接在结构体内部直接修改其 属性 的值的。比如:

// 更新名字
func update(name:String) -> Void {
    self.name = name
}

这样是会直接报错的,必须在 func 的前面加一个关键字 mutating。如:

// 更新名字
mutating func update(name:String) -> Void {
    self.name = name
}

到这里,关于 Swift 中结构体的使用介绍,基本差不多了。在 Swift 的实际开发中,结构体的使用也是比较频繁的。由上面的介绍可以知道,功能也比 OC 中的多,主要的原因是有 函数。在上面的代码中也能看在,也有 self 关键字,使用方式与 Class 几乎一致。所以在一些轻量级的场合,可以直接选择使用结构体。

1.5 枚举

简单的定义:

// 枚举定义
enum HGEnum {
    case go
    case back
}

可以这样的使用:

{
    direction(d: HGEnum.go)
}

func direction(d:HGEnum) -> Void {
    switch d {
    case .go:
        print("go")
    case .back:
        print("back")

    }
}

从上面也能看出获取枚举的方式,HGEnum.go 与 .go 是同一个,但是要保证只有这个枚举有这个 go,否则出错。

关于枚举的值

直接这样打印:

print(HGEnum.go)

发现打印结果是:go,枚举值仅仅是一个符号, 不代表任何类型。如果想要绑定原始值, 必须指明枚举的类型,比如:

// 枚举定义
enum HGEnum:String {
    case go   = "go_value"
    case back = "back_value"
}

一旦指明了枚举的类型,在使用上没有区别,可以使用 rawValue 获取具体的值:

print(HGEnum.go.rawValue)  // go_value
print(HGEnum.go)           // go

枚举有能定义函数

func enumFunc() {
    print(self.rawValue, "_哈哈哈哈哈")
}

代用方式:

HGEnum.go.enumFunc()
HGEnum.back.enumFunc()

二、方法到函数

在 Swift 中就没有方法这种叫法了,统一称函数。函数定义的模板如下:

func 函数名(参数列表) -> 返回值类型 { 
    代码块 
    return 返回值 
} 

对于函数这一块,没有什么特别的。这里有一个规律,就是 Swift 函数转成 OC 方法的时候,是这样的:

// Swift 函数
func hello(name:String, from:String) -> String {
    return "你好!我是 " + name + ", 来自于 " + from
}

// 转成 OC 是这样的 
// - (NSString*)helloWithName:(NSString*)name from:(NSString*)from;

上面代码的亮点是函数名与方法名,是有规律的。这也给我们一个在 OC 中方法命名规范的提醒:第一个参数以 With 做拼接,并首字母大写,其它参数前的方法名部分直接使用参数的名称。当然,规范仅仅是一个规范而已,苹果的 API 也并非全部按照这样的规范,比如:

// tap
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    // TODO: 待处理
}

关于 函数 这一块,相对 OC 来说有以下两个明显的不同:

函数中可以定义函数,这个功能在 OC 也有类似的,就是方法中定义 Block。
函数重载,这个在 OC 中是实现不了的。

三、类

在 OC 中有三种 Class:Block,NSProxy 与 NSObject。据我现在所知,在 Swift 中没有了 Block,但是有了一种闭包的东西。除此之外,在 Swift 中的 Class 可以不用继承任何的基类。
在 OC 中即使是一个简单的数据模型都需要继承于 NSObeject,显得有些重量级。但是在实际上还是有很多区别的。

3.1 简单的定义

有两个致命的规律:

定义的 Class 一定要有属性,否则直接报错
创建一个类的实例, 必须在创建之后, 里面所有的非可选属性必须有值,否则报错

class HGPerson {

}

没有任何属性,直接报错。

class HGPerson {
    var name:String
}

name 为非可选,创建实例之后 name 没有值,直接报错。

class HGPerson {
    var name:String
    // var name:String = ""
    // 构造函数
    init() {
        name = ""
    }
}

重写构造函数,非可选属性 name 默认有值。每个 Class 都会有一个默认的无参构造函数,一旦有重写,默认构造函数将失效。

在使用上,与 OC 中的几乎完全一样。

3.2 特殊方法

在一个 Class 中,我们往往比较在乎的是一个实例的生命周期。总之一句话:生于构造函数,毁于虚构函数。
构造函数:一个特殊的函数,与结构体中的一样。不用 func 作为修饰,函数名统一为 init。
虚构函数:实例销毁时系统调用的函数 deinit,功能与 OC 中的 dealloc 一样。

3.3 setter 与 getter 方法

这里的 setter 与 getter 方法,和 OC 中的还有点不一样。比如:

var doSomething:String {
    set {
        // setter

    }

    get {
        // getter
        return ""
    }
}

这里需要注意一点,在 Swift 中的只读属性,将上面的 set 去掉,就是只读属性的。

3.4 属性监听

var sex:String = "" {
    willSet(newValue) {
        print("当前的值 = " + self.sex + ",新值 = " + newValue)
    }
    didSet(oldValue) {
        print("当前的值 = " + self.sex + ",之前的值 = " + oldValue)
    }
}

这里要注意一个问题:在构造函数中的 setter 方法是不会被监听到的。

3.3 注意事项

Swift 中的 Class 是可以没有基类的。

四、协议(代理)

4.1 简单使用

定义

/// MARK 定义一个代理
protocol DetailDelegate: NSObjectProtocol {
    // 从控制器返回 content 内容
    func detail(vc:DelegateDetailController?, content:String?)
}

关键字:protocol 与 NSObjectProtocol。这里需要注意一点的是,在 Swift 中的协议也是可以没有基类的,在 OC 中也一样,但是一般都是继承于 NSObject 协议。在 Swift 中有以下三种情况:

没有继承,这种情况只能使用在没有继承 NSObject 的 Class 中,不能使用 weak 修饰,毕竟 weak 只能修饰 Class。
继承于 class,这种情况可用于所有的 Class。
继承于 NSObjectProtocol,这种情况可用于所有的 Class。与第2中的区别是,这个协议自带了很多的系统协议。所以继承于这种协议的不推荐使用在没有继承于 NSObject 的 Class 中,因为在 Swift 中的所有协议函数都是强制必须要实现的。

综上,继承于 class一般使用在没有继承于 NSObject 的 Class 中,而继承于 NSObjectProtocol一般使用于继承于 NSObject 的 Class 中。没有继承的使用在结构体与枚举中,这个就很厉害了,在上面的结构体与枚举中就知道,这两种数据结构也是可以定义函数的,所以有这样的的协议场景也是很相当合理的。

delegate变量

// 定义个代理变量
weak var delegate:DetailDelegate?

与 OC 一致,需要弱化。

执行

let cell = tableView.cellForRow(at: indexPath)
delegate?.detail(vc: self, content: cell?.textLabel?.text)

五、控制器中的代码布局

这里说的控制器代码布局,仅仅是一个例子,只要是 Class 都是同样的套路
在 OC 中,默认的代码结构是这样的:

#import "HomeController.h"

@interface HomeController ()

@end

@implementation HomeController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
}

@end

核心的代码都是写在 @implementation 与 @end 之间,如果要将其中的功能分开,只能是通过 分类 或者直接另建文件。在 Swift 中,默认的结构是这样的:

class HomeController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
    }
}

全部的代码,都是写在第一个大括号中。但是可以借助 extension 来做分割:

/// 系统相关函数实现
class HomeController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    }
}

/// 登录 相关的函数实现
extension HomeController {

}

/// 叫车 相关的函数实现
extension HomeController {

}

/// UITableViewDelegate 的协议函数
extension HomeController: UITableViewDelegate {

}

/// UITableViewDataSource 的协议函数
extension HomeController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 45;
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "id")

        return cell!
    }
}

/// HGObjectDelegate 协议函数
extension HomeController: HGObjectDelegate {


}

以上是一个简单的分割,在实际的开发中,可能没有这么简单,毕竟实际的项目的代码更加复杂。
上面简单的代码中可以看到可以通过 extension 做针对性的分离。

六、@objc

@objc 这个关键组合,作用是在 Swift 中实现,在 OC 中使用。

6.1 协议中使用

在协议中,会看到这个关键词。在上面的介绍中,Swift 中的协议一旦被遵循,那所有的函数都必须是先实现的,没有可选函数这一说。换成 OC 的说法就是必选的。在 OC 中没有实现必选方法是报警告,在 Swift 中是直接报错。那么问题来了:在 OC 中是有可选协议方法的,如果这个协议是在 Swift 中实现,应该如何处理呢?

  • OC 中如何使用 Swift 中的协议?
  • 如何在 Swift 中给 OC 提供可选协议函数?

一个简单的例子如下:

@objc
protocol HGObjectDelegate {
    // 可选的协议方法
    @objc optional func optionalFunc()
}

@objc 代表可以在 OC 中使用,optional 在 OC 中是可选的协议方法。

现在看在 HGObjectDelegate 没有任何的集成,相当于在 OC 中没有继承 NSObject 一样。但是可以直接使用与 OC 中的所有 Class 中。在 Swift 中,这个协议是不能使用在没有继承的 Class 中的。

6.2 函数中使用

在 Swift 实现的函数,是可以很好的转换成 OC 方法的,一般不使用转换,其实在上面也已经有介绍。但是 Swift 中的函数与 OC 中的方法还是有所差异的,比如在 Swift 中有重载,然而。。。。这种情况就需要 @objc 做一下转换。比如以下的代码:

@objc(sumIntWithA:b:)
func sum(a:Int, b:Int) -> Int {
    print("Int")
    return a+b;
}

@objc(sumDoubleWithA:b:)
func sum(a:Double, b:Double) -> Double {
    print("Double")
    return a+b
}

一看就懂,无需介绍。
在 OC 中这么使用:

HGObject* obj = [HGObject new];
NSInteger int_Result = [obj sumIntWithA:9 b:4];
float doble_Result = [obj sumDoubleWithA:3.2 b:2.3];
NSLog(@"%zd %f", int_Result, doble_Result);

在 Swift 中这么使用:

let obj = HGObject();
let sum1 = obj.sum(a: 1, b: 2)
let sum2 = obj.sum(a: 2.3, b: 2.5)
print(sum1, sum2)
2018-03-30 10:53:28 fenglin0429 阅读数 371
  • iOS/Swift/OC/Objective-C/Xcode/0基础/入门

    这是一门快速入门iOS开发的课程,目的是让大家快速学会,iOS开发环境搭建,和iOS一些基础知识,最后完成一个小项目。 项目信息 提供完整的Git提交历史,和每节视频一一对应,目前有41次提交,355行注释,271行代码(不包含可视化布局文件,纯Swift和Objective-C代码)。

    2911 人正在学习 去看看 任苹蜻
做为一个iOS开发的门外汉,连OC都没有学会,就来强行入门一波swift,说不是作死,有谁能信。

常量和变量 以及其声明

常量 let

let maxNum = 1000

当一个量声明出来,赋初值之后,如果不再改变,这时候尽量的将其声明为常量,这样这个量对整个计算资源的消耗更少,整个程序更加的优化。

变量 var

var index = 2

与其他语言类似的,可以在一个语句中同时声明多个变量

var x=1,y=2,z=3

swift 是一种强类型的语言,虽然没有声明其类型,但其类型在赋初值时已经确定,这种机制叫做 Type inference。
也可进行变量类型的声明,方法如下

var s:String ="Hello World"

var a , b ,c :Double  
// 此时的a,b,c都是double类型的变量

综上,swift的变量常量声明就结束了,感觉非常的简单省事,节省了很多打字的消耗。
类比于Java的替代语言kotlin,同样的声明方式,同样优秀的语言,非常值得学习。

kotlin:
val 常量

var 变量

var name = “Tom”;
or
var address:String = “泺源大街”;

2014-06-03 14:55:50 cuibo1123 阅读数 15202
  • iOS/Swift/OC/Objective-C/Xcode/0基础/入门

    这是一门快速入门iOS开发的课程,目的是让大家快速学会,iOS开发环境搭建,和iOS一些基础知识,最后完成一个小项目。 项目信息 提供完整的Git提交历史,和每节视频一一对应,目前有41次提交,355行注释,271行代码(不包含可视化布局文件,纯Swift和Objective-C代码)。

    2911 人正在学习 去看看 任苹蜻
学oc吧,学完估计也就淘汰了。

学swift吧,短时间内普及几率太低,即便学完了,大部分老项目还是用oc..


不学oc吧,放眼望去现在全是oc,swift完全没有用武之地。

不学swift吧,说不上那天这玩意火了,现学现卖恐怕来不及,即便靠oc苟延残喘的活着,质量和薪水估计也一定不咋地,毕竟我们都有一个当大牛的梦。。


看苹果态度和swift能力,个人觉得oc一定会淘汰,
但是:短期内应该会共存!
不可能所有项目立刻swift重写,维护就要求一定会oc。
而且swift人才和大项目经验缺乏,很多公司应该不会立刻就上。
我个人可能会大项目继续objective-c,小项目用swift试水。

oc和swift并存,这就给iOS入门者如何选择Swift和objective-c带来了一个巨大的问题。

对于新手,建议把主要精力放在Swift上,可以慢慢学,1年之内迫切需要使用swift的可能性应该不是很大。

但是oc3~5年内彻底淘汰的可能性应该也很小,团队合作,项目维护,甚至是新项目开发很长一段时间内都会用的上,所以oc技术也至少要达到能维护的程度,技术底层和实现细节可以不深究了。


以上时间线纯属个人预期,不同公司对新技术的兴趣不同,所以各位还要慎重考虑。

#wwdc2014#

2016-03-09 15:51:00 ai_pple 阅读数 237
  • iOS/Swift/OC/Objective-C/Xcode/0基础/入门

    这是一门快速入门iOS开发的课程,目的是让大家快速学会,iOS开发环境搭建,和iOS一些基础知识,最后完成一个小项目。 项目信息 提供完整的Git提交历史,和每节视频一一对应,目前有41次提交,355行注释,271行代码(不包含可视化布局文件,纯Swift和Objective-C代码)。

    2911 人正在学习 去看看 任苹蜻

1:但是初步看Swift,发现Swift只有var 和 let两种 

2:问度娘发现Swift中var表示变量,let表示常量

2. Swift写一个string值,不需要@也不需要;(分号), 如var str = “hello,world”

3:Swift输出函数用println(str)str是“hello,world”

4:Swift填icon只需要一部,打开Assets.xcassets 里面的icon ,把对于图片尺寸放上去,运行!,ok!

5:以下是转载过来的

  1. /** 
  2. * 元组 java中map的马甲,先这么理解吧 
  3. */  
  4. let http404Error = (404"Not Found")  
  5. let (statusCode, statusMessage) = http404Error  
  6. println("The status code is \(statusCode)")  
  7. // 输出 "The status code is 404"  
  8. println("The status message is \(statusMessage)")  
  9. // 输出 "The status message is Not Found"  
  10.   
  11. let (justTheStatusCode, _) = http404Error  
  12. println("The status code is \(justTheStatusCode)")  
  13. // 输出 "The status code is 404"  只需要一部分元组值,分解的时候可以把要忽略的部分用下划线(_)标记  
  14.   
  15.   
  16. println("The status code is \(http404Error.0)")  
  17. // 输出 "The status code is 404" 下标方式取值  
  18. println("The status message is \(http404Error.1)")  
  19. // 输出 "The status message is Not Found" 下标方式取值  
  20. let http200Status = (statusCode: 200, description"OK"//凌乱了, 居然可以这样写, 这是map<String , Object> 先这么理解吧。  

Swift 从OC入门

阅读数 3

Swift的简单入门1

阅读数 478

Swift入门

阅读数 310

没有更多推荐了,返回首页