GoogleAnalyticsのiOS SDKをpodspec側のdependencyにすると相性が悪い

GoogleAnalyticsのSDKのラッパーライブラリを作りたい

そのためには、podspec側にdependencyを書いておく必要がある。こんな感じ。

Pod::Spec.new do |s|
  s.name             = 'Example'
  s.version          = '0.1.0'
  s.summary          = 'A short description of Example.'
略
  s.dependency 'Google/Analytics'
end

これでpod installをするとtransitive dependencyのエラーが出てpod installができなくなってしまう。 原因は、GoogleAnalyticsが提供しているライブラリがFramework形式ではなく、.aのstatic libraryのためGoogle様がどうにかしてくれないとどうしようもない。 swiftの場合、use_frameworks!が必要なため、ここで詰まってしまう。

回避策、そしてまた別の問題

Podfile側に下記のworkaroundを入れれば回避可能。 https://github.com/CocoaPods/CocoaPods/issues/3289

pre_install do |installer|
    def installer.verify_no_static_framework_transitive_dependencies; end
end

しかし、pod installはうまくいくけどライブラリはリンクされないため結局ライブラリ側ではGAのSDKが利用できない。 リンクさせるためには、下記のようにpodspec側のxcconfigにFRAMEWORK_SEARCH_PATHSLIBRARY_SEARCH_PATHSなどを追記していかないといけない。実際は、他にも必要だが何が必要かを探して自分で書いていかないといけない。

  s.pod_target_xcconfig = {
    'FRAMEWORK_SEARCH_PATHS' => '"${PODS_ROOT}/Google/Frameworks"'
  }

言語のコミュニティがどうとかどうでもいい

当方、iOSをobjcからやってて、Androidも少し。フロントエンドは、jqueryの頃から、typescriptあたりまでなんとなく。 サーバーは、RailsScala Play frameworkあたりを少々。 今はインフラ周り、AWSGCP、コンテナ周りは、docker、k8s、ECS、Deisなどを、少々かじっております。

で、

Scalaの話でなんかコミュニティがどうこうで揉めてるのを見て、なんかほんと、どうでもいいことで争ってる。言語なんてなんだっていいんだよ。ある言語をわかってる人は、いざやってみたら多分どのパラダイムでも、すぐ理解できる。分からないってなら、多分何やっても分からない。

なんていうか、外野のあーだこーだ、コミュニティがどうこうなんてどうでもいい。第一線の人たちは一般人なんかシカトでいいです。

ほんと、みんなすごい人たちなんだから、一般人がどうこうとか、コミュニティ怖いとかどうでもいい。みなさんは、ソフトウェアを作って欲しい。ぼくたちみたいな一般人なんて相手にしなくていいよ。

日本で有名な人たちは、一般人なんて相手にしなくていいから、日本発、すごいソフトウェアをみんな作ってて欲しい><

外国では次から次へと有名なソフトウェアが生まれて、何も生み出さない自分を悔しく思って。 こんな何もできない自分に比べてもっとすごい人たちが、なんか、しょうもないあーだこーだに巻き込まれてるのはもったいないし、損失だなと。

Objective-Cのallocは何をしてるのか

allocはNSObjectのクラスメソッド

alloc - NSObject | Apple Developer Documentation

+ (instancetype)alloc;

The isa instance variable of the new instance is initialized to a data structure that describes the class; memory for all other instance variables is set to 0.

初期化前にメモリを確保。なのでこの時点で一応インスタンスはできている。でも初期化はされてない。サイズは確保されてない状態ってことだと思う。initして初めてサイズが確保される。なので、allocの返り値の型とinitの返り値の型は同じ。

Swiftの場合、 Hoge() ってやると、[[Hoge alloc] init]; まで呼ばれるのでallocを意識することはない。

allocationの説明

developer.apple.com

isaとは

http://algorithm.com.au/downloads/talks/objective-c-internals/objective-c-internals.pdf

In other words, an NSObject is simply a struct with a single field, named isa (“is a”, as in “a car is a vehicle”) that points to some sort of Class type.

AnyClassの正体

AnyObjectの型

typealias AnyClass = AnyObject.Type

何か分からないものの型を表現してる。

参考

Swifter - Swift Must Know Tips

kubernetesでserviceのselectorはnamespace内に閉じてるのか検証

まとめ

  • 同じlabel名がつけられていてもnamespace内でのみ振り分けられる

検証の構成

  • GKE上で試した
  • Deploymentでただ単にnginxかapacheが動いてるだけ
  • sandbox1ではnginx、sandbox2ではapacheが動いてる
  • Service(LoadBalancer)で接続
  • labelは同名にする
namespace: sandbox1

| Service |
     |
     | app: sandbox-webserver
     ▼
