美文网首页swift
从Objective-C向Swift转换学习到的经验(转)

从Objective-C向Swift转换学习到的经验(转)

作者: onehao16 | 来源:发表于2016-08-15 17:49 被阅读320次

    首先贴上原文地址 如有侵权 告知删除,在这里仅仅是个人学习和交流
    http://www.pig66.com/weixintoutiao/kejika/2016-02-29/688907.html

    一、初始化UIView的子类

    在iOS应用上实现UI就需要子类化UIView,也就是要重写UIView的init方法。注意:两种语言有所区别。

    Objective-C只需在UIView子类中重写必要的init方法。要初始化一个UIView框架,就要重写initWithFrame:框架,如下所示:

    @implementation SubUIView
    
      - (id) initWithFrame:(CGRect)frame{
        self = ;
        if (self != nil) {
            // ...
        }
        return self;
      }
      @end
    

    然而Swift需要多一些步骤来重写同一个init方法。首先,重写使用CGRect框架作为其参数的init方法。根据UIView文档,用Swift语言构建时,须重写init(coder:),但我们不需要这种方法,就用如下代码处理。类属性初始化所需的代码可以在init(frame:)中执行。

    class SubUIView: UIView {
      override init(frame: CGRect) {
    
              super.init(frame: frame)
              // ...
    }
        required init?(coder aDecoder: NSCoder) {
              fatalError("init(coder:) has not been implemented")
      }
    }
    

    初始化UIViewController的子类

    子类化UIViewController是iOS开发的重要步骤。使用Interface Builder的开发者需要重写initWithNibName:bundle:,但既然我们用代码来构建UI,就不需要执行这一方法了。只需重写init方法,在其中初始化类属性即可。

    @implementation SubUIViewController
    
    - (id) init{
    self = ;
        if (self != nil) {
            // ...
      }
        return self;
    }
    
      @end
    

    Swift也一样要重写init()方法。实现指定的初始化init(nibName:bundle:)来子类化UIViewController。重申:此过程不适用Interface Builder,所以无需定义nibName和bundle的值,而是调用比指定初始化更简单的convenience初始化,将指定初始化init(nibName:bundle:)设为零。现在调用init()来初始化类,用重写的(nibName:bundle:)执行类属性。

    class SubUIViewController: UIViewController {
    
      convenience init() {
          self.init(nibName: nil, bundle: nil)
    }
    
    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
    
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
        // Initialize properties of class
    }   
    
        required init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
      }
    }
    

    现在可以创建和调用UIViewController的子类,如下所示:

        let viewController: SubUIViewController = SubUIViewController()
        self.navigationController?.pushViewController(viewController, animated: false)
    

    二、使用Auto Layout来实现View

    没有Interface Builder的情况下,就用Auto Layout中的NSLayoutConstraint类来设置View的大小和位置——注意Objective-C和Swift在这里有微妙差别。

    Objective-C使用NSLayoutConstraint类中的constraintWithItem方法。

    + (instancetype)constraintWithItem:(id)view1
                         attribute:(NSLayoutAttribute)attire
                         relatedBy:(NSLayoutRelation)relation
                            toItem:(id)view2
                         attribute:(NSLayoutAttribute)attr2
                        multiplier:(CGFloat)multiplier
                          constant:(CGFloat)c
    

    Swift使用同一个类中的init方法。

    convenience init(item view1: AnyObject,
       attribute attr1: NSLayoutAttribute,
       relatedBy relation: NSLayoutRelation,
          toItem view2: AnyObject?,
       attribute attr2: NSLayoutAttribute,
      multiplier multiplier: CGFloat,
        constant c: CGFloat)
    
    
    如果是Objective-C,则执行以下代码。这段代码将创建NSLayoutConstraint(定义self.profileImageView和self之间的位置),然后添加到self上。
    

    使用Swift也可以创建NSLayoutConstraint,具体如下:

    self.addConstraint(NSLayoutConstraint.init(item: self.profileImageView!, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: self, attribute: NSLayoutAttribute.Leading, multiplier: 1, constant: kMessageCellLeftMargin))
    

    比较两种语言版本你会发现,不同于Objective-C,Swift是从NSLayoutConstraint调用init方法的,而且属性和relatedBy的枚举值也有差别。

    两种语言NSLayoutConstraint中的枚举值分别是:

       NSLayoutAttribute:
    

    Objective-C

    typedef enum: NSInteger {
         NSLayoutAttributeLeft = 1,
         NSLayoutAttributeRight,
         NSLayoutAttributeTop,
         NSLayoutAttributeBottom,
         NSLayoutAttributeLeading,
         NSLayoutAttributeTrailing,     
         NSLayoutAttributeWidth,
         NSLayoutAttributeHeight,
         NSLayoutAttributeCenterX,
         NSLayoutAttributeCenterY,
         NSLayoutAttributeBaseline,
         NSLayoutAttributeLastBaseline = NSLayoutAttributeBaseline,
         NSLayoutAttributeFirstBaseline,
         NSLayoutAttributeLeftMargin,
         NSLayoutAttributeRightMargin,
         NSLayoutAttributeTopMargin,
         NSLayoutAttributeBottomMargin,
         NSLayoutAttributeLeadingMargin,
         NSLayoutAttributeTrailingMargin,
         NSLayoutAttributeCenterXWithinMargins,
         NSLayoutAttributeCenterYWithinMargins,
         NSLayoutAttributeNotAnAttribute = 0
    } NSLayoutAttribute;
    

    Swift版:

    enum NSLayoutAttribute : Int {
          case Left
          case Right
          case Top
          case Bottom
          case Leading
          case Trailing
          case Width
          case Height
          case CenterX
          case CenterY
          case Baseline
          static var LastBaseline: NSLayoutAttribute { get }
          case FirstBaseline
          case LeftMargin
          case RightMargin
          case TopMargin
          case BottomMargin
          case LeadingMargin
          case TrailingMargin
          case CenterXWithinMargins
          case CenterYWithinMargins
          case NotAnAttribute
    }
    

    NSLayoutRelation:

    Objective-C版:

    enum {
         NSLayoutRelationLessThanOrEqual = -1,
         NSLayoutRelationEqual = 0,
         NSLayoutRelationGreaterThanOrEqual = 1,
    };
    typedef NSInteger NSLayoutRelation;
    

    Swift版:

    enum NSLayoutRelation : Int {
        case LessThanOrEqual
        case Equal
        case GreaterThanOrEqual
    }
    

    三、选择器:

    使用UIButton、NSNotificationCenter、NSTimer等时,使用选择器来分配要执行的方法。在Objective-C中,@selector指令代表使用选择器。

    - (void)test{
          // ...
          mTimer = ;
      }
    
      - (void)timerCallback:(NSTimer *)timer   {    
          // ...
      }
    

    在Swift中,不需要使用指令或字符串来分配方法。

    func test() {
        self.mTimer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: "timerCallback:", userInfo: nil, repeats: true)
    }
    
    func timerCallback(timer: NSTimer) {
        // ...
    }
    

    四、字符串:

    尽管在Swift代码中也可以用Objective-C专门处理字符串的NSString,但要使用以String对象为属性的UITextField上的文本或其他的话,就要清楚NSString和String的区别。

    在Objective-C中,UITextField上的文本为NSString,所以属性的长度就是字符串的长度。

    - (BOOL)textFieldShouldReturn:(UITextField *)textField{
        NSString *message = ;
          if ( > 0) {
           // ...
          }
          return YES;
      }
    

    Swift是没有长度属性的,所以要用characters属性的count属性。

    func textFieldShouldReturn(textField: UITextField) -> Bool {
        let message: String = textField.text!
        if message.characters.count > 0 {
            // ...
        }
       return true
    }
    

    在Objective-C中,我们用 stringWithFormat: 来创建一个格式化字符串。

    但在Swift中,String里没有 stringWithFormat 方法,所以用init(format:_ arguments:)代之。我们可以分配一个与NSString格式化结构相同的格式化字符串来创建一个新字符串,然后给arguments赋以相关的值。

        self.typingLabel?.text = String.init(format: "%d Typingsomething cool...", count)
    

    五、从数据类型得到最小&最大值

    就从数字格式上得到最小和最大值而言,Objective-C和Swift也有差别。Objective-C使用一个预定义宏来得到最小和最大值,但Swift则可以直接从数据类型上得到这些值。Objective-C使用的是如下的宏:

      CGFLOAT_MAX
      CGFLOAT_MIN
      INT32_MAX
      INT32_MIN
      LLONG_MAX
      LLONG_MIN
    

    而Swift则从数据类型上得到最小和最大值,如下:

    CGFloat.max
    CGFloat.min
    Int32.max
    Int32.min
    Int64.max
    Int64.min
    

    六、字典和枚举值:

    Objective-C用NSDictionary来定义NSAttributedString的属性。Swift则用Dictionary而不是NSDictionary,但想为Dictionary分配枚举值的时候,做法稍有不同。

    Objective-C直接为NSDictionary分配键值,如下所示:称为NSUnderlineStyleSingle的枚举值不能作为NSDictionary值直接分配,所以要先用@()将它转换成一个对象。

      NSDictionary *underlineAttribute = @{NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle)};
    

    Swift可以直接为Dictionary分配键值(如下所示)。如果该值定义为AnyObject,那么Swift就跟Objective-C一样不能直接使用枚举值,而是使用rawValue属性代之。

    let underlineAttribute: =
    

    即使使用相同名称的类,也会在两种语言中遇到针对同一功能的不同方法名称,所以以类参考文件为准比较保险。

    如果决定使用Swift,建议先学习其基本知识,并试着将手头现有的Objective-C项目转化为Swift版本练练手。

    相关文章

      网友评论

        本文标题:从Objective-C向Swift转换学习到的经验(转)

        本文链接:https://www.haomeiwen.com/subject/rbbusttx.html