コードスニペット(Push通知編 アプリ側)
Push通知のコードスニペット
実装手順
- Push通知の設定
- デバイストークンの送信
- Push通知を受け取る
1. Push通知の設定
iOS7以下とiOS8以上で仕様が違う
import UIKit class RemotePushManager { class func registerForRemoteNotifications(application: UIApplication) { if #available(iOS 8.0, *) { let settings = UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound], categories: nil) application.registerUserNotificationSettings(settings) application.registerForRemoteNotifications() } else { application.registerForRemoteNotificationTypes([.Alert, .Badge, .Sound]) } } }
import UIKit @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { RemotePushManager.registerForRemoteNotifications(application) return true }
2. デバイストークンの送信
自前サーバーへデバイストークンを送信する
//MARK: - リモートプッシュ通知 func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) { let characterSet: NSCharacterSet = NSCharacterSet(charactersInString: "<>") let deviceTokenString: String = (deviceToken.description as NSString) .stringByTrimmingCharactersInSet(characterSet) .stringByReplacingOccurrencesOfString(" ", withString: "") as String print(deviceTokenString) //TODO : デバイストークンの送信 } func application(application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: NSError) { }
3. Push通知を受け取る
import UIKit class RemotePushManager { class func received(application: UIApplication, launchOptions: [NSObject: AnyObject]?) { if let launchOptions = launchOptions { if let aps = launchOptions["aps"] as? [NSObject: AnyObject] { print(aps["alert"]) print(aps["sound"]) print(aps["badge"]) } } } }
import UIKit @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { RemotePushManager.registerForRemoteNotifications(application) if let launchOptions = launchOptions { if let option : NSDictionary = launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey] as? NSDictionary { self.application(application, didReceiveRemoteNotification: option as [NSObject : AnyObject]) } } return true } //Push通知受信時とPush通知をタッチして起動したとき func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) { RemotePushManager.received(application, launchOptions: userInfo) switch application.applicationState { case .Inactive: break case .Active: break case .Background: break } } }
APNSから受信するデータは、下記のようなイメージ
{ "aps":{ "alert": "New Message", "badge": 3, "sound": "sound1.aiff", "content-available": 1 // -> サイレントプッシュ }, "name": "value" }
サーバー側
サーバーサイトは、下記のようなライブラリを使うと便利です。
コードスニペット (UIWebView編)
UIWebViewのコードスニペット
よく使いそうなメソッドをExtension化しました。
import UIKit extension UIWebView { /** UIWebViewを表示する(サーバーのファイル) */ func open(urlString: String) { self.loadRequest(NSURLRequest(URL: NSURL(string: urlString)!)) } /** UIWebViewを表示する(ローカルファイル) */ func openLocalFile(fileName: String, ofType: String) { let path: NSString = NSBundle.mainBundle().pathForResource(fileName, ofType:ofType)! self.open(path as String) } /** ユーザーエージェントの取得 */ func userAgent() -> String { return self.stringByEvaluatingJavaScriptFromString("navigator.userAgent") ?? "" } /** ユーザーエージェントの変更 */ func updateUserAgent(str: String) { if let userAgent = self.stringByEvaluatingJavaScriptFromString("navigator.userAgent") { let customUserAgent = userAgent.stringByAppendingString(" \(str)") let dic = ["UserAgent" : customUserAgent] NSUserDefaults.standardUserDefaults().registerDefaults(dic) } } /** JSの関数を呼ぶ(戻り値なし) */ func jsFunc(jsString: String) { self.stringByEvaluatingJavaScriptFromString(jsString) } /** JSの関数を呼ぶ(戻り値あり) */ func jsFuncCallBack(jsString: String) -> NSDictionary? { let result = self.stringByEvaluatingJavaScriptFromString(jsString) if let resultData = result?.dataUsingEncoding(NSUTF8StringEncoding) { return try! NSJSONSerialization.JSONObjectWithData(resultData, options: NSJSONReadingOptions.MutableContainers) as? NSDictionary } return nil } /** ページ内アンカー移動 */ func internalAnchor(request: NSURLRequest, anchorName: String) { let names = request.URL?.absoluteString.componentsSeparatedByString("#") jsFunc("window.location.hash = \"\(names?.first!)\"") } }
UIWebViewのDelegateをクラス化しました。
import UIKit typealias WebViewDidFinishLoad = (UIWebView) -> () typealias WebViewDidStartLoad = (UIWebView) -> () typealias WebViewDidFailLoadWithError = (UIWebView, NSError?) -> () class WebViewDelegate: NSObject, UIWebViewDelegate { var webViewDidFinishLoad: WebViewDidFinishLoad? var webViewDidStartLoad: WebViewDidStartLoad? var webViewDidFailLoadWithError: WebViewDidFailLoadWithError? func setupWebViewDidFinishLoad(webViewDidFinishLoad: WebViewDidFinishLoad) { self.webViewDidFinishLoad = webViewDidFinishLoad } func setupWebViewDidStartLoad(webViewDidStartLoad: WebViewDidStartLoad) { self.webViewDidStartLoad = webViewDidStartLoad } func setupWebViewDidFailLoadWithError(webViewDidFailLoadWithError: WebViewDidFailLoadWithError) { self.webViewDidFailLoadWithError = webViewDidFailLoadWithError } //MARK: - UIWebViewDelegate //Pageがすべて読み込み終わった時呼ばれるデリゲートメソッド. func webViewDidFinishLoad(webView: UIWebView) { if webViewDidFinishLoad != nil{ if let block = webViewDidFinishLoad { block(webView) } } } //Pageがloadされ始めた時、呼ばれるデリゲートメソッド. func webViewDidStartLoad(webView: UIWebView) { if webViewDidStartLoad != nil{ if let block = webViewDidStartLoad { block(webView) } } } func webView(webView: UIWebView, didFailLoadWithError error: NSError?) { if webViewDidFailLoadWithError != nil{ if let block = webViewDidFailLoadWithError { block(webView, error) } } } }
外部HTMLファイルを読みには、
import UIKit class ViewController: UIViewController { @IBOutlet weak var webView: UIWebView! var webViewDelegate = WebViewDelegate() let requestURL = "http://www.apple.com/jp/iphone-6s/" override func viewDidLoad() { super.viewDidLoad() setup() } override func viewWillAppear(animated: Bool) { super.viewWillAppear(animated) webView.open(requestURL) } func setup() { webViewDelegate.setupWebViewDidStartLoad { (webView) -> () in print(__FUNCTION__) } webViewDelegate.setupWebViewDidFinishLoad { (webview) -> () in print(__FUNCTION__) } webViewDelegate.setupWebViewDidFailLoadWithError { (WebView, error) -> () in print(error) } webView.delegate = webViewDelegate } }
ローカルHTMLファイルを読むには
webView.openLocalFile("index", ofType: "html")
HTMLを直接書くには、
func createHTML() -> String { let sMessage = "Hello" let sMeta = "<meta name=\"viewport\" content=\"initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no\">"; let sStyle = "<style>html,body{background-color:#eaeae9;}p{font-size:14px;font-weight:bold;width:80%;marg in:50px auto;}</style>"; let sHtmlHead = "<head>" + sMeta + sStyle + "</head>"; let sHtmlBody = "<body><p>" + sMessage + "</p></body>"; return "<html>" + sHtmlHead + sHtmlBody + "</html>"; } webView.loadHTMLString(createHTML(), baseURL: nil)
コードスニペット (UIButton編)ボタン押下時のアニメーション
ボタン押下時のアニメーションをつけるコードスニペット
UIButtonのExtensionにアニメーションを追加してみました。
import UIKit extension UIButton{ /** * ボタン押下時のアニメーション */ func pushAnimation() { let defaultButton = self.bounds UIView.animateWithDuration(1.5, delay: 0.0, usingSpringWithDamping: 0.2, initialSpringVelocity: 10, options: UIViewAnimationOptions.CurveEaseInOut, animations: { () -> Void in self.bounds = CGRectMake( defaultButton.origin.x, defaultButton.origin.x, defaultButton.size.width + 40, defaultButton.size.height) }) { (finished) -> Void in self.bounds = CGRectMake( defaultButton.origin.x, defaultButton.origin.x, defaultButton.size.width, defaultButton.size.height) } } }
使い方
@IBAction func tappedButton(sender: UIButton) { sender.pushAnimation() }
コードスニペット (UIView編)プロパティへのショートカット
UIViewのプロパティへのショートカット用のコードスニペット
extension化しました。
extension UIView { /** 上の位置を取得 :returns: 上の位置 */ func top() -> CGFloat { return self.frame.origin.y } /** 右の位置を取得 :returns: 右の位置 */ func right() -> CGFloat { return self.frame.origin.x + self.frame.size.width } /** 下の位置を取得 :returns: 下の位置 */ func bottom() -> CGFloat { return self.frame.origin.y + self.frame.size.height } /** 左の位置の取得 :returns: 左の位置 */ func left() -> CGFloat { return self.frame.origin.x } /** UIViewの幅を取得 :returns: UIViewの幅 */ func width() -> CGFloat { return self.frame.size.width } /** UIViewの高さを取得 :returns: UIViewの高さ */ func height() -> CGFloat { return self.frame.size.height } /** UIViewのoriginを取得 :returns: UIViewのorigin */ func origin() -> CGPoint { return self.frame.origin } /** UIViewのサイズを取得 :returns: UIViewのサイズ */ func size() -> CGSize { return self.frame.size } }
使い方
print("w : \(self.view.width()) - h : \(self.view.height())")
コードスニペット(Carthageインストール、設定編)
Carthageインストールと設定のコードスニペット
ゴール
Alamofire(通信用ライブラリ)を利用できるようにする。
手順
- Carthageのダウンロードとインストール
- 外部ライブラリの導入
- プロジェクトに外部ライブラリを追加
1.Carthageのダウンロードとインストール
以下、ターミナルからコマンドを入力する。 インストール済みの方は、飛ばしてください。
1.1. Homebrewの導入
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" brew update
1.2. Carthageの導入
brew install carthage
2.外部ライブラリの導入
以下、ターミナルからコマンドを入力する。
2.1. ライブラリを導入したいプロジェクトのディレクトリへ移動
2.2. Cartfileを作成
vim Cartfile
2.3. 外部ライブラリの追加 今回は、Alamofireというライブラリを追加する
github "Alamofire/Alamofire"
2.4. 外部ライブラリをビルド
carthage update --platform iOS
上記まで進むと、Buildディレクトリ配下にフレームワークが作られる。 /Carthage/Build/iOS/Alamofire.framework
3.プロジェクトに外部ライブラリを追加
3.1. Buil Phasesタブから、「Linked Frameworks and Library」にある+ボタンを押す
3.2. 「Add Other...」を選択する
3.3. プロジェクトのディレクトリ内から、Carthage/Build/iOSと移動し、ライブラリの.frameworkファイルを選択する
3.4. Build Phasesタブに移動し、+ボタンから、「New Run Script Phase」を選択する
3.5. Shell」の下にある黒い部分に以下のコマンドを記述します。
/usr/local/bin/carthage copy-frameworks
3.6. 「input Files」にて+ボタンを押し、以下のようにframeworkの情報を記述する
$(SRCROOT)/Carthage/Build/iOS/Alamofire.framework
さいごに
あとは、「import Alamofire」すれば利用可能です。
コードスニペット (UIColor編)
テーマ
カラーの指定は、デフォルトで用意されていもの以外は、使いづらい ということで、extensionを作りました。
UIColorのコードスニペット
extension UIColor { //色をRGBで指定する class func rgb(rgbValue: UInt) -> UIColor { return UIColor( red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0, green: CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0, blue: CGFloat(rgbValue & 0x0000FF) / 255.0, alpha: CGFloat(1.0) ) } //画像を繰り返し表示する class func patternImage(fileName: String) -> UIColor { return UIColor(patternImage: UIImage(named: fileName)!) } }
ついでに、画像の色を変える方法も載せておきます。
画像を色ごとにいちいち用意するのが面倒なときは、画像の色ごと変えちゃいましょう。
//画像の色を変更する func changeColorImage() { imageView.image = UIImage(named: "alarm.png")?.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate) imageView.tintColor = UIColor.redColor() }
おすすめ本のご紹介
Amazon.co.jp: 詳細! Swift 2 iPhoneアプリ開発 入門ノート Swift 2 + Xcode 7対応: 大重 美幸: 本
コードスニペット(画像をピンチイン・ピンチアウト、回転、移動したい)
テーマ
UIImageViewをピンチイン・ピンチアウトしたり、回転したり、移動できるようにカスタマイズします。
実装手順
- UIImageViewの拡張クラスを作る
- UIImageViewに1で作成したクラスを指定する
1. UIImageViewの拡張クラスを作る
import UIKit class FlexibleImageView: UIImageView,UIGestureRecognizerDelegate { var scale: Float = 0.0 var rotation: Float = 0.0 var isChange = false var isReset = false var defaultTransform: CGAffineTransform? required init(coder aDecoder: NSCoder) { super.init(coder: aDecoder)! self.setup() } func setup() { self.userInteractionEnabled = true let rotation = UIRotationGestureRecognizer(target: self, action: "doAnimation:") rotation.delegate = self self.addGestureRecognizer(rotation) let pinch = UIPinchGestureRecognizer(target: self, action: "doAnimation:") pinch.delegate = self self.addGestureRecognizer(pinch) self.isChange = false self.scale = 1.0 self.rotation = 0.0 let pan = UIPanGestureRecognizer(target: self, action: "doPanAciton:") self.addGestureRecognizer(pan) } //MARK: - Action func doPanAciton(sender: UIPanGestureRecognizer) { let translation = sender.translationInView(self.superview!) let movedPoint = CGPointMake(self.center.x + translation.x, self.center.y + translation.y) self.center = movedPoint sender.setTranslation(CGPointZero, inView: self) } func doAnimation(sender: UIGestureRecognizer) { if !isChange && sender.state == UIGestureRecognizerState.Began { isChange = true defaultTransform = self.transform } else if isChange && sender.state == UIGestureRecognizerState.Ended { reset() return } if sender.state == UIGestureRecognizerState.Ended { return } if sender.isKindOfClass(UIRotationGestureRecognizer) { self.rotation = Float((sender as! UIRotationGestureRecognizer).rotation) } else { self.scale = Float((sender as! UIPinchGestureRecognizer).scale) } var transform = CGAffineTransformConcat( CGAffineTransformConcat(self.defaultTransform!, CGAffineTransformMakeRotation(CGFloat(self.rotation))), CGAffineTransformMakeScale(CGFloat(self.scale), CGFloat(self.scale))) self.transform = transform } //MARK: - Private func resetAnimation() { if isReset == true { UIView.animateWithDuration(0.2, animations: { () -> Void in self.transform = self.defaultTransform! }) } } func reset() { self.isChange = false self.scale = 1.0 self.rotation = 0.0 NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: "resetAnimation", userInfo: nil, repeats: false) } func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool { return true } }
2. UIImageViewに1.で作成したクラスを指定する
StoryBoardで利用する場合は、Custom ClassのClassに「FlexibleImageView」を指定してください。 あとは、何もしなくても、ピンチイン・ピンチアウト、回転、移動できます。
おすすめ本のご紹介
エントリーにも良いと思います。