iOS 基於CTMediator的組件化方案

目錄

1.創建私有 Spec Repo

2.新建工程(New Project)

3.你需要創建podspec文件

4.設置podspec文件

5.創建提交update.sh腳本

6.CTMediator組件化需要創建的幾個類

總結

遇到的問題


 

看了衆多的組件化方案後,我選擇了Casa Taloyum 的 CTMediator 的組件化方案。沒有別的原因,就因爲耦合度低,而且維護成本低。感謝作者的啓發。

創建步驟如下:

 

1.創建私有 Spec Repo

什麼是Spec Repo?它是所有Pod的一個索引,就是一個容器,所有公開的Pods都放在這裏面。我的理解是:他是一個倉庫,我們自己創建的庫可以從這裏查找到,別人沒有引用這個這個倉庫,他就找不到我們私有的組件。

pod repo add [私有Pod源倉庫名字] [私有Pod源的repo地址]

例如:pod repo add SASpecs http://***/***/SASpecs.git

如果成功創建了,我們就可以在~/.cocoapods/repo目錄下看到 SASpecs這個目錄了

 

2.新建工程(New Project)

創建你需要的組件模塊,然後 git clone 到本地,完成你需要的功能,然後提交

 

3.你需要創建podspec文件

pod spec create iOS_aaa

 

4.設置podspec文件

#
#  Be sure to run `pod spec lint TestSpec_color.podspec' to ensure this is a
#  valid spec and to remove all comments including this before submitting the spec.
#
#  To learn more about Podspec attributes see https://guides.cocoapods.org/syntax/podspec.html
#  To see working Podspecs in the CocoaPods repo see https://github.com/CocoaPods/Specs/
#

