$30 off During Our Annual Pro Sale. View Details »

Swiftで行うアプリ開発 ~Objective-CからSwiftへの移行~

Swiftで行うアプリ開発 ~Objective-CからSwiftへの移行~

IBM Watson Summit 2016 Day2 F2-4の
"Swiftのオープンソース化がもたらすアプリケーションの未来とIBMの取り組み - 進化するアプリ開発の新世界へご招待 -"
の後半の資料です。

Taiki Suzuki

May 26, 2016
Tweet

More Decks by Taiki Suzuki

Other Decks in Programming

Transcript

  1. typedef NS_ENUM(NSInteger, TNProfilePath) {! TNProfilePathFollowing,! TNProfilePathFollowers,! TNProfilePathTalk! };! ! TNProfilePath

    profilePath = TNProfilePathTalk;! switch (profilePath) {! case TNProfilePathTalk:! NSLog(@"Talk");! break;! ! case TNProfilePathFollowers:! NSLog(@"Followers");! break;! ! case TNProfilePathFollowing:! NSLog(@"Following");! break;! } 0CKFDUJWF$ͷྫ
  2. let profilePath = TNProfilePath.Talk! switch profilePath {! case .Talk:! print("Talk")!

    ! case .Followers:! print("Followers")! ! case .Following:! print("following")! } ܕਪ࿦
  3. // Objective-C! UIView *view = [UIView new];! view.backgroundColor = [UIColor

    redColor];! ! // Swift! let view = UIView()! view.backgroundColor = .redColor() ܕਪ࿦
  4. TNUserModel *user = ...; // औಘࣦഊͳͲͰnil NSMutableArray *array = [NSMutableArray

    array]; [array addObject:user]; // <- Ϋϥογϡ! 0CKFDUJDF$ͰͷOJMͷѻ͍
  5. TNUserModel *user = ...; // औಘࣦഊͳͲͰnil NSMutableArray *array = [NSMutableArray

    array]; if (user != nil) { [array addObject:user]; } 0CKFDUJDF$ͰͷOJMͷѻ͍
  6. var user: UserModel? = ... // औಘࣦഊͰnil var array =

    [UserModel]() array.append(user) // ίϯύΠϧ࣌఺Ͱ͢ͰʹΤϥʔ 0QUJPOBMܕ
  7. 0QUJPOBMܕ var user: UserModel? = ... var array = [UserModel]()

    if let user = user as? UserModel { array.append(user) }
  8. ɹ// TNProfilePathManager.m! @implementation TNProfilePathManager! ! static NSArray *kPathList = nil;!

    static dispatch_once_t kOnceToken;! ! + (NSString *)pathWithProfilePath:(TNProfilePath)path {! dispatch_once(&kOnceToken, ^{! kPathList = @[! @"/following", // 0! @"/followers", // 1! @"/talk“ // 2! ];! });! return kPathList[path];! } ! @end 0CKFDUJWF$ͷ&OVN
  9. enum ProfilePath: String {! case Following = "/following"! case Followers

    = "/followers"! case Talk = "/talk"! } 3BX7BMVF&OVN
  10. enum ProfilePath {! case Following(userId: Int, limit: Int)! case Followers(userId:

    Int, limit: Int)! case Talk(talkId: Int)! } "TTPDJBUFE7BMVF&OVN
  11. enum ProfilePath {! case Following(userId: Int, limit: Int)! case Followers(userId:

    Int, limit: Int)! case Talk(talkId: Int)! ! var value: String {! switch self {! case .Following(let userId, let limit):! return "/following?userId=\(userId)&limit=\(limit)"! case .Followers(let userId, let limit):! return "/followers?userId=\(userId)&limit=\(limit)"! case .Talk(let talkId):! return "/talk?talkId=\(talkId)"! }! }! } "TTPDJBUFE7BMVF&OVN
  12. - (void)swapIntValues:(NSInteger *)left right:(NSInteger *)right { NSInteger temp = *left;

    *left = *right; *right = temp; } - (void)swapStringValues:(NSString **)left right:(NSString **)right { NSString *temp = *left; *left = *right; *right = temp; } 0CKFDUJWF$ͷྫ
  13. NSInteger a = 10; NSInteger b = 20; [self swapIntValues:&a

    right:&b]; // a = 20, b = 10 NSString *abc = @"abc"; NSString *def = @"def"; [self swapStringValues:&abc right:&def]; // abc = def, def = abc 0CKFDUJWF$ͷྫ
  14. func swapValues<T>(inout left: T, inout _ right: T) { let

    temp = left left = right right = temp } δΣωϦΫε
  15. var a: Int = 10 var b: Int = 20

    swapValues(&a, &b) var abc: String = "abc" var def: String = "def" swapValues(&abc, &def) δΣωϦΫε
  16. UIView *view = ...;! CGRect frame = view.frame;! frame.origin.x *=

    2.0f;! frame.origin.y *= 2.0f;! frame.size.width *= 2.0f;! frame.size.height *= 2.0f;! view.frame = frame; 0CKFDUJWF$ͷྫ
  17. func * (left: CGRect, right: CGFloat) -> CGRect {! return

    CGRect(! x: left.origin.x * right,! y: left.origin.y * right,! width: left.size.width * right,! height: left.size.height * right! )! } ԋࢉࢠͷΦʔόʔϩʔυ
  18. let view: UIView = ...! let frame = view.frame! view.frame

    = frame * 2 ԋࢉࢠͷΦʔόʔϩʔυ
  19. infix operator +- { associativity left precedence 140 }! func

    +- (left: CGFloat, right: CGFloat) -> (CGFloat, CGFloat) {! return (left + right, left - right)! }! ! // (12, 8)! let (plusValue, minusValue) = 10 +- 2 ΧελϜԋࢉࢠ
  20. // Swift 1.2ະຬ class Manager { class var sharedInstance: Manager

    { struct Static { static let instance = Manager() } return Static.instance } } // Swift 1.2Ҏ্ class Manager { static let sharedInstance = Manager() } 4XJGU
  21. // Swift 1.2ະຬ override func touchesBegan(touches: NSSet, withEvent event: UIEvent)

    {} // Swift 1.2Ҏ্ override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {} 4XJGU
  22. // Swift 1.2ະຬ let cell = tableView.dequeueReusableCellWithIdentifier("Cell") as UITableViewCell //

    Swift 1.2Ҏ্ let cell = tableView.dequeueReusableCellWithIdentifier("Cell") as! UITableViewCell 4XJGU
  23. •  2014/08 Swi$ 1.0 •  2014/10 Swi$ 1.1 •  2015/04

    Swi$ 1.2 •  2015/09 Swi$ 2.0 ੒௕εϐʔυ
  24. // Swift 2.0ະຬ if let URL = NSURL(string: "https://...") {

    let request = NSURLRequest(URL: URL) } // Swift 2.0Ҏ্ guard let URL = NSURL(string: "https://...") else { return } let request = NSURLRequest(URL: URL) 4XJGU
  25. let data: NSData = ... // Swift 2.0ະຬ var error:

    NSError? let json = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: &error) if let error = error { println(error) } // Swift 2.0Ҏ্ do { let json = try NSJSONSerialization.JSONObjectWithData(data, options: []) } catch let error as NSError { print(error) } 4XJGU
  26. protocol ImageSettable { var imageView: UIImageView! { get set }

    func setImage(image: UIImage?) } extension ImageSettable { func setImage(image: UIImage?) { imageView.image = image } } class UserInfoView: UIView, ImageSettable { @IBOutlet var imageView: UIImageView! var iconImage: UIImage? { didSet { setImage(iconImage) } } } 4XJGU
  27. •  2014/08 Swi$ 1.0 •  2014/10 Swi$ 1.1 •  2015/04

    Swi$ 1.2 •  2015/09 Swi$ 2.0 •  2015/10 Swi$ 2.1 ੒௕εϐʔυ
  28. •  2014/08 Swi$ 1.0 •  2014/10 Swi$ 1.1 •  2015/04

    Swi$ 1.2 •  2015/09 Swi$ 2.0 •  2015/10 Swi$ 2.1 •  2015/12 Swi$ ΦʔϓϯιʔεԽ ੒௕εϐʔυ
  29. •  2014/08 Swi$ 1.0 •  2014/10 Swi$ 1.1 •  2015/04

    Swi$ 1.2 •  2015/09 Swi$ 2.0 •  2015/10 Swi$ 2.1 •  2015/12 Swi$ ΦʔϓϯιʔεԽ •  2016/03 Swi$ 2.2 ੒௕εϐʔυ
  30. // Swift 2.2ະຬ let selector = Selector("handleTapGesture:") let tapGesture =

    UITapGestureRecognizer(target: self, action: selector) // Swift 2.2Ҏ্ let selector = #selector(UserInfoView.handleTapGesture(_:)) let tapGesture = UITapGestureRecognizer(target: self, action: selector) 4XJGU
  31. // Swift 2.2ͰԼهͷهड़Λ͢ΔͱWarning for var i = 0; i <

    100; i++ { print(i) } for var i = 100; i > 0; i-- { print(i) } // Swift 2.2Ͱ΋Warning͕Ͱͳ͍ for i in 0..<100 { print(i) } for i in 100.stride(to: 0, by: -1) { print(i) } 4XJGU
  32. // UserStatus.swift @objc enum UserStatus: Int { case Launch case

    SendSMS case Registered } // ViewController.m #import ”<ProjectName>-Swift.h" @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; UserStatus status = UserStatusRegistered; } @end 4XJGU
  33. •  2014/08 Swi$ 1.0 •  2014/10 Swi$ 1.1 •  2015/04

    Swi$ 1.2 •  2015/09 Swi$ 2.0 •  2015/10 Swi$ 2.1 •  2015/12 Swi$ ΦʔϓϯιʔεԽ •  2016/03 Swi$ 2.2 h'ps://developer.apple.com/library/ios/documenta<on/Swi./Conceptual/ Swi._Programming_Language/RevisionHistory.html ੒௕εϐʔυ
  34. USZ4XJGU •  ظؒ –  2016/03/02 ʙ 2016/03/04 •  ։࠵৔ॴ – 

    ौ୩ϚʔΫγςΟ΢Τετ 13֊ גࣜձࣾαΠόʔΤʔδΣϯτ
  35. •  Do you believe in magic? The making of try!

    Swi$ Conference Tokyo 2016 –  h'ps://www.natashatherobot.com/try-swi.- conference-tokyo-2016/ •  try! Swi$ શ೔ఔฉ͖ى͜͠·ͱΊ –  h'p://niwatako.hatenablog.jp/entry/ 2016/03/05/022452 •  try! Swi$ ࢿྉ·ͱΊ –  h'p://qiita.com/mishimay/items/ 895d676eb9940d75e639 USZ4XJGU
  36. @interface TNQRCodeViewController: UIViewController! ! @property (weak, nonatomic) IBOutlet UIView* qrCodeReaderView;!

    @property (weak, nonatomic) IBOutlet UIView* mainContainerView;! @property (weak, nonatomic) IBOutlet UIButton *toggleButton;! @property (copy, nonatomic) NSString *userName;! ! - (void)showQRCode;! ! @end! IϑΝΠϧ
  37. extension TNQRCodeViewController {! @IBAction func didTapToggleControl(sender: UIButton) {! showQRCode()! }!

    ! func createQRCode() {! // QRίʔυੜ੒ॲཧ }! } TXJGUϑΝΠϧ
  38. •  .mͷinterface಺ͷpropertyΛ͢΂ͯɺ.hʹҠ͢ •  .mͷϝιουΛ͢΂ͯ.hʹఆٛ͢Δ •  .hΛBridge-Header.h಺Ͱimport͢Δ •  Objec*ve-CͷΫϥεͷExtensionΛੜ੒ •  Extension಺ͰඞཁͳfuncΛ࣮૷͢Δ

    •  l<ProjectName>-Swi$.hzΛObjec*ve-CͰimportͯ͠ɺ ExtensionͷfuncΛݺͿ •  ExtensionʹϝιουΛ͢΂ͯҠߦͰ͖ͨΒɺSwi$ ͰΫϥεΛ࡞Δ 0CKFDUJWF$͔ΒͷҠߦ
  39. •  .mͷinterface಺ͷpropertyΛ͢΂ͯɺ.hʹҠ͢ •  .mͷϝιουΛ͢΂ͯ.hʹఆٛ͢Δ •  .hΛBridge-Header.h಺Ͱimport͢Δ •  Objec*ve-CͷΫϥεͷExtensionΛੜ੒ •  Extension಺ͰඞཁͳfuncΛ࣮૷͢Δ

    •  l<ProjectName>-Swi$.hzΛObjec*ve-CͰimportͯ͠ɺ ExtensionͷfuncΛݺͿ •  ExtensionʹϝιουΛ͢΂ͯҠߦͰ͖ͨΒɺSwi$ ͰΫϥεΛ࡞Δ •  Swi$ͷΫϥεʹ.hͷpropertyΛ͢΂ͯҠ͢ 0CKFDUJWF$͔ΒͷҠߦ
  40. class QRCodeViewController: UIViewController { @IBOutlet weak var qrCodeReaderView: UIView! @IBOutlet

    weak var mainContainerView: UIView! @IBOutlet weak var toggleBu'on: UIBu'on! var userName: String override func viewDidLoad() { super.viewDidLoad() createQRCode() } @IBAc<on func didTapToggleControl(sender: UIBu'on) { showQRCode() } func createQRCode() { // QRίʔυੜ੒ॲཧ } }  TXJGUϑΝΠϧ
  41. + (void)sendLogWithCategoryName:(NSString *)categpryName ! pageId:(NSString *)pageId {! // ϩάૹ৴ͷॲཧ }!

    ! [LogPageCategory sendLogWithCategoryName:@"profile" ! pageId:@"/profile/followers"]; ϩάૹ৴ͷྫ
  42. enum LogPageCategory { case Search (SearchPageId) case Home (HomePageId) case

    Profile (ProfilePageId) case Notification (NotificationPageId) } ϩάૹ৴ͷྫ
  43. protocol PageIdPathGettable { static var CategoryName: String { get }

    var rawValue: Int { get } var value: String { get } var path: String { get } } extension PageIdPathGettable { var path: String { return self.dynamicType.CategoryName + value } } ϩάૹ৴ͷྫ
  44. @objc enum ProfilePageId: Int, PageIdPathGettable { static let CategoryName =

    "profile" case Following case Followers case Talk var value: String { switch self {     case .Following: return "/following" case .Followers: return "/followers" case .Talk: return "/talk” } } } ϩάૹ৴ͷྫ
  45. extension LogPageCategory { var path: String { return pageId.path }

    var categoryName: String { return pageId.dynamicType.CategoryName } private var pageId: PageIdPathGettable { switch self { case .Profile (let pageId): return pageId } } } } ϩάૹ৴ͷྫ
  46. class LogSendManager: NSObject { class func sendLog(logPageCategory logPageCategory: LogPageCategory) {

    let categoryName = logPageCategory.categoryName let path = logPageCategory.path // ϩάΛૹΔॲཧ } } ϩάૹ৴ͷྫ
  47. class LogContainer: NSObject { let category: LogPageCategory init(category: LogPageCategory) {

    self.category = category super.init() } } ϩάΛ0CKFDUJWF$ͱڞଘ
  48. class LogContainer: NSObject { let category: LogPageCategory init(category: LogPageCategory) {

    self.category = category super.init() } class func profile(pageId: ProfilePageId) -> LogContainer { return LogContainer(category: .Profile(pageId)) } } ϩάΛ0CKFDUJWF$ͱڞଘ
  49. class LogSendManager: NSObject { class func sendLog(logPageCategory logPageCategory: LogPageCategory) {

    let categoryName = logPageCategory.categoryName() let path = logPageCategory.path() // ϩάΛૹΔॲཧ } class func sendLog(logContainer logContainer: LogContainer) { sendLog(logPageCategory: logContainer.category) } } ϩάΛ0CKFDUJWF$ͱڞଘ
  50. class LogSendManager: NSObject { class func sendLog(logPageCategory logPageCategory: LogPageCategory) {

    let categoryName = logPageCategory.categoryName() let path = logPageCategory.path() // ϩάΛૹΔॲཧ } class func sendLog(logContainer logContainer: LogContainer) { sendLog(logPageCategory: logContainer.category) } } ϩάΛ0CKFDUJWF$ͱڞଘ
  51. TNUserInfoView *userInfoView = [TNUserInfoView new]; userInfoView.translatesAutoresizingMaskIntoConstraints = NO; [self.contentView addSubview:

    userInfoView]; [self.contentView addConstraints:@[ [NSLayoutConstraint constraintWithItem:userInfoView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeTop multiplier:1.0f constant:0.0f ], [NSLayoutConstraint constraintWithItem:userInfoView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeRight multiplier:1.0f constant:0.0f ], [NSLayoutConstraint constraintWithItem:userInfoView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeBottom multiplier:1.0f constant:0.0f ], [NSLayoutConstraint constraintWithItem:userInfoView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeLeft multiplier:1.0f constant:0.0f ] ]]; 7JFXʹ੍໿Λ͚ͭΔ
  52. TNUserInfoView *userInfoView = [TNUserInfoView new]; userInfoView.translatesAutoresizingMaskIntoConstraints = NO; [self.contentView addSubview:

    userInfoView]; [self.contentView addConstraints:@[ [NSLayoutConstraint constraintWithItem:userInfoView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeTop multiplier:1.0f constant:0.0f ], [NSLayoutConstraint constraintWithItem:userInfoView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeRight multiplier:1.0f constant:0.0f ], [NSLayoutConstraint constraintWithItem:userInfoView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeBottom multiplier:1.0f constant:0.0f ], [NSLayoutConstraint constraintWithItem:userInfoView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeLeft multiplier:1.0f constant:0.0f ] ]]; 7JFXʹ੍໿Λ͚ͭΔ
  53. let userInfoView = UserInfoView() userInfoView.translatesAutoresizingMaskIntoConstraints = false self.contentView.addSubview(userInfoView) self.contentView.addConstraints([ NSLayoutConstraint(item:

    userInfoView, attribute: .Top, relatedBy: .Equal, toItem: self.contentView, attribute: .Top, multiplier: 1, constant: 0), NSLayoutConstraint(item: userInfoView, attribute: .Right, relatedBy: .Equal, toItem: self.contentView, attribute: .Right, multiplier: 1, constant: 0), NSLayoutConstraint(item: userInfoView, attribute: .Left, relatedBy: .Equal, toItem: self.contentView, attribute: .Left, multiplier: 1, constant: 0), NSLayoutConstraint(item: userInfoView, attribute: .Bottom, relatedBy: .Equal, toItem: self.contentView, attribute: .Bottom, multiplier: 1, constant: 0) ]) 7JFXʹ੍໿Λ͚ͭΔ
  54. let userInfoView = UserInfoView() userInfoView.translatesAutoresizingMaskIntoConstraints = false self.contentView.addSubview(userInfoView) self.contentView.addConstraints([ NSLayoutConstraint(item:

    userInfoView, attribute: .Top, relatedBy: .Equal, toItem: self.contentView, attribute: .Top, multiplier: 1, constant: 0), NSLayoutConstraint(item: userInfoView, attribute: .Right, relatedBy: .Equal, toItem: self.contentView, attribute: .Right, multiplier: 1, constant: 0), NSLayoutConstraint(item: userInfoView, attribute: .Left, relatedBy: .Equal, toItem: self.contentView, attribute: .Left, multiplier: 1, constant: 0), NSLayoutConstraint(item: userInfoView, attribute: .Bottom, relatedBy: .Equal, toItem: self.contentView, attribute: .Bottom, multiplier: 1, constant: 0) ]) 7JFXʹ੍໿Λ͚ͭΔ
  55. let userInfoView = UserInfoView() userInfoView.translatesAutoresizingMaskIntoConstraints = false self.contentView.addSubview(userInfoView) self.contentView.addConstraints([ NSLayoutConstraint(item:

    userInfoView, attribute: .Top, relatedBy: .Equal, toItem: self.contentView, attribute: .Top, multiplier: 1, constant: 0), NSLayoutConstraint(item: userInfoView, attribute: .Right, relatedBy: .Equal, toItem: self.contentView, attribute: .Right, multiplier: 1, constant: 0), NSLayoutConstraint(item: userInfoView, attribute: .Left, relatedBy: .Equal, toItem: self.contentView, attribute: .Left, multiplier: 1, constant: 0), NSLayoutConstraint(item: userInfoView, attribute: .Bottom, relatedBy: .Equal, toItem: self.contentView, attribute: .Bottom, multiplier: 1, constant: 0) ]) 7JFXʹ੍໿Λ͚ͭΔ TNUserInfoView *userInfoView = [TNUserInfoView new]; userInfoView.translatesAutoresizingMaskIntoConstraints = NO; [self.contentView addSubview: userInfoView]; [self.contentView addConstraints:@[ [NSLayoutConstraint constraintWithItem:userInfoView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeTop multiplier:1.0f constant:0.0f ], [NSLayoutConstraint constraintWithItem:userInfoView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeRight multiplier:1.0f constant:0.0f ], [NSLayoutConstraint constraintWithItem:userInfoView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeBottom multiplier:1.0f constant:0.0f ], [NSLayoutConstraint constraintWithItem:userInfoView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeLeft multiplier:1.0f constant:0.0f ] ]];
  56. let userInfoView = UserInfoView() self.contentView.addLayoutSubview(view, andConstraints: userInfoView.Top |==| self.contentView.Top |*|

    1 |+| 0, userInfoView.Right |==| self.contentView.Right |*| 1 |-| 0, userInfoView.Left |==| self.contentView.Left |*| 1 |+| 0, userInfoView.Bottom |==| self.contentView.Bottom |*| 1 |-| 0 ) .JTUFS'VTJPO
  57. let userInfoView = UserInfoView() self.contentView.addLayoutSubview(view, andConstraints: userInfoView.Top |==| self.contentView.Top |*|

    1 |+| 0, userInfoView.Right |==| self.contentView.Right |*| 1 |-| 0, userInfoView.Left |==| self.contentView.Left |*| 1 |+| 0, userInfoView.Bottom |==| self.contentView.Bottom |*| 1 |-| 0 ) .JTUFS'VTJPO let userInfoView = UserInfoView() userInfoView.translatesAutoresizingMaskIntoConstraints = false self.contentView.addSubview(userInfoView) self.contentView.addConstraints([ NSLayoutConstraint(item: userInfoView, attribute: .Top, relatedBy: .Equal, toItem: self.contentView, attribute: .Top, multiplier: 1, constant: 0), NSLayoutConstraint(item: userInfoView, attribute: .Right, relatedBy: .Equal, toItem: self.contentView, attribute: .Right, multiplier: 1, constant: 0), NSLayoutConstraint(item: userInfoView, attribute: .Left, relatedBy: .Equal, toItem: self.contentView, attribute: .Left, multiplier: 1, constant: 0), NSLayoutConstraint(item: userInfoView, attribute: .Bottom, relatedBy: .Equal, toItem: self.contentView, attribute: .Bottom, multiplier: 1, constant: 0) ])
  58. public class MisterFusion: NSObject { private let item: UIView? private

    let attribute: NSLayoutAttribute? private let relatedBy: NSLayoutRelation? private let toItem: UIView? private let toAttribute: NSLayoutAttribute? private let multiplier: CGFloat? private let constant: CGFloat? private let priority: UILayoutPriority? private let horizontalSizeClass: UIUserInterfaceSizeClass? private let verticalSizeClass: UIUserInterfaceSizeClass? private let identifier: String? } .JTUFS'VTJPOͷ಺෦
  59. infix operator |==| { associativity left precedence 95 } func

    |==| (left: MisterFusion, right: MisterFusion) -> MisterFusion { return MisterFusion(item: left.item, attribute: left.attribute, relatedBy: .Equal, toItem: right.item, toAttribute: right.attribute, multiplier: nil, constant: nil, priority: nil, horizontalSizeClass: nil, verticalSizeClass: nil, identifier: left.identifier) } .JTUFS'VTJPOͷ಺෦
  60. func addLayoutConstraint(misterFusion: MisterFusion) -> NSLayoutConstraint? { let item: UIView =

    misterFusion.item ?? self let attribute: NSLayoutAttribute = misterFusion.attribute ?? .NotAnAttribute let relatedBy: NSLayoutRelation = misterFusion.relatedBy ?? .Equal let toAttribute: NSLayoutAttribute = misterFusion.toAttribute ?? attribute let toItem: UIView? = toAttribute == .NotAnAttribute ? nil : misterFusion.toItem ?? self let multiplier: CGFloat = misterFusion.multiplier ?? 1 let constant: CGFloat = misterFusion.constant ?? 0 let constraint: NSLayoutConstraint = ... constraint.priority = misterFusion.priority ?? UILayoutPriorityRequired constraint.identifier = misterFusion.identifier addConstraint(constraint) return constraint } .JTUFS'VTJPOͷ಺෦
  61. var Equal: MisterFusion -> MisterFusion? { return { [weak self]

    in guard let me = self else { return nil } return me |==| $0 } } .JTUFS'VTJPOΛ0CKFDUJWF$Ͱ࢖͏
  62. TNUserInfoView *userInfoView = [TNUserInfoView new]; [self.contentView addLayoutSubview:userInfoView andConstraints:@[ userInfoView.Top .Equal(self.contentView.Top)

    .Multiplier(1.0f).Constant(0.0f), userInfoView.Right .Equal(self.contentView.Right) .Multiplier(1.0f).Constant(0.0f), userInfoView.Left .Equal(self.contentView.Left) .Multiplier(1.0f).Constant(0.0f), userInfoView.Bottom.Equal(self.contentView.Bottom).Multiplier(1.0f).Constant(0.0f) ]]; .JTUFS'VTJPOΛ0CKFDUJWF$Ͱ࢖͏
  63. TNUserInfoView *userInfoView = [TNUserInfoView new]; [self.contentView addLayoutSubview:userInfoView andConstraints:@[ userInfoView.Top .Equal(self.contentView.Top)

    .Multiplier(1.0f) .Constant(0.0f), userInfoView.Right .Equal(self.contentView.Right) .Multiplier(1.0f) .Constant(0.0f), userInfoView.Left .Equal(self.contentView.Left) .Multiplier(1.0f) .Constant(0.0f), userInfoView.Bottom .Equal(self.contentView.Bottom) .Multiplier(1.0f) .Constant(0.0f) ]]; .JTUFS'VTJPOΛ0CKFDUJWF$Ͱ࢖͏ TNUserInfoView *userInfoView = [TNUserInfoView new]; userInfoView.translatesAutoresizingMaskIntoConstraints = NO; [self.contentView addSubview: userInfoView]; [self.contentView addConstraints:@[ [NSLayoutConstraint constraintWithItem:userInfoView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeTop multiplier:1.0f constant:0.0f ], [NSLayoutConstraint constraintWithItem:userInfoView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeRight multiplier:1.0f constant:0.0f ], [NSLayoutConstraint constraintWithItem:userInfoView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeBottom multiplier:1.0f constant:0.0f ], [NSLayoutConstraint constraintWithItem:userInfoView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeLeft multiplier:1.0f constant:0.0f ] ]];