はじめに
iOSエンジニアの小菅です。
先日以下の記事とライブラリを公開しました。
はてブもいくつかついた頃に以下のコメントを頂きました!
ということで、前回作ったおかげで簡単に作成できることがすぐ想像できたので作ってしまいました。
のでこのライブラリの使い方と公開までの作業手順の紹介を書いていきます。
インストール方法と使い方
README.mdにも書きましたが、頑張って英語で書いたのでこの記事では日本語で紹介したいと思います。
インストール
CocoaPods
# Podfile
pod "Nuke-WebP-Plugin"
bundle exec pod install
で依存関係も込みでインストールされるかと思います。
Carthage
# Cartfile
github "ryokosuge/Nuke-WebP-Plugin"
carthage update --platform iOS
でインストールされます。
対応OS
現状、iOSのみになっています。
まずは公開させることを目標に作ったので、省きました。
macOSなどにも今後対応させて行きたいと思っています。
ちなみにまだbundle exec pod search Nuke
で調べても出てきません…。
何かしなきゃいけないのか、はたまた時間の問題なのか…
作業手順
今回は先にCarthageに対応させてからCocoaPodsのpodspecファイルを作成してdeployしました。
Carthage対応
まずは普通にプロジェクトを作成します。
その後プロジェクトのルートディレクトリにCartfile
を作成して依存関係を解決していきます。
# Cartfile
github "kean/Nuke" ~> 6.0
git "https://chromium.googlesource.com/webm/libwebp" "v0.6.0"
今回はWebP対応するのでlibwebp
を入れます。
その後carthage update --no-use-binaries
を実行します。
> carthage update --no-use-binaries
*** Fetching Nuke
*** Checking out libwebp at "v0.6.0"
*** Checking out Nuke at "6.0"
*** xcodebuild output can be found in /var/folders/yl/6188sfqd28l1klc_nxby14d40000gn/T/carthage-xcodebuild.bIf38x.log
*** Building scheme "Nuke tvOS" in Nuke.xcodeproj
*** Building scheme "Nuke watchOS" in Nuke.xcodeproj
*** Building scheme "Nuke iOS" in Nuke.xcodeproj
*** Building scheme "Nuke macOS" in Nuke.xcodeproj
上記のようにNuke ${platform}
だけがビルドされます。
libwebp
はどこに行ったかと言うと
> tree -L 3 Carthage
Carthage
├── Build
│ ├── Mac
│ │ ├── Nuke.framework
│ │ └── Nuke.framework.dSYM
│ ├── iOS
│ │ ├── Nuke.framework
│ │ ├── Nuke.framework.dSYM
│ ├── tvOS
│ │ ├── Nuke.framework
│ │ └── Nuke.framework.dSYM
│ └── watchOS
│ ├── Nuke.framework
│ └── Nuke.framework.dSYM
└── Checkouts
├── Nuke
│ └── ~ 省略 ~
└── libwebp
├── AUTHORS
├── Android.mk
├── CMakeLists.txt
├── COPYING
├── Carthage
├── ChangeLog
├── Makefile.am
├── Makefile.vc
├── NEWS
├── PATENTS
├── README
├── README.mux
├── autogen.sh
├── build.gradle
├── cmake
├── configure.ac
├── doc
├── examples
├── extras
├── gradle
├── gradle.properties
├── gradlew
├── gradlew.bat
├── imageio
├── iosbuild.sh
├── m4
├── makefile.unix
├── man
├── src
└── swig
というようにCarthage > Checkouts
の中に入っています。
Nuke.framework
はCarthageおきまりのcopy-framework
のスクリプトでlinkします。
libwebpを使う
libwebp
を使う為にいくつか対応しました。
まずは上記のように HEADER_SEARCH_PATH にCarthage/Checkouts/libwebp
をrecursiveで入力しました。
あとdecode処理を今回Objective-Cで書いたので、module.modulemap
を作成してimportできるようにしました。
framework module NukeWebPPlugin {
umbrella header "Nuke_WebP_Plugin.h"
export *
module * { export * }
}
#import <Foundation/Foundation.h>
//! Project version number for Nuke_WebP_Plugin.
FOUNDATION_EXPORT double Nuke_WebP_PluginVersionNumber;
//! Project version string for Nuke_WebP_Plugin.
FOUNDATION_EXPORT const unsigned char Nuke_WebP_PluginVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <Nuke_WebP_Plugin/PublicHeader.h>
#import "WebPImageDecoder.h"
module.modulemapのpathも設定します。
macroの用意
Nukeが他のOSに対応していたので、あとで対応できるようにmacroを組みました。
#import <TargetConditionals.h>
#ifndef WebPImageMacros_h
#define WebPImageMacros_h
#if !TARGET_OS_IPHONE && !TARGET_OS_IOS && !TARGET_OS_TV && !TARGET_OS_WATCH
#define WEBP_PLUGIN_MAC 1
#else
#define WEBP_PLUGIN_MAC 0
#endif
#if TARGET_OS_IOS || TARGET_OS_TV
#define WEBP_PLUGIN_UIKIT 1
#else
#define WEBP_PLUGIN_UIKIT 0
#endif
#if TARGET_OS_IOS
#define WEBP_PLUGIN_IOS 1
#else
#define WEBP_PLUGIN_IOS 0
#endif
#if TARGET_OS_TV
#define WEBP_PLUGIN_TV 1
#else
#define WEBP_PLUGIN_TV 0
#endif
#endif /* WebPImageMacros_h */
上記のmacroはrs/SDWebImageを参考に作りました。
#import <TargetConditionals.h>
をしないとTARGET_OS_IPHONE
などに値が入らないことに1時間ほど悩みました。
ここみて解決しました。
上記のmacroを組んだ理由ですが、iOSならUIImage
、macOSならNSImage
を使うのでそれの分岐をできるようにしたためです。
以下のようにimport分の分岐を入れました。
#import "WebPImageMacros.h"
#if WEBP_IMAGE_MAC
#import <AppKit/AppKit.h>
#define Image NSImage
#else
#import <UIKit/UIKit.h>
#define Image UIImage
#endif
@interface WebPImageDecoder : NSObject
+ (nullable Image *)decodeData:(nonnull NSData *)data;
@end
PRODUCT_NAMEの変更
Carthageで生成されるフレームワークの名前を変更します。
現状Nuke-WebP-Pluginでプロジェクトを作っていますが、フレームワーク名はNukeWebPPluginにしたかったのでPRODUCT_NAME
を変えました。
carthage build && carthage archive
あとは公開したいheaderファイルをpublicにして完了です。
以下のコマンドでbuildします。
> carthage build --no-skip-current
*** xcodebuild output can be found in /var/folders/yl/6188sfqd28l1klc_nxby14d40000gn/T/carthage-xcodebuild.VUG6a2.log
*** Building scheme "Nuke iOS" in Nuke.xcodeproj
*** Building scheme "Nuke macOS" in Nuke.xcodeproj
*** Building scheme "Nuke tvOS" in Nuke.xcodeproj
*** Building scheme "Nuke watchOS" in Nuke.xcodeproj
*** Building scheme "Nuke-WebP-Plugin iOS" in Nuke-WebP-Plugin.xcodeproj
> carthage archive
*** Found Carthage/Build/iOS/NukeWebPPlugin.framework
*** Found Carthage/Build/iOS/NukeWebPPlugin.framework.dSYM
*** Found Carthage/Build/iOS/F52359E3-6369-3A8D-BB87-A68E74463A24.bcsymbolmap
*** Found Carthage/Build/iOS/03E847A8-D09B-34A9-9FD0-E0D8C28B71AA.bcsymbolmap
*** Found Carthage/Build/iOS/1B2BFE33-28E3-3A89-B4AB-1B6D53B18460.bcsymbolmap
*** Found Carthage/Build/iOS/7A60B7EC-EABB-3D05-9EE1-A38C3A87C51D.bcsymbolmap
*** Created NukeWebPPlugin.framework.zip
CocoaPodsの対応
ここまでくればこちらは案外簡単にすみます。
まずは以下のコマンドでspecファイルを作成します。
> bundle exec pod spec create [ライブラリ名]
そうすると[ライブラリ名].podspec
がディレクトリに作成されるのでこれを以下のように編集します。
> cat Nuke-WebP-Plugin.podspec
Pod::Spec.new do |s|
s.name = "Nuke-WebP-Plugin"
s.version = "1.0.0"
s.summary = "Nuke's WebP plugin which can load and display WebP"
s.homepage = "https://github.com/ryokosuge/Nuke-WebP-Plugin"
s.license = { :type => "MIT", :file => "LICENSE" }
s.author = { "ryokosuge" => "ryo.kosuge@gmail.com" }
s.social_media_url = 'https://twitter.com/ryo_kosuge'
s.platform = :ios, "9.0"
s.source = { :git => "https://github.com/ryokosuge/Nuke-WebP-Plugin.git", :tag => "v#{s.version}" }
s.source_files = "Source/**/*"
s.public_header_files = "Source/**/*.h"
s.requires_arc = true
s.module_name = 'NukeWebPPlugin'
s.dependency 'libwebp', '0.6.0'
s.dependency 'Nuke', '~> 6.0'
s.xcconfig = {
'USER_HEADER_SEARCH_PATHS' => '$(inherited) $(SRCROOT)/libwebp/src'
}
end
CocoaPodsのライブラリ名はpodspecで指定したライブラリ名と同じにする必要があります。
上記の値の詳細は以下のドキュメントを参考にしてください。
module_name
でフレームワークの名前を変更できます。
ファイルのlintは以下のコマンドで確認できます。
> bundle exec pod lib lint Nuke-WebP-Plugin.podspec
-> Nuke-WebP-Plugin (1.0.0)
Nuke-WebP-Plugin passed validation.
問題なければ passed validation.
が表示されます。
Warningが出力された場合
Errorの場合は、フォーマットが正しくなかったりするので修正が必要です。
しかし、Warningが出力されても仕方ないものもあります。
source
のversion
がまだgithubのreleaseにない場合
上記の場合は一旦オプションで--allow-warnings
で回避するわざもありました。
ですが、Warningもできる限りなくすべきなので、多用しないようにしましょう。
Demoアプリの作成
最後にサンプリアプリのプロジェクトを作成します。
ここは適当な名前で大丈夫です。
サンプルプロジェクトを作成後、サンプルのディレクトリにPodfile
を作成して以下のように記述します。
# Demo/Podfile
source 'https://github.com/CocoaPods/Specs.git'
use_frameworks!
platform :ios, '9.0'
target 'Nuke-WebP-Demo' do
pod 'Nuke-WebP-Plugin', :path => '../'
end
ターゲット名とライブラリ名は適時書き換えてください。
サンプルアプリはライブラリで出来ることを確認できるように作成しましょう。
自分は今回WebPの表示ができれば良かったので、UIImageView
を中央に置いてwebp画像を表示する処理をするだけのアプリを作成しました。
CocoaPodsへ登録
上記の状態でまずはgit tag
をうってpushします。
tagは[プロジェクト名].podspec
のversion
の値と同じにしてください。
tagをプッシュしたら最終確認をします。
> bundle exec pod spec lint
-> Nuke-WebP-Plugin (1.0.0)
Analyzed 1 podspec.
Nuke-WebP-Plugin.podspec passed validation.
無事 passed validation
が表示されたら準備完了です。
以下のコマンドを叩いてpushしてください。
> bundle exec pod trunk push [プロジェクト名].podspec
無事反映終わったら以下のようにCocoaPods/Specレポジトリにコミットされているかと思います。
これはpushした後すぐに確認したらこうなっていました。
かなりの頻度でpushされているので不安であればcommitを見るといいかと思います。
アカウント作成
初めてpushする際にアカウント作成が必要です。
以下のコマンドで作成出来ます。
> bundle exec pod trunk register [email] "[user name]"
自分の場合は
> bundle exec pod trunk register ryo.kosuge@gmail.com "Ryo Kosuge"
これで登録終わりです。
登録内容は以下のコマンドで出来ます。
> bundle exec pod trunk me
- Name: Ryo Kosuge
- Email: ryo.kosuge@gmail.com
- Since: January 15th, 15:51
- Pods:
- NukeWebP
- Nuke+WebP
- Nuke-WebP-Plugin
- Sessions:
- January 15th, 15:51 - May 27th, 01:37. IP: 113.43.142.102
自分が作ったライブラリのdeprecateのやり方
今回Nuke-WebP-Pluginを作成したおかげで前回作ったNuke-WebPが必要なくなったのでdeprecateしました。
それのやり方とNuke-WebPの代わりにNuke-WebP-Pluginを使用するように促す方法は以下のコマンドになります。
> bundle exec pod trunk deprecate [deprecateするライブラリ名] --in-favor-of=[使って欲しいライブラリ名]
これで非推奨の設定も完了です。
まだ bundle exec pod search Nuke
などで探しても出てきませんが、CocoaPodsのページでは無事表示されました。
これで無事公開作業は終了です。
終わりに
ということで今回もNuke関連の記事を書きました。
でも今回作ってWebP対応が思いの外、軽くできることが知れて良かったです。
あと他のライブラリたちのpodspecを読むついでにたくさんのソースコードを読めたので大変勉強になりました。
特にテストは凄いなと思いました。
コードリーディングの必要さと楽しさの再確認ができたのが一番の功績かもしれないです。
Pull Requestお待ちしております!