| nginx |

------------------------------
namespace: sandbox2
| Service |
     |
     | app: sandbox-webserver
     ▼
| apache |

ディレクトリ構成

├── sandbox1
│   ├── Chart.yaml
│   └── templates
│       ├── deployment.yaml
│       ├── namespace.yaml
│       └── service.yaml
├── sandbox2
│   ├── Chart.yaml
│   └── templates
│       ├── deployment.yaml
│       ├── namespace.yaml
│       └── service.yaml

検証コード(sandbox1)

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: web
  namespace: sandbox1
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: sandbox-webserver
    spec:
      containers:
      - name: web
        image: bitnami/nginx:latest
        ports:
        - containerPort: 80
apiVersion: v1
kind: Service
metadata:
  name: web
  namespace: sandbox1
spec:
  ports:
  - name: http
    port: 80
    targetPort: 80
    protocol: TCP
  type: LoadBalancer
  selector:
    app: sandbox-webserver

検証コード(sandbox2)

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: web
  namespace: sandbox2
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: sandbox-webserver
    spec:
      containers:
      - name: web
        image: bitnami/apache:latest
        ports:
        - containerPort: 80
apiVersion: v1
kind: Service
metadata:
  name: web
  namespace: sandbox2
spec:
  ports:
  - name: http
    port: 80
    targetPort: 80
    protocol: TCP
  type: LoadBalancer
  selector:
    app: sandbox-webserver

Swiftで動的にクラス作ってメソッド呼ぶ。しかも全く型情報がない状態で。要はjavascriptみたいなことがしたい

まとめ

  • NSSClassFromString使う
  • 引数が3つ以上だとperformSelectorは使えない
  • SwiftだとNSInvocationは使えないので代わりにIMPを使う
  • Class methodとInstance methodで呼び方ちょっと違う
  • performSelectorの返り値の型はUnmanaged<AnyObject>takeUnretainedValueを使う

引数が多いときのやり方で参考にしたobjcのコード

github.com

+ (id)initGraphRequestWithGraphPath:(NSString *)graphPath{
    Class FBSDKGraphRequestClass = NSClassFromString (@"FBSDKGraphRequest");
    id graph = [FBSDKGraphRequestClass alloc];
    
    SEL aSelector = NSSelectorFromString(@"initWithGraphPath:parameters:");
    IMP imp = [graph methodForSelector:aSelector];
    id (*func)(id, SEL, id, id) = (void *)imp;
    
    graph = func(graph, aSelector, graphPath, @{});
    return graph;
}

www.b2cloud.com.au

Unmanaged<AnyObject>の取り出し方

stackoverflow.com

var unmanagedObject: Unmanaged = someFunctionThatReturnsAnUnmanagedObject() var newValue: Type = unmanagedObject.takeRetainedValue as Type

takeRetainedValueってやつを使うみたい。でも、アプリがEXC_BAD_ACCESSかなんかだったかで落ちた。 takeUnretainedValueだったら大丈夫だった。

ふーむ。allocしたのに、release漏れてるからとかなんだろうか。Swiftでは普通allocなんて書かないからあんまり普段考えないことだけど。

SwiftでIMPを呼ぶ

stackoverflow.com

unsafeBitCastを使う。

NSClassFromStringでClass methodを呼ぶ

stackoverflow.com

kubernetes meetup Tokyo #4に参加してLT発表してきた #k8sjp

k8sjp.connpass.com

ECSからGKEに乗り換えたい

感想

  • Google Japanの食堂でながーい会場で発表した。人めっちゃいた。
  • kubernetesのserviceまわり、OnlyLocalのことが少し理解できた
  • RBACっていうIAMみたいな機能の話がためになった
  • ServiceAccountもなんなのか分かった
  • ただ、歓談の時間がほとんどなくてあんまり人と話すチャンスがなかった
  • 歓談のときに、kubernetesにしようと思ってたけど当時は難しそうすぎて、docker swarmにしたけど、そろそろkubernetesにしようかなーみたいなこと話せてよかった
  • あと、openshift使ってる人の話も聞けて参考になった
  • etcdが落ちた時、復旧する時にどれを神にすればいいか辛そうという話をしました
  • meetupうちでもやりたいなーって話しかけに行ったんですが400人ぐらい毎回集まっちゃうからでかい会場じゃないと厳しいとのこと、残念><
  • オーケストレーションはkubernetesがデファクトではありますが、みたいな雰囲気をなんとなく感じました
  • AWS上にkubernetesたてるにしても、etcdとかmasterのapi-serverも冗長化するみたいな風にしてやれば意外といけそうではって雰囲気。kube-awsってやつで H/A etcdになるように更新してるみたい