Upgrade to Pro — share decks privately, control downloads, hide ads and more …

如何打造一个让人愉快的框架

Wei Wang
January 10, 2016

 如何打造一个让人愉快的框架

For @swift, Beijing, 2016/01/10

Wei Wang

January 10, 2016
Tweet

More Decks by Wei Wang

Other Decks in Technology

Transcript

  1. ই֜಑᭜ӞӻᦏՈషளጱ
    ੜ਎

    View full-size slide

  2. ֕ᘍᡤکᬯฎӞེ୏ݎ
    ᘏտᦓ...

    View full-size slide

  3. ই֜಑᭜ӞӻᦏՈషளጱ
    ໛ຝ

    View full-size slide

  4. ྎኦށጱ“᫪ৼ”
    > ᗑᕶ᧗࿢
    > ཛྷࣳᥴຉ
    > ੕ᛯපຎ
    > ᥤࢶۖኮ
    ...

    View full-size slide

  5. զӤඳԪᕍંᡦ຅
    ইํᵮݶਫંૣݳ

    View full-size slide

  6. COCOA TOUCH LIBRARY
    ஫ӧԧ ᮎԶଙ
    ᤩಋۖ୚አ޾ .a ෈կ
    ಅඪᯈጱ௣థ

    View full-size slide

  7. Ջԍฎᶉாପ
    (STATIC LIBRARY)

    View full-size slide

  8. Ջԍฎᶉாପ
    (STATIC LIBRARY)
    .a + .h
    ፓຽ෈կ (Object files, .o) ጱ
    ᵞݳ
    ᯈݳᝑଗ१෈կ (.h) ֵአ
    ᱾ളک๋ᕣጱݢಗᤈ෈
    կӾ
    ࣁӞԶӤԧଙ१ጱᒫӣ
    ොପӾݢᚆᬮᚆᥠک

    View full-size slide

  9. ᔮᕹ໛ຝ
    .FRAMEWORK

    View full-size slide

  10. Ջԍฎۖா໛ຝ
    (DYNAMIC FRAMEWORK)
    ਂࣁԭᔮᕹٖ᮱
    ᬩᤈ෸᭗ᬦ dyld ۖா᱾

    ӧᵱᥝ᯿ෛے᫹
    ፗک iOS 8҅ݝํ Apple ګ֢
    ጱ໛ຝ಍ᚆֵአۖாොୗ

    View full-size slide

  11. UNIVERSAL FRAMEWORK
    զڹጱӞԶᒫӣො໛ຝԞ൉
    ׀ .framework ෈կ
    ਫᨶӤฎ಑۱ጱᶉாପ1 2
    2 https://github.com/jverkoey/iOS-Framework
    1 https://github.com/kstenerud/iOS-Universal-Framework

    View full-size slide

  12. LIBRARY V.S. FRAMEWORK

    View full-size slide

  13. COCOA TOUCH
    FRAMEWORK
    iOS 8 ୏তᚆڠୌۖா໛ຝ
    Swift ໛ຝጱࠔӞᭌೠ
    (ࢩԅ Runtime ᴴګ)

    View full-size slide

  14. ۱޾ׁᩢᓕቘ

    View full-size slide

  15. COCOAPODS3
    3 http://cocoapods.org

    View full-size slide

  16. զڹ
    workspace + libPod.a
    ୏ݎᘏ᭗ᬦ PodSpec ຽᦩᶱፓ
    አಁֵአ Podfile ೰ਧֵአጱ໛ຝ
    ץදᶱፓ෈կ̵Build Phase ޾ᚕ๜຅
    ୌᶉாପ
    “׍فୗ”ጱᵞ౮ොୗ

    View full-size slide

  17. ๋ᬪ
    From 0.36.0 - Swift ޾ۖா໛ຝඪ೮
    use_frameworks!

    View full-size slide

  18. ๋ᬪ
    From 0.36.0 - Swift ޾ۖா໛ຝඪ೮
    use_frameworks!
    ᬯӻᭌᶱտਖ਼ᶱፓׁᩢق᮱දԅ
    framework
    None or All

    View full-size slide

  19. ֵአ COCOAPODS
    # Podfile
    platform :ios, '8.0'
    use_frameworks!
    target 'MyApp' do
    pod 'AFNetworking', '~> 2.6'
    pod 'ORStackView', '~> 3.0'
    pod 'SwiftyJSON', '~> 2.3'
    end
    $ pod install

    View full-size slide

  20. CARTHAGE4
    4 https://github.com/Carthage/Carthage

    View full-size slide

  21. Րඪ೮ Framework
    ᶋ׍ف҅ӧදݒᶱፓ෈կ
    ݄Ӿஞ۸҅ፗള՗ git ՙପ឴ݐ

    View full-size slide

  22. ֵአ CARTHAGE
    # Cartfile
    github "ReactiveCocoa/ReactiveCocoa"
    github "onevcat/Kingfisher" ~> 1.8
    github "https://enterprise.local/hello/repo.git"
    $ carthage update

    View full-size slide

  23. SWIFT
    PACKAGE
    MANAGER5
    5 https://swift.org/package-manager/

    View full-size slide

  24. API ᦡᦇ
    ᘍᡤ൉׀ᕳ୏ݎᘏጱٖ਻

    View full-size slide

  25. API ᦡᦇ
    ᘍᡤ൉׀ᕳ୏ݎᘏጱٖ਻
    ੱݢᚆੜጱᦢᳯ๦ᴴ
    // Do this
    public func mustMethod() { ... }
    func onlyUsedInFramework() { ... }
    private func onlyUsedInFile() { ... }
    // Don't do this
    public func mustMethod() { ... }
    public func onlyUsedInFramework() { ... }
    public func onlyUsedInFile() { ... }

    View full-size slide

  26. API ᦡᦇ
    ޸ݷ҅ฎވႴศฃ౜ਠෆ

    View full-size slide

  27. API ᦡᦇ
    ޸ݷ҅ฎވႴศฃ౜ਠෆ
    ႴศกᏟጱ޸ݷ
    // Do this
    public mutating func removeAt(position: Index) -> Element
    // Don't do this
    public mutating func remove(i: Int) -> Element
    // <- index or element?

    View full-size slide

  28. API ᦡᦇ
    ޸ݷ҅ฎވႴศฃ౜ਠෆ
    ႴศกᏟጱ޸ݷ
    // Do this
    public func recursivelyFetch(urls: [(String, Range)]) throws -> [T]
    // Don't do this
    public func fetch(urls: [(String, Range)]) throws -> [T] // <- how?

    View full-size slide

  29. API ᦡᦇ
    ޸ݷ҅ฎވႴศฃ౜ਠෆ
    ႴศกᏟጱ޸ݷ
    public var displayName: String
    public var screenName: String // <- Better
    // Don't do this
    public func displayName() -> String
    // <- noun or verb? Why returning `String`?

    View full-size slide

  30. API ᦡᦇ
    ޸ݷ҅ฎވႴศฃ౜ਠෆ
    ੤ᦶԅ֦ጱොဩٟဳ᯽෈໩
    Ӟݙᦾ෫ဩᤒᬿႴ༩ᬯӻොဩٍ֛؉ԧՋԍ -> ᧗ᘍᡤ᯿຅
    ቘమᇫாғդᎱӧᵱᥝ෈໩੪ᚆᤩ፡౜

    View full-size slide

  31. API ᦡᦇ
    ޸ݷ҅ฎވႴศฃ౜ਠෆ
    SWIFT API DESIGN GUIDELINES
    HTTPS://SWIFT.ORG/DOCUMENTATION/API-DESIGN-GUIDELINES.HTML

    View full-size slide

  32. API ᦡᦇ
    սضၥᦶ҅ၥᦶḝۖ୏ݎ

    View full-size slide

  33. API ᦡᦇ
    սضၥᦶ҅ၥᦶḝۖ୏ݎ
    // In Test Target
    import XCTest
    @testable import YourFramework
    class FrameworkTypeTests: XCTestCase {
    // ...
    }

    View full-size slide

  34. ୏ݎ෸ጱᭌೠ
    ޸ݷ٫ᑱ
    // F1.framework
    extension UIImage {
    public method() { print("F1") }
    }
    // F2.framework
    extension UIImage {
    public method() { print("F2") }
    }

    View full-size slide

  35. ୏ݎ෸ጱᭌೠ
    ޸ݷ٫ᑱ - CASE 1
    // app
    import F1
    import F2
    UIImage().method()
    // Ambiguous use of 'method()'

    View full-size slide

  36. ୏ݎ෸ጱᭌೠ
    ޸ݷ٫ᑱ - CASE 2
    // app
    import F1
    UIImage().method()
    // ᬌڊ F2 ҁᕮຎӧᏟਧ҂

    View full-size slide

  37. ୏ݎ෸ጱᭌೠ
    ੒ԭ COCOA ᔄࣳጱ extension
    ஠ᶳႲےڹᖗ

    View full-size slide

  38. ୏ݎ෸ጱᭌೠ
    ޸ݷ٫ᑱ
    // Don't do this
    // F1.framework
    extension UIImage {
    public method() { print("F1") }
    }
    // F2.framework
    extension UIImage {
    public method() { print("F2") }
    }

    View full-size slide

  39. ୏ݎ෸ጱᭌೠ
    ޸ݷ٫ᑱ
    // Do this
    // F1.framework
    extension UIImage {
    public f1_method() { print("F1") }
    }
    // F2.framework
    extension UIImage {
    public f2_method() { print("F2") }
    }

    View full-size slide

  40. ୏ݎ෸ጱᭌೠ
    ᩒრ BUNDLE
    let bundle =
    NSBundle(forClass: ClassInFramework.self)
    let path =
    bundle.pathForResource("resource", ofType: "png")
    YourApp.app/Frameworks/YourFramework.framework/
    resource.png

    View full-size slide

  41. COCOAPODS
    pod spec create MyFramework
    Pod::Spec.new do |s|
    s.name = "MyFramework"
    s.version = "1.0.2"
    s.summary = "My first framework"
    s.description = <<-DESC
    It's my first framework.
    DESC
    s.ios.deployment_target = "8.0"
    s.source = { :git => "https://github.com/onevcat/myframework.git",
    :tag => s.version }
    s.source_files = "Class/*.{h,swift}"
    s.public_header_files = ["MyFramework/MyFramework.h"]
    end

    View full-size slide

  42. COCOAPODS
    ൉Իک CocoaPods
    # ಑ tag
    git tag 1.0.2 && git push origin --tags
    # podspec ෈ဩ༄ັ
    pod spec lint MyFramework.podspec
    # ൉Իک CocoaPods Ӿஞՙପ
    pod trunk push MyFramework.podspec

    View full-size slide

  43. SWIFT PM
    ਖ਼რ෈կනف Sources Ӿ
    // Package.swift
    import PackageDescription
    let package = Package(
    name: "MyKit",
    dependencies: [
    .Package(url: "https://github.com/onevcat/anotherPacakge.git",
    majorVersion: 1)
    ]
    )

    View full-size slide

  44. ᇇ๜ᓕቘ
    # Podfile
    pod 'AFNetworking', '~> 2.6.1'
    # 2.6.x ّ਻ (2.6.1, 2.6.2, 2.6.9 ᒵ҅ӧ۱ތ 2.7)
    # Podfile
    pod 'AFNetworking', '~> 2.6'
    # 2.x ّ਻ (2.6.1, 2.7, 2.8 ᒵ҅ӧ۱ތ 3.0)
    # Cartfile
    github "Mantle/Mantle" >= 1.1
    # य़ԭᒵԭ 1.1 (1.1҅1.1.4, 1.3, 2.1 ᒵ)

    View full-size slide

  45. ᇇ๜ّ਻
    SEMANTIC VERSIONING8
    x(major).y(minor).z(patch)
    8 http://semver.org

    View full-size slide

  46. ᇇ๜ّ਻
    > major - لو API දۖ౲ᘏڢٺ
    > minor - ෛႲےԧلو API
    > patch - bug ץྋᒵ
    > 0.x.y ݝ᭽ਝ๋ݸӞ๵

    View full-size slide

  47. ᇇ๜ّ਻
    ֵአ git tag ᬰᤈᇇ๜ຽᦕ
    ֦ጱአಁ/۱ᓕቘᔮᕹ๗๕ݳቘጱّ
    ਻ᇇ๜

    View full-size slide

  48. ᇇ๜ّ਻
    // MyFramework.h
    //! Project version string for MyFramework.
    FOUNDATION_EXPORT const unsigned char MyFrameworkVersionString[]; // 1.8.3
    //! Project version number for MyFramework.
    FOUNDATION_EXPORT double MyFrameworkVersionNumber; // 347
    // Exported module map
    //! Project version number for MyFramework.
    public var MyFrameworkVersionNumber: Double
    // ଚဌํ੕ڊ MyFrameworkVersionString

    View full-size slide

  49. ೮ᖅᵞ౮
    ᭌೠݳᭇጱ CI ሾह
    TRAVIS CI, CIRCLE CI, COVERALLS, CODECOV...

    View full-size slide

  50. ᛔۖ۸ጱݎ૲ၞᑕ
    FASTLANE9
    9 https://fastlane.tools

    View full-size slide

  51. ᛔۖ۸ጱݎ૲ၞᑕ
    # Fastfile
    desc "Release new version"
    lane :release do |options|
    target_version = options[:version]
    raise "The version is missed." if target_version.nil?
    ensure_git_branch # Ꮯᦊ master ړඪ
    ensure_git_status_clean # Ꮯᦊဌํ๚൉Իጱ෈կ
    scan # ᬩᤈၥᦶ
    sync_build_number_to_git # ਖ਼ build ݩᦡԅ git commit හ
    increment_version_number(version_number: target_version) # ᦡᗝᇇ๜ݩ
    version_bump_podspec(path: "Kingfisher.podspec",
    version_number: target_version) # ๅෛ podspec
    git_commit_all(message: "Bump version to #{target_version}") # ൉Իᇇ๜ݩץද
    add_git_tag tag: target_version # ᦡᗝ tag
    push_to_git_remote # വᭆک git ՙପ
    pod_push # ൉Իک CocoaPods
    end
    $ fastlane release version:1.8.4

    View full-size slide

  52. ᛔۖ۸ጱݎ૲ၞᑕ
    ݚक़ጱֺৼғ
    AFNETWORKING/FASTLANE

    View full-size slide

  53. ڠୌӞӻսᐹጱ໛ຝ
    ෈໩҅ဳ᯽҅ၥᦶ҅դᎱᨶᰁ҅
    ๅෛ෭ப҅issue ߥଫ᭛ଶ...

    View full-size slide

  54. ڠୌӞӻսᐹጱ໛ຝ
    ෈໩҅ဳ᯽҅ၥᦶ҅դᎱᨶᰁ҅
    ๅෛ෭ப҅issue ߥଫ᭛ଶ...
    COCOAPODS QUALITY
    HTTPS://COCOAPODS.ORG/PODS/KINGFISHER/QUALITY
    QUALITY INDEXES GUIDE

    View full-size slide

  55. ݢᚆጱᳯ᷌
    ّ਻௔כᦤ (database҅Key-archiving)

    View full-size slide

  56. ݢᚆጱᳯ᷌
    ᯿॔۱ތ
    ਖ਼ EMBEDDED_CONTENT_CONTAINS_SWIFT
    ᦡᗝԅ NO
    ӧᥝਖ਼ׁᩢጱ framework copy ک
    Framework Ӿ

    View full-size slide

  57. ݢᚆጱᳯ᷌
    ෫ဩّ਻ጱ໛ຝׁᩢ10
    10 Dependency Hells

    View full-size slide

  58. ݢᚆጱᳯ᷌
    Framework ے᫹᭛ଶ 11 12
    12 rdar://22948371
    11 App launch time increased

    View full-size slide

  59. ݢᚆጱᳯ᷌
    Swift ᇇ๜ๅෛ

    View full-size slide

  60. ՗Քॠ୏ত୏ݎ໛ຝ

    View full-size slide

  61. WRITE THE CODE
    CHANGE THE WORLD

    View full-size slide