Pod::Spec.new do |spec|

  # ―――  Spec Metadata  ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
  #
  #  These will help people to find your library, and whilst it
  #  can feel like a chore to fill in it's definitely to your advantage. The
  #  summary should be tweet-length, and the description more in depth.
  #

  spec.name         = "TestSpec_color" #工程名
  spec.version      = "0.0.8" #版本號,每次發版都需要修改
  spec.summary      = "A short description of TestSpec_color.  aaa "

  # This description is used to generate tags and improve search results.
  #   * Think: What does it do? Why did you write it? What is the focus?
  #   * Try to keep it short, snappy and to the point.
  #   * Write the description between the DESC delimiters below.
  #   * Finally, don't worry about the indent, CocoaPods strips it!
  spec.description  = <<-DESC
                          this is A  #這裏最好寫點東西
                   DESC

  spec.homepage     = "https://github.com/fn512613/TestSpec_color"#主頁
  # spec.screenshots  = "www.example.com/screenshots_1.gif", "www.example.com/screenshots_2.gif"


  # ―――  Spec License  ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
  #
  #  Licensing your code is important. See https://choosealicense.com for more info.
  #  CocoaPods will detect a license file if there is a named LICENSE*
  #  Popular ones are 'MIT', 'BSD' and 'Apache License, Version 2.0'.
  #

  spec.license      = { :type => "MIT", :file => "FILE_LICENSE" }#框架遵守的開源協議
  # spec.license      = { :type => "MIT", :file => "FILE_LICENSE" }


  # ――― Author Metadata  ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
  #
  #  Specify the authors of the library, with email addresses. Email addresses
  #  of the authors are extracted from the SCM log. E.g. $ git log. CocoaPods also
  #  accepts just a name if you'd rather not provide an email address.
  #
  #  Specify a social_media_url where others can refer to, for example a twitter
  #  profile URL.
  #

  spec.author             = { "QPP" => "[email protected]" }#作者
  # Or just: spec.author    = "錢盼盼"
  # spec.authors            = { "錢盼盼" => "[email protected]" }
  # spec.social_media_url   = "https://twitter.com/錢盼盼"

  # ――― Platform Specifics ――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
  #
  #  If this Pod runs only on iOS or OS X, then specify the platform and
  #  the deployment target. You can optionally include the target after the platform.
  #

  # spec.platform     = :ios
  spec.platform     = :ios, "9.0"#最低支持版本

  #  When using multiple platforms
  # spec.ios.deployment_target = "5.0"
  # spec.osx.deployment_target = "10.7"
  # spec.watchos.deployment_target = "2.0"
  # spec.tvos.deployment_target = "9.0"


  # ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
  #
  #  Specify the location from where the source should be retrieved.
  #  Supports git, hg, bzr, svn and HTTP.
  #

  spec.source       = { :git => "https://github.com/fn512613/TestSpec_color.git", :tag => "#{spec.version}" }


  # ――― Source Code ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
  #
  #  CocoaPods is smart about how it includes source code. For source files
  #  giving a folder will include any swift, h, m, mm, c & cpp files.
  #  For header files it will include any header in the folder.
  #  Not including the public_header_files will make all headers public.
  #

  spec.source_files  = "TestSpec_color/TestSpec_color/*.{h,m}"#本地框架文件索引,相對TestSpec_color文件的目錄





  #重要的提醒:
  #當你的庫中有子目錄的時候
  #spec.subspec 'Base' do |ss|
        #ss.source_files = "SchoolAppNotification/SchoolAppNotification/Base/*.{h,m}"
  #end
  #spec.subspec 'Notification' do |ss|
            #ss.source_files = "SchoolAppNotification/SchoolAppNotification/Notification/*.{h,m}"
            #ss.subspec 'ViewModel' do |sss|
              #sss.source_files = "SchoolAppNotification/SchoolAppNotification/Notification/ViewModel/*.{h,m}"
            #end
            #ss.dependency 'SchoolAppNotification/Base'#一些共用的文件都放在這個文件夾裏,防止出現相互引用報錯
  #end

  #spec.resources = 'SchoolAppNotification/SchoolAppNotification/Resources/SchoolAppNotification.bundle' #資源文件






  # spec.exclude_files = "Classes/Exclude"

  # spec.public_header_files = "Classes/**/*.h"


  # ――― Resources ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
  #
  #  A list of resources included with the Pod. These are copied into the
  #  target bundle with a build phase script. Anything else will be cleaned.
  #  You can preserve files from being cleaned, please don't preserve
  #  non-essential files like tests, examples and documentation.
  #

  # spec.resource  = "icon.png"
  # spec.resources = "Resources/*.png"

  # spec.preserve_paths = "FilesToSave", "MoreFilesToSave"


  # ――― Project Linking ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
  #
  #  Link your library with frameworks, or libraries. Libraries do not include
  #  the lib prefix of their name.
  #

  # spec.framework  = "SomeFramework"
  # spec.frameworks = "SomeFramework", "AnotherFramework"

  # spec.library   = "iconv"
  # spec.libraries = "iconv", "xml2"


  # ――― Project Settings ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
  #
  #  If your library depends on compiler flags you can set them in the xcconfig hash
  #  where they will only apply to your library. If you depend on other Podspecs
  #  you can include multiple dependencies to ensure it works.

  spec.requires_arc = true
  #當你需要依賴第三方庫的時候
  #spec.dependency "DZNEmptyDataSet"


  # spec.xcconfig = { "HEADER_SEARCH_PATHS" => "$(SDKROOT)/usr/include/libxml2" }
  # spec.dependency "JSONKit", "~> 1.4"

end

重要:你還需要創建一個FILE_LICENSE文件,裏面寫MIT

5.創建提交update.sh腳本

VersionString=`grep -E 'spec.version.*=' TestSpec_color.podspec`

arr=(${VersionString//\"/ })

version=${arr[2]}

echo "準備提交 ${version}版本"

 

git add .

git ci -m "${version}"

git push

git tag -a "${version}" -m "${version}版本"

git push --tags

pod repo push TestSpecs TestSpec_color.podspec --allow-warnings

pod repo update ~/.cocoapods/repos/TestSpecs/

注意:pod repo push SASpecs SchoolAppNotification.podspec --allow-warnings --use-libraries #發版本 --allow-warnings是有警告也可以編譯通過 --use-libraries有第三方庫的時候需要添加這個參數
pod repo update ~/.cocoapods/repos/TestSpecs/ #更新本地庫,如果不更新,pod search是搜不到最新的版本

 

6.CTMediator組件化需要創建的幾個類

1.首先在VC目錄下創建Target_XXX文件繼承NSObject

2.在Target_XXX文件裏實現創建VC對象方法,可以接受參數

3.新建另一個工程,pod 引入CTMediator,工程裏創建CTMediator Category分類

4.在CTMediator分類中實現創建VC的方法

Target_TimeLine.m
- (UIViewController *)Action_ViewController:(NSDictionary *)params{
    typedef void (^CallbackType)(id);
    CallbackType callback = params[@"callback"];
    CourseTableDetailViewController *vc = [[CourseTableDetailViewController alloc] init];
    vc.callback = callback;
    vc.data = params[@"data"];
    return vc;
}
//創建Target文件是爲了實現VC的創建,以及傳參數

CTMediator+CourseTable.m
- (UIViewController *)TimeLine_ViewControllerWithCallback:(void(^)(NSString *result))callback{
    NSMutableDictionary *params = [[NSMutableDictionary alloc] init];
    params[@"callback"] = callback;
    return [self performTarget:@"TimeLine" action:@"ViewController" params:params shouldCacheTarget:NO];
}

//創建CTMediator是爲了解耦,不引入VC頭文件,還有確定實現VC的方法和所傳的參數
//需要跳轉只要使用CTMediator的分類就可以。從而隔絕了VC與VC之間的引用關係
  • Target_AA文件是創建UIViewController對象,方法可以實現接參,和一些簡單的邏輯處理,這個文件是用來封裝ViewController
  • Category文件target參數是Target_AA文件中的AA、
  • action是- (UIViewController *)Action_ViewController:(NSDictionary *)params中的Action_後面的“ViewController”
  • param參數是你需要傳入的參數
  • Category文件需要單獨創建一個工程、因爲這樣可以防止提交版本的時候互相包含
  • 調用者不需要關心ViewController需要做什麼操作,只需要按照暴露出來的接口初始化就可以了
  • Category可以實例化多個方法
  • 每個有改動需要先上傳版本,然後在工程中刪除Podfile.lock文件,再運行pod install

附上自己創建工程的目錄:

每個模塊都可以獨立運行

 

 

總結

1、這個組件化方案的hard code僅存在於Target對象和Category方法中,影響面極小,並不會泄漏到主工程的業務代碼中,也不會泄漏到業務線的業務代碼中。

2、而且在實際組件化的實施中,也是依據category去做業務線的組件化的。所以先寫category裏的target名字,action名字,param參數,到後面在業務線組件中創建Target的時候,照着category裏面已經寫好的內容直接copy到Target對象中就肯定不會出錯(僅Target對象,並不會牽扯到業務線本身原有的對象)。

3、在這個實踐中,響應者的命名域並沒有泄漏到除了響應者以外的任何地方,這就帶來一個好處,遷移非常方便。

4、實施組件的時候不能使用xib和storyboard文件,需要手寫佈局

5、缺點是有的大模塊打包時間較長

6、每次pod install前 ,先pod repo update ~/.cocoapods/repos/*私有庫*/更新一下repo 刪除pod.lock文件

 

遇到的問題

1.報錯RuntimeError

RuntimeError - [!] Xcodeproj doesn't know about the following attributes {"inputFileListPaths"=>[], "outputFileListPaths"=>[]} for the 'PBXShellScriptBuildPhase' isa.
報這個錯是因爲舊版本的 CocoaPods 無法解析運行一下 sudo gem install cocoapods --pre

2.引用自己或者三方framework或者a文件時候

在podsepc中應該這樣寫:

s.ios.vendored_frameworks = "xxx/**/*.framework"

s.ios.vendored_libraries = "xxx/**/*.a”

3、The 'Pods' target has transitive dependencies錯誤

如果私有庫添加了靜態庫或者dependency用了靜態庫

那麼執行pod lib lint還有pod spec lint時候需要加上—user-libraries選項

4、私有庫已經通過驗證並傳到私有repo也能通過pod search,但是就是pod install失敗。

這時候只要執行pod update 然後去喝杯水就好了。。。

5、[iOS] unknown: Encountered an unknown error (/usr/bin/xcrun simctl list -j devices

錯誤的原因:XCode未設置Command line tools 解決方法:在XCode -> Preferences -> Locations中設置Command line tools。

6、[!]Unable to find the 'TestSpec' repo. If it has not yet been cloned,add it via 'pod repo add'.

看一下你的私有Specs庫的名字是不是寫錯了,我就是少寫了一個s

7、[!] The `TestSpec_color.podspec` specification does not validate.

出現這個問題,是podspec文件哪裏設置的有問題,根據上面的error一步步解決問題,這個也是出現最多的問題。

例如:ERROR | description: The description is empty.

這個需要在description寫點東西

 
 
 
————————————————————————————————————
ps:解決上面的上傳問題,我好像找到了昨天FFmpeg生成.a文件失敗的原因了,👍
 
 
 
 
 
 
 
 
 
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章