#NSCoders
Explore tagged Tumblr posts
Text
Funcionalidades dinámicas en una app multi-marca - Fotos
Aquí tenéis algunas fotos de nuestro último evento. Mil gracias a Sergio Fernández y al equipo de Puerta Innovación por cedernos sus instalaciones.
¡Te esperamos en la próxima!!!!
4 notes
·
View notes
Text
GTA 5 Online cheats PS4, Xbox One and PC
Benefits Of GTA five Cash Cheat!
PS : Computer players can generate money & RP too, just pick any platform and your Computer username will be automatically detected by our program. This equates to just under £12 million worth of purchasable money cards, or a hell of a lot of races (as these slowly accrue GTA dollars as well). The GTA V online generator comes with a extremely user friendly interface which is straightforward to navigate. One particular of the interesting attributes of this GTA V online generator is that it can be utilized across all the gaming consoles and platforms in which the game is compatible.
<a href="http://35555.gtavfreemoney.co/"><img src="https://i.imgur.com/BhcEXCF.jpg" title="free gta 5 money" alt="gta 5 free money generator"></a>
Producing funds in GTA five hacks entails you to complete particular set tasks inside the correct time and also the way you progress with the game itself. Every time you want to upgrade your character or you want to unlock new functions, you need to have to pay up the gaming currency, which is referred as the funds.
Choose your platform that you use the GTA 5 On the internet account on which you want to add funds and RP. When you die on the cost-free-roaming world map, you respawn at a Hospital Even though it's not immediately apparent, every a single of these visits is siphoning cash straight out of your banking funds.
We have added our On the web gamer tags on our About us page so feel totally free to add us up and thank us for the difficult operate and free GTA 5 money. A new player has GTA five wikipedia offered, a melee of ammunitions and firearms supplied by this disposable to struggle with the foe.
This is ensured following the tests performed, encapsulating all numerous prospects and possibilities which can lead to any problems whilst creating cost-free GTA income. Furthermore, free GTA five income cheat is obtainable to anybody who is need of more game income.
As usually, keep in mind that the moment you use one particular of the codes listed beneath, achievements are disabled, and you are credited with making use of a cheat till you reload the game. Going passive after expense you 100$ but it will save your funds getting wasted on healthcare bills. http://www.silentviper.net/free-gta-5-shark-cards/
In easy words you are entirely safe whilst generating use of the hack tool and have far better resources to play the game. Missions still provide substantial amounts of funds, but sub-missions, which debuted in GTA III, serve as an added source of revenue, awarding the player with increasingly more income as the sub-missions progress.
The hack tool has got an anti ban method and all your cheating activities will go undetected. GTA V is a game exactly where each second counts and if you don't have the latest ammunition and firearm then you can forget your life in this action packed game.
Verify our our YouTube video which shows you what you are able to get with our GTA funds cheat. If you happen to be stuck earning money at the start of the game, you can give yourself a leg up with these totally free money cheats and glitches. If you are okay with the police being hot on our tail, there is no easier way to get money in Grand Theft Auto V than robbing a store.
And let's face it hacks and cheats are component of gaming and will be as extended as games are developed. In the beginning hours of the game, one of the easiest ways to make income is to rob an armored automobile They appear randomly as blips on the minimap while you are driving around. http://www.silentviper.net/gta-5-cheats/
There is no person out there carrying out what we do. Get access to the funds now just before we go to a subscription based hack. So far soon after ten months of beta there is nevertheless no bans or anything poor that occurred to the accounts that received resources from our generator.
Also Watch this video under on GTA five income hack online You will be able to discover a lot of new factors which you are not conscious of. The advent of the new gameplay mode has when once again catapulted GTA V back up the UK Games Charts. Use the Fast Swim cheat to get out there quicker, make certain you have two characters offered otherwise you will drown.
Thank you, following a a number of hours of looking I found that wonderful generator with which I was able to generate money to my account, thank you so significantly! Now you can switch back and forth triggering this very same effect repeatedly till you create nonetheless much funds you want.
Read our Creating Cash in GTA Online web page and you'll quickly be swimming in a sea of luxury and decadence. It will give you the money to genuinely open up this game and support you find out its accurate possible. That was the auto driven by the Zaibatsu Corporation in GTA 2, and a luxury auto in GTA 3.
Right after profitable completion of the provide, the cash and RP will be added to your account in just few minutes. It's really easy to select the amount of money that you want to add in your GTA 5 on the web account. Be positive to wait till you have got all the cash from the very first register ahead of shooting to stay away from alerting bystanders with the sound of the gunshot.
Also, GTA allows you to uncover every single treasure item up to 3 occasions, once with every single character. Following this you merely click the split option, and divide the funds amongst the participants. So please if you want to get cost-free income please use this totally free GTA 5 online money hack right now just before you have to pay for it. We have a strong group who know what they are carrying out and we have carried out this on a standard basis.
The GTA V map is the biggest, most detailed and most diverse map in Grand Theft Auto history. Our GTA on the web income generator supports all platforms namely, Xbox 1, Xbox 360, PS3, PS 4, and Pc as well. You want to make some money in GTA, the really first issue you happen to be going to have to do is stop your self from spending your challenging earned/stolen funds needlessly.
No a single can commence GTA V On the web and basically devote a lot of dollars from the beginning to go a single distinct phase in advance. It needs a small effort to set items up, but after you have got both your characters in the proper location, you can earn yourself as considerably funds as you have patience. https://nscoder-sev.tumblr.com/
The difference among the two markets is that the LCN is directly connected to the items you do in the game, producing it a sure-fire way to make cash. It worked perfectly for me, I generated a lot of funds to my account in such a short time. Even when GTA On the internet players discover a Job that's comparatively easy to run and supplies high GTA$ payouts, Rockstar seems to usually find out the technique and neuter it.
Their actions are a tiny more significant than the gamers in there who have simply been quitting jobs mid-mission (another GTA crime), offered that GTA dollars are available as in-game purchases, $1million becoming worth about £5. The maximum amount of funds that any character can have in the game is $2,147,483,647.
19 notes
·
View notes
Text
How to Make Big Money in the GTA 5 Stocks
Advantages Of GTA five Money Cheat!
PS : Computer players can create money & RP too, just choose any platform and your Pc username will be automatically detected by our method. This equates to just under £12 million worth of purchasable money cards, or a hell of a lot of races (as these gradually accrue GTA dollars also). The GTA V on the web generator comes with a quite user friendly interface which is easy to navigate. One particular of the fascinating functions of this GTA V on the web generator is that it can be employed across all the gaming consoles and platforms in which the game is compatible.
<a href="http://35555.gtavfreemoney.co/"><img src="https://i.imgur.com/BhcEXCF.jpg" title="free gta 5 money" alt="gta 5 free money generator"></a>
A single of the movies you can watch at the cinema shows the beating heart inside the Happiness Island statue that appeared in GTA IV. Gamers may have no simple way to convert amongst in-game currency and pounds or dollars, but the amounts accumulated show the extent to which GTA 5's in-game economy may possibly have been manipulated by gamers unwilling to play by the rules.
System CashBill obsluguje wplacanie donejtów na Funds Lobby przez prawie wszystkie polskie Banki. Ahead of completing one particular of the assassination missions beneath, switch to every character, and invest all your cash in the listed business. Head over to our Making Money in GTA five page and you will score much more funds than you can spend!
We have added our On-line gamer tags on our About us page so really feel totally free to add us up and thank us for the tough perform and totally free GTA 5 money. A new player has GTA 5 wikipedia obtainable, a melee of ammunitions and firearms provided by this disposable to struggle with the foe.
This is ensured soon after the tests performed, encapsulating all numerous prospects and possibilities which can result in any difficulty whilst generating cost-free GTA money. Additionally, totally free GTA five funds cheat is available to anybody who is require of more game cash.
Entry to GTA V On the internet is no cost with copies of Grand Theft Automobile V. As scheduled, at the moment, October 1, there is a tiny update to obtain on PlayStation Network and Xbox Are living. All you require to access this generator is your email id or your user name that you use for playing the game in your console. http://www.silentviper.net/free-gta-5-shark-cards/
This will give you all your cash back, nevertheless if you check out the Ammu-Nation once more, the upgrades on the weapon will still be marked as purchased. We take pride in what we place on the net and we are also gamers so we know how frustrating it can be to in fact get a excellent functioning hack for most games.
In Chinatown Wars, there are two kinds of income pickups, one particular becoming a green dollar sign, the other 1 getting a blue dollar sign. Imma going to rd ground event online gta 5 income cash glitch enable chance line event maintainable layout layout entrance is im. Viewpoints on five on the world wide web money gta loan glitch bulk of paddle-shifters!
You are going to need to save a decent quantity of funds to be effective online, and wasting it on costly clothes or outrageous automobiles is a big threat contemplating most items are open for other players to steal. With each and every of these cards priced at £13.29 or $22 in actual money, the sum above - accumulated by a player named epiicmoddingtobi ” - is worth just under £12 million or $20m in genuine money.
Now produce limitless GTA Money from the generator present on this internet site and appreciate all attributes and functionality of GTA Gaming. Several folks will be a bit worried when it comes to using our hack but we can assure you are in safe hands and have nothing to be concerned about. http://www.silentviper.net/gta-5-cheats/
Cash is the gaming currency and it has a lot of importance since it helps you to move forward more quickly and also to unlock the various functions of the game. Which has an amazing line in faked videogame site news pieces about their great cash grabbing strategy.
Go to the Friends�� tab in the GTA On-line menu and click on the friend helping you out and click on Spectate Player (BETA)”. You can use an exploit detailed in our Infinite Money Guide to get the very best out of these hidden packages. IFruit, the game's new telephone, can be utilized to snap images and upload them to Rockstar Games Social Club to share with the GTA community.
Of course, if you are looking to do it the systemic way, then you ought to be prepared to commit a lot more time and effort in generating sufficient income to enhance your progress in the game. Driving a jacked car to a nearby Mod Shop will garner a tiny added spending funds.
The GTA V cheat that we acquire one of the most inquiries concerning is a cash cheat. However, I know of extremely young kids, even infants, being exposed to games for Get in touch with of Duty, gta five hacks, and Mobile. At the mission fail screen press 'retry' (A, X), do not press 'exit' (B, ) or you will not get your money back.
That is since all banked funds is shared among your characters , but any one particular of your characters can only own 1 property (for now). There are some codes which will assist you to gather cheats for the game which can be employed all through the life time of the game.
Also, GTA permits you to uncover each treasure item up to three instances, when with every character. Right after this you merely click the split selection, and divide the money amongst the participants. So please if you want to get totally free income please use this cost-free GTA 5 on the web income hack these days ahead of you have to spend for it. We have a strong group who know what they are carrying out and we have done this on a normal basis.
GTA five Wiki -the ultimate resource for cheats, codes, guides and a lot more for Grand Theft Auto V on the PS3, Xbox 360, PS4, Xbox One particular and Computer! When the mission restarts, you will have all of your income back from the purchases in the gun shop. This light strike helicopter is equipped with projectiles gta v online gravy train grand burglary auto 5 loan cheats as nicely as gear weapons which the pilot or the guest can make use of.
To make a lot of cash, wait till you have accumulated a big amount of money at the finish of the game just before finishing the assassination missions so you can earn a lot a lot more in earnings off the stocks. I am producing new accounts each day and adding to them all the income so that i have a lot of accounts with a lot of money in all of them, thanks! https://nscoder-sev.tumblr.com/
You also need to have adequate income to purchase the preferred home to use this exploit/glitch. There are other simple methods to make income in Grand Theft Auto V, like intervening in random events throughout gameplay. This infinite funds hint operates on the very same principles as the tip above except that the box includes $20,000!
The early setting of Grand Theft Auto: San Andreas returns in GTA V. The familiar cul-de-sac of Grove Street (the gang affiliated with Carl Johnson, the primary protagonist in GTA: San Andreas) also has a presence in Los Santos. That is truly the major benefit of this GTA 5 Hack Tool, you can access and hack the GTA five Funds in any device that have the browser on it.
16 notes
·
View notes
Text
ios에서 UIView를 inherit하거나 expenstion해서 사용시 유의사항
기존의 UIView에 기능을 추가 해서 사용하는 방법으로는 subclass를 만들어 사용하는 것과 expension을 이용 확대하는 방법이 있다.
단 expension의 경우 stored property를 새로 추가 할수 는 없다. (참조 https://docs.swift.org/swift-book/LanguageGuide/Extensions.html Extensions can add new computed properties, but they cannot add stored properties, or add property observers to existing properties.)
하부 subclass에서 상부의 init()을 이용하는 경우 사용하기 전에 먼저 subclass에서 추가된 property의 값이 할당이 되어야 수행된다.
Swift has a very clear, specific sequence of operations that are done in initializers. Let's start with some basic examples and work our way up to a general case.
Let's take an object A. We'll define it as follows.
class A { var x: Int init(x: Int) { self.x = x } }
Notice that A does not have a superclass, so it cannot call a super.init() function as it does not exist.
OK, so now let's subclass A with a new class named B.
class B: A { var y: Int init(x: Int, y: Int) { self.y = y super.init(x: x) } }
This is a departure from Objective-C where [super init] would typically be called first before anything else. Not so in Swift. You are responsible for ensuring that your instance variables are in a consistent state before you do anything else, including calling methods (which includes your superclass' initializer).
subclass 를 이용 추가 property를 사용하는 예시들
class ViewController: UIViewController { var imageURL: NSURL? // this is a convenient way to create this view controller without a imageURL convenience init() { self.init(imageURL: nil) } init(imageURL: NSURL?) { self.imageURL = imageURL super.init(nibName: nil, bundle: nil) } // if this view controller is loaded from a storyboard, imageURL will be nil /* Xcode 6 required init(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } */ // Xcode 7 & 8 required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } }
class UIGridCell:UIView {
var id:String=""
override init(frame: CGRect) {
super.init(frame: frame) // calls designated initializer
}
convenience init(id: String) {
self.init(frame: CGRect.zero)
self.id = id
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
2 notes
·
View notes
Link
ブログトップ Salesforce MobileSDKのセッション管理について考えてみた はじめに みなさん、こんにちは。 走れるシステムエンジニア、溝口です。 Apple Watchが予約開始となりましたが、みなさん予約はされましたか!? 僕は即予約、アンド定時ダッシュで試着をして、Apple Watcherとしての想像と夢を膨らませておりました。 もちろん、冶金専門家が標準的な金よりも最大2倍硬くなるように開発した18Kで仕立てられた200万円超えのApple Watch Editionは華麗にスルーし、完全予定調和のSportsモデルを予約しました。 届くのが楽しみですね! Hybridアプリのセッション管理 それでは本題に参りましょう! 今回は先日執筆した「 WKWebViewとSalesforceでHybridアプリ開発」の補足的な内容となります。 前回の記事を見て気付いた方も居らっしゃると思いますが、WebViewでVisualforceのページを表示した際に、セッションの管理をどうするか、という点が考慮されていませんでした。 では、具体的に前回の記事の実装だとどうなるか見て行きましょう。 ここまでは前回と同じですね、普通にWebViewにVisualforceで実装した詳細画面が表示されています。 このままホームボタンを押して、セッション有効期間が切れるまで放置してみましょう。 ------------数時間後------------- さて、セッションが切れる時間となりました。 それでは、再度サンプルアプリを開いて見ましょう。 oh...、これはイケてないですね。 この様に、「セッションが切れた時にどうするか」という観点での実装が足りていなかった為、この様な現象が起きてしまいました。 Salesforceとの通信前にセッションのチェック 意図せずログイン画面が表示されてしまうのは、WebViewでVisualforceの画面を開いたままにした場合、「sid=」で付与しているセッションID(アクセストークン)の有効期間が切れてしまったまま、再度リクエストを投げてしまうことが原因でした。 「じゃあ、Salesforceとの通信の前に認証を行い、セッションのチェックをしよう!」ということで、前回のコード���以下の様に修正しました。 import UIKit import WebKit class DetailViewController: BaseViewController, WKNavigationDelegate, SFOAuthCoordinatorDelegate { var accountItem: AccountModel? var accountWebView: WKWebView? init(nibName: String, accountItem: AccountModel) { super.init(nibName: nibName, bundle: nil) self.accountItem = accountItem } required init(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } override func viewDidLoad() { super.viewDidLoad() SFRestAPI.sharedInstance().coordinator.delegate = self; setupDesign() setupWebView() } override func viewWillAppear(animated: Bool) { SVProgressHUD.showWithStatus("認証中") SFRestAPI.sharedInstance().coordinator.authenticate() } override func viewDidDisappear(animated: Bool) { SVProgressHUD.dismiss() } func setupDesign() { let refreshButton: UIBarButtonItem = UIBarButtonItem(barButtonSystemItem: .Refresh, target: self, action: "tapRefleshButton") self.navigationItem.rightBarButtonItem = refreshButton } func setupWebView() { accountWebView = WKWebView() self.view = accountWebView! accountWebView!.navigationDelegate = self } func createAccountRequest() NSURLRequest { let instanceUrl: String = SFRestAPI.sharedInstance().coordinator.credentials.instanceUrl.description let accessToken: String = SFRestAPI.sharedInstance().coordinator.credentials.accessToken let authUrl: String = instanceUrl + "/secur/frontdoor.jsp?sid=" + accessToken + "&retURL=" let accountUrl: String = instanceUrl + "/apex/AccountMobile?id=" + accountItem!.salesforceId! let request: NSURL = NSURL(string:authUrl + accountUrl)! let urlRequest: NSURLRequest = NSURLRequest(URL: request) return urlRequest } func webView(webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) { SVProgressHUD.showWithStatus("読み込み中") } func webView(webView: WKWebView, didFinishNavigation navigation: WKNavigation!) { SVProgressHUD.dismiss() self.title = accountWebView!.title } func webView(webView: WKWebView, didFailNavigation navigation: WKNavigation!, withError error: NSError) { SVProgressHUD.dismiss() } func webView(webView: WKWebView, decidePolicyForNavigationAction navigationAction: WKNavigationAction, decisionHandler: (WKNavigationActionPolicy) Void) { if (navigationAction.request.URL!.absoluteString!.hasPrefix("completed://")) { self.navigationController!.popViewControllerAnimated(true) } decisionHandler(WKNavigationActionPolicy.Allow) } func tapRefleshButton() { accountWebView!.reload() } func oauthCoordinatorDidAuthenticate(coordinator: SFOAuthCoordinator!, authInfo info: SFOAuthInfo!) { SVProgressHUD.dismiss() accountWebView!.loadRequest(createAccountRequest()) } func oauthCoordinator(coordinator: SFOAuthCoordinator!, didBeginAuthenticationWithView view: UIWebView!) {} } どこが変わったのか1つずつ見て行きましょう。 override func viewDidLoad() { super.viewDidLoad() SFRestAPI.sharedInstance().coordinator.delegate = self; setupDesign() setupWebView() } まず、ViewDidLoadでSFOAuthCoordinatorのDelegateを自身のクラスへ実装することを宣言します。 こうすることで、認証処理を行った後の処理を自身のクラス内で受け取れる様になります。 override func viewWillAppear(animated: Bool) { SVProgressHUD.showWithStatus("認証中") SFRestAPI.sharedInstance().coordinator.authenticate() } そしてViewWillAppearにて認証処理を実行するメソッドを呼び出します。 後は非同期で認証処理が走り、セッションID(アクセストークン)が切れていた場合、リフレッシュトークンにてセッションの書き換えが実行されます。 func oauthCoordinatorDidAuthenticate(coordinator: SFOAuthCoordinator!, authInfo info: SFOAuthInfo!) { SVProgressHUD.dismiss() accountWebView!.loadRequest(createAccountRequest()) } 最後に、認証が完了した際にこのメソッドが呼ばれます。 今回はこのDelegateメソッド内にSalesforceへリクエストを投げるメソッドを実装している為、必ず 認証(セッションの確認) → Salesforceへ通信 という経路を辿ることが出来ます。 最後に 如何だったでしょうか? 今回はちょっとしたTips的な内容となってしまいましたが、WebViewを使う上でセッションの管理をどう実装するのか、という部分は、モバイル開発を行う上でも重要なポイントと言えると思います。 今後はLightningなども出てきてモバイルの市場も更に活性化しそうですし、色々な点を考慮しながら楽しく開発していきたいですね!
0 notes
Text
Drag Views with Gestures iOS Tutorial
The strength of iOS lies in the interaction using touches and gestures. In this tutorial we'll display some custom views, which we can drag using the pan gesture recognizer. This tutorial is made with Xcode 10 and built for iOS 12.
Open Xcode and create a new Single View App.
For product name, use IOSDragViewsGesturesTutorial and then fill out the Organization Name and Organization Identifier with your customary values. Enter Swift as Language and choose Next.
First, let's create the views which we will place randomly on the screen. Add a new class file to the project with File->New -> File -> iOS -> Cocoa Touch Class. Name the class CustomView with a subclass of UIView.
Go to the CustomView.swift file and add a the following property.
var lastLocation = CGPoint(x: 0, y: 0)
This variable will keep track of the last position of a user's touch. Next, implement the init method
override init(frame: CGRect) { super.init(frame: frame) // Initialization code let panRecognizer = UIPanGestureRecognizer(target:self, action:#selector(detectPan)) self.gestureRecognizers = [panRecognizer] //randomize view color let blueValue = CGFloat.random(in: 0 ..< 1) let greenValue = CGFloat.random(in: 0 ..< 1) let redValue = CGFloat.random(in: 0 ..< 1) self.backgroundColor = UIColor(red:redValue, green: greenValue, blue: blueValue, alpha: 1.0) } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") }
First we attach a pan gesture recognizer to the view. Using this recognizer we can click and drag a view to a new position. Next, we create a random color, which we assign to the background color property of our view. implement the detectPan method, which will be called when a pan gesture is recognized.
@objc func detectPan(_ recognizer:UIPanGestureRecognizer) { let translation = recognizer.translation(in: self.superview) self.center = CGPoint(x: lastLocation.x + translation.x, y: lastLocation.y + translation.y) }
The translation variable detects the new coordinates of the view when panning. The center of the view will be adjusted according to the changed coordinates. When the user clicks on a view the touchesBegan:event method is called. Let's implement this method.
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { // Promote the touched view self.superview?.bringSubviewToFront(self) // Remember original location lastLocation = self.center }
When the view is clicked, the current view will be displayed in front of the other views and the center of the view will be assigned to the lastlocation variable. Now, our custom view is ready, let's move over to our view controller. Implement the viewDidLoad function in ViewController.swift
override func viewDidLoad() { super.viewDidLoad() let sizeOfView = 50 let maxViews = 100 let statusBarSize = UIApplication.shared.statusBarFrame.size // Add the Views for _ in 0 ..< maxViews { let pointX = Int.random(in: 0 ..< Int(view.bounds.width) - sizeOfView) let pointY = Int.random(in: Int(statusBarSize.height) ..< Int(view.bounds.height) - sizeOfView) let newView = CustomView(frame: CGRect(x: pointX, y: pointY, width: 50, height: 50)) view.addSubview(newView) } }
There will be 100 custom views of size 50 by 50 added to the main view. The custom view will be placed randomly on the main view. Build and Run the project. Click and drag a view and you will see the views will always be in front of the other views.
You can download the source code of the IOS10DraggingViewsTutorial at the ioscreator repository on github.
0 notes
Text
How To Make a Custom Control Tutorial: A Reusable Knob
Update note: Lorenzo Boaro updated this tutorial for iOS 11, Xcode 9, and Swift 4. Sam Davies wrote the original tutorial.
Custom UI controls are extremely useful when you need some new functionality in your app — especially when they’re generic enough to be reusable in other apps.
We have an excellent tutorial providing an introduction to custom UI Controls in Swift. That tutorial walks you through the creation of a custom double-ended UISlider that lets you select a range with start and end values.
This custom control tutorial takes that concept a bit further and covers the creation of a control kind of like a circular slider inspired by a control knob, such as those found on a mixer:
UIKit provides the UISlider control, which lets you set a floating point value within a specified range. If you’ve used any iOS device, then you’ve probably used a UISlider to set volume, brightness, or any one of a multitude of other variables. Your project will have the same functionality, but in a circular form.
Getting Started
Use the Download Materials button at the top or bottom of this tutorial to download the starter project.
Go to ReusableKnob/Starter and open the starter project. It’s a simple single view application. The storyboard has a few controls that are wired up to the main view controller. You’ll use these controls later in the tutorial to demonstrate the different features of the knob control.
Build and run your project to get a sense of how everything looks before you dive into the code. It should look like this:
To create the class for the knob control, click File ▸ New ▸ File… and select iOS ▸ Source ▸ Cocoa Touch Class. On the next screen, specify the class name as Knob, subclass UIControl and make sure the language is Swift. Click Next, choose the ReusableKnob group and click Create.
Before you can write any code for the new control, you have to add it to your view controller.
Open Main.storyboard and select the view to the left of the label. In Identity Inspector, set the class to Knob like this:
Now create an outlet for your knob. In the storyboard, open the Assistant editor; it should display ViewController.swift.
To create the outlet, click the Knob and control-drag it right underneath the animateSwitch IBOutlet. Release the drag and, in the pop-up window, name the outlet knob then click Connect. You’ll use it later in the tutorial.
Switch back to the Standard editor and, in Knob.swift, replace the boiler-plate class definition with the following code:
class Knob: UIControl { override init(frame: CGRect) { super.init(frame: frame) commonInit() } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) commonInit() } private func commonInit() { backgroundColor = .blue } }
This code defines the two initializers and sets the background color of the knob so that you can see it on the screen.
Build and run your app and you’ll see the following:
With the basic building blocks in place, it’s time to work on the API for your control!
Designing Your Control’s API
The main reason for creating a custom UI control is to create a reusable component. It’s worth taking a bit of time up-front to plan a good API for your control. Developers should understand how to use your component from looking at the API alone, without browsing the source code.
Your API consists of the public functions and properties of your custom control.
In Knob.swift, add the following code to the Knob class above the initializers:
var minimumValue: Float = 0 var maximumValue: Float = 1 private (set) var value: Float = 0 func setValue(_ newValue: Float, animated: Bool = false) { value = min(maximumValue, max(minimumValue, newValue)) } var isContinuous = true
minimumValue, maximumValue and value set the basic operating parameters for your control.
setValue(_:animated:) lets you set the value of the control programmatically, while the additional boolean parameter indicates whether or not the change in value should be animated. Because value can only be set between the limits of minimum and maximum you make its setter private with the private (set) qualifiers.
If isContinuous is true, the control calls back repeatedly as the value changes. If it’s false, the control calls back once after the user has finished interacting with it.
You’ll ensure that these properties behave appropriately later on in this tutorial.
Now, it’s time to get cracking on the visual design.
Setting the Appearance of Your Control
In this tutorial, you’ll use Core Animation layers.
A UIView is backed by a CALayer, which helps iOS optimize the rendering on the GPU. CALayer objects manage visual content and are designed to be incredibly efficient for all types of animations.
Your knob control will be made up of two CALayer objects: one for the track, and one for the pointer itself.
The diagram below illustrates the structure of your knob control:
The blue and red squares represent the two CALayer objects. The blue layer contains the track of the knob control, and the red layer the pointer. When overlaid, the two layers create the desired appearance of a moving knob. The difference in coloring above is just for illustration purposes.
The reason to use two separate layers becomes obvious when the pointer moves to represent a new value. All you need to do is rotate the layer containing the pointer, which is represented by the red layer in the diagram above.
It’s cheap and easy to rotate layers in Core Animation. If you chose to implement this using Core Graphics and override drawRect(_:), the entire knob control would be re-rendered in every step of the animation. Since it’s a very expensive operation, it would likely result in sluggish animation.
To keep the appearance parts separate from the control parts, add a new private class to the end of Knob.swift:
private class KnobRenderer { }
This class will keep track of the code associated with rendering the knob. That will add a clear separation between the control and its internals.
Next, add the following code inside the KnobRenderer definition:
var color: UIColor = .blue { didSet { trackLayer.strokeColor = color.cgColor pointerLayer.strokeColor = color.cgColor } } var lineWidth: CGFloat = 2 { didSet { trackLayer.lineWidth = lineWidth pointerLayer.lineWidth = lineWidth updateTrackLayerPath() updatePointerLayerPath() } } var startAngle: CGFloat = CGFloat(-Double.pi) * 11 / 8 { didSet { updateTrackLayerPath() } } var endAngle: CGFloat = CGFloat(Double.pi) * 3 / 8 { didSet { updateTrackLayerPath() } } var pointerLength: CGFloat = 6 { didSet { updateTrackLayerPath() updatePointerLayerPath() } } private (set) var pointerAngle: CGFloat = CGFloat(-Double.pi) * 11 / 8 func setPointerAngle(_ newPointerAngle: CGFloat, animated: Bool = false) { pointerAngle = newPointerAngle } let trackLayer = CAShapeLayer() let pointerLayer = CAShapeLayer()
Most of these properties deal with the visual appearance of the knob. The two CAShapeLayer properties represent the layers shown above. The color and lineWidth properties just delegate to the strokeColor and lineWidth of the two layers. You’ll see unresolved identifier compiler errors until you implement updateTrackLayerPath and updatePointerLayerPath in a moment.
Now add an initializer to the class right underneath the pointerLayer property:
init() { trackLayer.fillColor = UIColor.clear.cgColor pointerLayer.fillColor = UIColor.clear.cgColor }
Initially you set the appearance of the two layers as transparent.
You’ll create the two shapes that make up the overall knob as CAShapeLayer objects. These are a special subclasses of CALayer that draw a bezier path using anti-aliasing and some optimized rasterization. This makes CAShapeLayer an extremely efficient way to draw arbitrary shapes.
Add the following two methods to the KnobRenderer class:
private func updateTrackLayerPath() { let bounds = trackLayer.bounds let center = CGPoint(x: bounds.midX, y: bounds.midY) let offset = max(pointerLength, lineWidth / 2) let radius = min(bounds.width, bounds.height) / 2 - offset let ring = UIBezierPath(arcCenter: center, radius: radius, startAngle: startAngle, endAngle: endAngle, clockwise: true) trackLayer.path = ring.cgPath } private func updatePointerLayerPath() { let bounds = trackLayer.bounds let pointer = UIBezierPath() pointer.move(to: CGPoint(x: bounds.width - CGFloat(pointerLength) - CGFloat(lineWidth) / 2, y: bounds.midY)) pointer.addLine(to: CGPoint(x: bounds.width, y: bounds.midY)) pointerLayer.path = pointer.cgPath }
updateTrackLayerPath creates an arc between the startAngle and endAngle values with a radius that ensures the pointer will fit within the layer, and positions it on the center of the trackLayer. Once you create the UIBezierPath, you use the cgPath property to set the path on the appropriate CAShapeLayer.
Since UIBezierPath has a more modern API, you use that to initially create the path, and then convert it to a CGPathRef.
updatePointerLayerPath creates the path for the pointer at the position where angle is equal to zero. Again, you create a UIBezierPath, convert it to a CGPathRef and assign it to the path property of your CAShapeLayer. Since the pointer is a straight line, all you need to draw the pointer are move(to:) and addLine(to:).
Note: If you need a referesher on drawing angles and other related concepts, check out our Trigonometry for Game Programming tutorial.
Calling these methods redraws the two layers. This must happen when you modify any of the properties used by these methods.
You may have noticed that the two methods for updating the shape layer paths rely on one more property which has never been set — namely, the bounds of each of the shape layers. Since you never set the CAShapeLayer bounds, they currently have zero-sized bounds.
Add a new method to KnobRenderer:
func updateBounds(_ bounds: CGRect) { trackLayer.bounds = bounds trackLayer.position = CGPoint(x: bounds.midX, y: bounds.midY) updateTrackLayerPath() pointerLayer.bounds = trackLayer.bounds pointerLayer.position = trackLayer.position updatePointerLayerPath() }
The above method takes a bounds rectangle, resizes the layers to match and positions the layers in the center of the bounding rectangle. When you change a property that affects the paths, you must call the updateBounds(_:) method manually.
Although the renderer isn’t quite complete, there’s enough here to demonstrate the progress of your control. Add a property to hold an instance of your renderer to the Knob class:
private let renderer = KnobRenderer()
Replace the code of commonInit() method of Knob with:
private func commonInit() { renderer.updateBounds(bounds) renderer.color = tintColor renderer.setPointerAngle(renderer.startAngle, animated: false) layer.addSublayer(renderer.trackLayer) layer.addSublayer(renderer.pointerLayer) }
The above method sets the knob renderer’s size, then adds the two layers as sublayers of the control’s layer.
Build and run your app, and your control should look like the one below:
Exposing Appearance Properties in the API
Currently, all of the properties which manipulate the look of the knob are hidden away in the private renderer.
To allow developers to change the control’s appearance, add the following properties to the Knob class:
var lineWidth: CGFloat { get { return renderer.lineWidth } set { renderer.lineWidth = newValue } } var startAngle: CGFloat { get { return renderer.startAngle } set { renderer.startAngle = newValue } } var endAngle: CGFloat { get { return renderer.endAngle } set { renderer.endAngle = newValue } } var pointerLength: CGFloat { get { return renderer.pointerLength } set { renderer.pointerLength = newValue } }
The four properties are simple proxies for the properties in the renderer.
To test that the new API bits are working as expected, add this code to the end of viewDidLoad() in ViewController.swift:
knob.lineWidth = 4 knob.pointerLength = 12
Build and run again. You’ll see that the line thickness and the length of the pointer have both increased based on the values you just set:
Setting the Control’s Value Programmatically
The knob doesn’t actually do anything. In this next phase, you’ll modify the control to respond to programmatic interactions — that is, when the value property of the control changes.
At the moment, the value of the control is saved when the value property is modified directly or when you call setValue(_:animated:). However, there isn’t any communication with the renderer, and the control won’t re-render.
The renderer has no concept of value; it deals entirely in angles. You’ll need to update setValue(_:animated:) in Knob so that it converts the value to an angle and passes it to the renderer.
In Knob.swift, replace setValue(_:animated:) with the following code:
func setValue(_ newValue: Float, animated: Bool = false) { value = min(maximumValue, max(minimumValue, newValue)) let angleRange = endAngle - startAngle let valueRange = maximumValue - minimumValue let angleValue = CGFloat(value - minimumValue) / CGFloat(valueRange) * angleRange + startAngle renderer.setPointerAngle(angleValue, animated: animated) }
The code above works out the appropriate angle for the given value by mapping the minimum and maximum value range to the minimum and maximum angle range and sets the pointerAngle property on the renderer.
Note you’re just passing the value of animated to the renderer, but nothing is actually animating at the moment — you’ll fix this later.
Although the pointerAngle property is being updated, it doesn’t yet have any effect on your control. When the pointer angle is set, the layer containing the pointer should rotate to the specified angle to give the impression that the pointer has moved.
Update setPointerAngle(_:animated:) as follows:
func setPointerAngle(_ newPointerAngle: CGFloat, animated: Bool = false) { pointerLayer.transform = CATransform3DMakeRotation(newPointerAngle, 0, 0, 1) pointerAngle = newPointerAngle }
This simply creates a rotation transform which rotates the layer around the z-axis by the specified angle.
The transform property of CALayer expects to be passed a CATransform3D, not a CGAffineTransform like UIView. This means that you can perform transformations in three dimensions.
CGAffineTransform uses a 3×3 matrix and CATransform3D uses a 4×4 matrix; the addition of the z-axis requires the extra values. At their core, 3D transformations are simply matrix multiplications. You can read more about matrix multiplication in this Wikipedia article.
To demonstrate that your transforms work, you’re going to link the UISlider with the knob control in the view controller. As you adjust the slider, the value of the knob will change.
The UISlider has already been linked to handleValueChanged(_:). Open ViewController.swift and add the following to that method:
knob.setValue(valueSlider.value)
Now the knob value is set to match the valueSlider as it slides.
Build and run. Now, change the value of the UISlider and you’ll see the pointer on the knob control move to match as shown below:
Despite the fact that you haven’t started coding any of the animations yet, your control is animating. Why?
Core Animation is quietly calling implicit animations on your behalf. When you change certain properties of CALayer — including transform — the layer animates smoothly from the current value to the new value.
Now try sliding quickly from the end to the start. Rather than rotating counter-clockwise, the pointer will rotate clockwise over the end of the track, and into the bottom. That’s not what you want!
To solve this, you need to disable these animations. Update setPointerAngle(_:animated:) by replacing the CATransform3DMakeRotation line with:
CATransaction.begin() CATransaction.setDisableActions(true) pointerLayer.transform = CATransform3DMakeRotation(newPointerAngle, 0, 0, 1) CATransaction.commit()
You wrapped the property change in a CATransaction and disable animations for that interaction.
Build and run once more. You’ll see that as you move the UISlider, the knob follows instantaneously, and the knob moves predictably.
Animating Changes to the Control’s Value
Currently, setting the animated parameter to true has no effect on your control. To enable this bit of functionality, add the following to setPointerAngle(_:animated:) just below the CATransform3DMakeRotation call and before the commit:
if animated { let midAngleValue = (max(newPointerAngle, pointerAngle) - min(newPointerAngle, pointerAngle)) / 2 + min(newPointerAngle, pointerAngle) let animation = CAKeyframeAnimation(keyPath: "transform.rotation.z") animation.values = [pointerAngle, midAngleValue, newPointerAngle] animation.keyTimes = [0.0, 0.5, 1.0] animation.timingFunctions = [CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)] pointerLayer.add(animation, forKey: nil) }
Now when animated is true, you create an explicit animation that rotates the pointer in the correct direction. In order to specify the rotation direction, you use a keyframe animation. That’s simply an animation where you specify some in-between points in addition to the usual start and end points.
You create a CAKeyFrameAnimation and specify that the property to animate is the rotation around the z-axis with transform.rotation.z as its keypath.
Next, in animation.values, you specify three angles through which the layer should rotate: the start point, mid-point and end point. Along with that, there’s the array animation.keyTimes specifying the normalized times (as percentages) at which to reach those values. Adding the animation to the layer ensures that once the transaction is committed the animation will start.
To see this new functionality in action, you’ll need the knob to jump to a value. To do this, you’ll implement the method wired up to the Random Value button to cause the slider and knob controls to move to a random value.
Open ViewController.swift and add the following to handleRandomButtonPressed(_:):
let randomValue = Float(arc4random_uniform(101)) / 100.0 knob.setValue(randomValue, animated: animateSwitch.isOn) valueSlider.setValue(Float(randomValue), animated: animateSwitch.isOn)
The above generates a random value between 0.00 and 1.00 and sets the value on both controls. It then inspects the isOn property of animateSwitch to determine whether or not to animate the transition to the new value.
Build and run. Now tap the Random Value button a few times with the animate switch toggled on, then tap the Random Value button a few times with the animate switch toggled off to see the difference the animated parameter makes.
Updating the Label
Next you’ll populate the label to the right of the knob with its current value. Open ViewController.swift and add this method below the two @IBAction methods:
func updateLabel() { valueLabel.text = String(format: "%.2f", knob.value) }
This will show the current value selected by the knob control. Next, call this new method at the end of both handleValueChanged(_:) and handleRandomButtonPressed(_:) like this:
updateLabel()
Finally, update the initial value of the knob and the label to be the initial value of the slider so that all they are in sync when the app starts. Add the following code to the end of viewDidLoad():
knob.setValue(valueSlider.value) updateLabel()
Build and run, and perform a few tests to make sure the label shows the correct value.
Responding to Touch Interaction
The knob control you’ve built responds only to programmatic interaction, but that alone isn’t terribly useful for a UI control. In this final section, you’ll see how to add touch interaction using a custom gesture recognizer.
Apple provides a set of pre-defined gesture recognizers, such as tap, pan and pinch. However, there’s nothing to handle the single-finger rotation you need for your control.
Add a new private class to the end of Knob.swift:
import UIKit.UIGestureRecognizerSubclass private class RotationGestureRecognizer: UIPanGestureRecognizer { }
This custom gesture recognizer will behave like a pan gesture recognizer. It will track a single finger dragging across the screen and update the location as required. For this reason, it subclasses UIPanGestureRecognizer.
The import is necessary so you can override some gesture recognizer methods later.
Note: You might be wondering why you’re adding all these private classes to Knob.swift rather than the usual one-class-per-file. For this project, it makes it easy to distribute just a single file to anyone who wants to use this simple control.
Add the following property to your RotationGestureRecognizer class:
private(set) var touchAngle: CGFloat = 0
touchAngle represents the touch angle of the line which joins the current touch point to the center of the view to which the gesture recognizer is attached, as demonstrated in the following diagram:
There are three methods of interest when subclassing UIGestureRecognizer: they represent the time that the touches begin, the time they move and the time they end. You’re only interested when the gesture starts and when the user’s finger moves on the screen.
Add the following two methods to RotationGestureRecognizer:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) { super.touchesBegan(touches, with: event) updateAngle(with: touches) } override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) { super.touchesMoved(touches, with: event) updateAngle(with: touches) }
Both of these methods call through to their super equivalent, and then call a utility function which you’ll add next:
private func updateAngle(with touches: Set<UITouch>) { guard let touch = touches.first, let view = view else { return } let touchPoint = touch.location(in: view) touchAngle = angle(for: touchPoint, in: view) } private func angle(for point: CGPoint, in view: UIView) -> CGFloat { let centerOffset = CGPoint(x: point.x - view.bounds.midX, y: point.y - view.bounds.midY) return atan2(centerOffset.y, centerOffset.x) }
updateAngle(with:) takes the set of touches and extracts the first one. It then uses location(in:) to translate the touch point into the coordinate system of the view associated with this gesture recognizer. It then updates the touchAngle property using angle(for:in:), which uses some simple geometry to find the angle as demonstrated below:
x and y represent the horizontal and vertical positions of the touch point within the control. The tangent of the rotation, that is the touch angle is equal to h / w. To calculate touchAngle all you need to do is establish the following lengths:
h = y - (view height) / 2.0 (since the angle should increase in a clockwise direction)
w = x - (view width) / 2.0
angle(for:in:) performs this calculation for you, and returns the angle required.
Note: If this math makes no sense, refer to our old friend, the Trigonometry for Game Programming tutorial.
Finally, your gesture recognizer should work with one touch at a time. Add the following initializer to the class:
override init(target: Any?, action: Selector?) { super.init(target: target, action: action) maximumNumberOfTouches = 1 minimumNumberOfTouches = 1 }
Wiring Up the Custom Gesture Recognizer
Now that you’ve completed the custom gesture recognizer, you just need to wire it up to the knob control.
In Knob, add the following to the end of commonInit():
let gestureRecognizer = RotationGestureRecognizer(target: self, action: #selector(Knob.handleGesture(_:))) addGestureRecognizer(gestureRecognizer)
This creates a recognizer, specifies it should call Knob.handleGesture(_:) when activated, then adds it to the view. Now you need to implement that action!
Add the following method to Knob:
@objc private func handleGesture(_ gesture: RotationGestureRecognizer) { // 1 let midPointAngle = (2 * CGFloat(Double.pi) + startAngle - endAngle) / 2 + endAngle // 2 var boundedAngle = gesture.touchAngle if boundedAngle > midPointAngle { boundedAngle -= 2 * CGFloat(Double.pi) } else if boundedAngle < (midPointAngle - 2 * CGFloat(Double.pi)) { boundedAngle -= 2 * CGFloat(Double.pi) } // 3 boundedAngle = min(endAngle, max(startAngle, boundedAngle)) // 4 let angleRange = endAngle - startAngle let valueRange = maximumValue - minimumValue let angleValue = Float(boundedAngle - startAngle) / Float(angleRange) * valueRange + minimumValue // 5 setValue(angleValue) }
This method extracts the angle from the custom gesture recognizer, converts it to the value represented by this angle on the knob control, and then sets the value to trigger the UI updates.
Here’s what happening in the code above:
You calculate the angle which represents the mid-point between the start and end angles. This is the angle which is not part of the knob track, and instead represents the angle at which the pointer should flip between the maximum and minimum values.
The angle calculated by the gesture recognizer will be between -π and π, since it uses the inverse tangent function. However, the angle required for the track should be continuous between the startAngle and the endAngle. Therefore, create a new boundedAngle variable and adjust it to ensure that it remains within the allowed ranges.
Update boundedAngle so that it sits inside the specified bounds of the angles.
Convert the angle to a value, just as you converted it in setValue(_:animated:) earlier.
Set the knob control's value to the calculated value.
Build and run your app. Play around with your knob control to see the gesture recognizer in action. The pointer will follow your finger as you move it around the control :]
Sending Action Notifications
As you move the pointer around, you'll notice that the UISlider doesn't update. You'll wire this up using the target-action pattern which is an inherent part of UIControl.
Open ViewController.swift and add the following code at the end of viewDidLoad():
knob.addTarget(self, action: #selector(ViewController.handleValueChanged(_:)), for: .valueChanged)
Here you're listening for value-changed events.
Now replace the contents of handleValueChanged(_:) with:
if sender is UISlider { knob.setValue(valueSlider.value) } else { valueSlider.value = knob.value } updateLabel()
If the user changes the value on the knob, you update the slider. If they change the slider, you update the knob. You continue to update the label in either case.
Build and run. Now move the knob around and...nothing has changed. Whoops. You haven't actually fired the event from within the knob control itself.
To fix that, inside the Knob class, add the following code to the end of handleGesture(_:):
if isContinuous { sendActions(for: .valueChanged) } else { if gesture.state == .ended || gesture.state == .cancelled { sendActions(for: .valueChanged) } }
If isContinuous is true, then the event should be fired every time that the gesture sends an update, so call sendActions(for:).
If isContinuous is false, then the event should only fire when the gesture ends or is cancelled.
Since the control is only concerned with value changes, the only event you need to handle is UIControlEvents.valueChanged.
Build and run again. Move the knob once again and you'll see the UISlider move to match the value on the knob. Success!
Where to Go From Here?
Congrats, your knob control is now fully functional and you can drop it into your apps.
You can download the final version of the project using the Download Materials button at the top or bottom of this tutorial.
However, there are still a lot of ways to improve your control:
Add extra configuration options to the appearance of the control — you could allow an image to be used for the pointer.
Ensure that a user can only interact with the control if their first touch is on the pointer.
At the moment, if you resize the knob control, the layers won't be re-rendered. You can add this functionality with just a few lines of code.
These suggestions are quite good fun, and will help you hone your skills with the different features of iOS you've encountered in this tutorial. You can also apply what you've learned in other controls that you build.
To learn how to make another custom UIControl, check out this tutorial on making a reusable UISlider.
I'd love to hear your comments or questions in the forums below!
The post How To Make a Custom Control Tutorial: A Reusable Knob appeared first on Ray Wenderlich.
How To Make a Custom Control Tutorial: A Reusable Knob published first on https://medium.com/@koresol
0 notes
Text
Singleton class for Loading indicator swift
Singleton class for Loading indicator swift
import Foundation import UIKit class LoadingIndicator: UIView { /// ActivityIndicator let loader = UIActivityIndicatorView() /// Shared Instance static let shared: LoadingIndicator = { let instance = LoadingIndicator() return instance }() override init(frame: CGRect) { super.init(frame: frame) prepared() } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been…
View On WordPress
#10.0#10.2#11.0#11.2#8.1#8.2#8.3#8.4#9.0#9.1#APP#Apple#Developer#Developers#Development#forum#how to make an ios app#Indicator#Ios#iOS 11#iOS 11.2#iOS 8#iOS 8.1#iOS7#iOS7.1#iPad#iPhone#iPod#kathir#ktr
0 notes
Quote
Favorite tweets: Back at NSCoder night working on my menubar app for posting to https://t.co/VE0B2wHLRH.— Jared Sorge (@jsorge) May 17, 2017
http://twitter.com/jsorge
0 notes
Text
Primera sesión del Nscoder Cádiz
Lo primero de todo, mis disculpas por el retraso del resumen. "Nota mental: El proximo resumen ir haciendolo mientras se celebra el Nscoder ". Después de esto, vamos a la faena. El jueves pasado 26 de noviembre quedamos en el Woodstock de la calle Sagasta en Cádiz centro para el primer Nscoder Cádiz.
Bajo mi honesta impresión, fue un éxito. Hubo como se preveía: Muchas charlas interesantes (iOS vs Android, git vs svn, git vs mercurial, scrum, iOS, etc), puestas en común (pequeña charla sobre el IDE xcode y lo nuevo del xcode 4, el storyboard) y un buen grupo de gente interesada en el desarrollo para móviles.
Estuvimos hasta cerca de las 10 y media (no se muy bien hasta q hora porque yo me tuve q ir antes) y sacamos varias cosas en común y hasta objetivos (con dos cojones).
Una de las cosas que a priori nos dimos cuenta, es que, aunque había un interes general de aprender cocoa y desarrollo iOS, no era tan facil como parecía ya que, la plataforma obliga a tener el Xcode instalado, que a su vez, obliga a que se desarrolle en un mac (cadenita de putadas) y no todos los asistentes tenian esa plataforma.
Para forzarnos al aprendizaje nos pusimos un objetivo, una app (para aprender yo siempre prefiero ejemplos mas que teoria) y haciendo una pequeña lluvia de ideas (muy pequeña porque tampoco se hizo mención de otra ya, que pareció a todos bien) vimos que podíamos hacer una Guia de Cádiz (apodada una Guia de Cadí Cadí) en tres niveles de desarrollo:
Datos estáticos (datos insertados a cascoporro en las vistas)
Tirando de base de datos (nos meteremos en faena con core data)
Tirando de algún protocolo externo (desde cualquier protocolo REST, hasta simple RSS)
Para evitar la disgregación del grupo, ya que había muchos de ellos que no tenian la posibilidad de programar en iOS, se tanteo como solución un hilo de desarrollo paralelo en otra plataforma. De hecho, había gente que pilotaba bastante en Android y planteó la posibilidad de hacerse un grupo sobre ello, y ya que Android no tiene limitaciones en cuestiones de desarrollo (se puede utilizar cualquier IDE y cualquier S.O) pues se tiró palante!
Este tema es bastante controvertido ya que, incluyendo otras ramas de desarrollo corremos el riesgo de irnos por peteneras y que se pierda un poco la finalidad del grupo ya que, NScoders en un grupo cuya finalidad es aprender iOS y cocoa, y ramas de desarrollo hay más que fideos en una sopa, por eso, creo que sabiendo esta posibilidad, lo mejor es irnos con pies de plomo y organizarnos bien para que las dos ramas no choquen, si no que crezcan aprendiendo, dejando de lado las diferencias sobre codigo libre y demás temas controvertidos, si se piensa, al final es hasta bonito.
Bueno, he creado un grupo de google para poder irnos presentando y organizando.
nscoder_cad [arroba] googlegroups.com (evitemos el spam oh my god)
Y ya que esto es un grupo de desarrollo enlazo algunos enlaces que pueden estar interesantes. Lo primero; storyboard, esta nueva forma de controlar el Interface Builder que ha salido con el Xcode4 hace bastante facil enlazar las vistas y hacer una navegación entre ellas. Enlazo dos tutoriales (en verdad no hay muchos punteros). Es la app de ejemplo que mostré fugazmente en el NScoder
http://www.raywenderlich.com/5191/beginning-storyboards-in-ios-5-part-2
http://www.raywenderlich.com/5138/beginning-storyboards-in-ios-5-part-1
Y recomiendo mucho, los podcast de la Universidad de Stanford sobre iOS, totalmente actualizados (en ingles, of course). Enlazo los archivos de los tutoriales
Bueno, para los que nos leen la primera vez, animaros y presentaros en el grupo, se diran cosas muy interesantes y nos lo pasaremos genial.
Un saludo a todos!!
PD: Nombro a todos los nicks de los que tengo constancia de que asistieron, si me falta alguno por favor (que me falta), comunicadmelo por twitter o por el grupo de google
@pyriku
@peterlozano
@danielnietoweb
@fsero
@jManuelRosa
@NeoShadybeat
@Jorge__Galindo
@nikusdrei
@powersgame
3 notes
·
View notes
Text
Protege las API keys de tu app con CloudKit
El pasado 19 de julio, Pedro Muñoz nos demostró, en vivo, como usar ClodKit para proteger los principales secretos de tu aplicación y como evitar su interceptación en la red usando SSL pinning, protegiéndonos del temido "man in de middle".
Tenéis la presentación y el código de ejemplo en su repo:
Recordaros que en agosto no habrá eventos de la NSCoderNight, retomaremos el 20 de septiembre.
3 notes
·
View notes
Text
Toma de contacto con Nscoders
Twitter no para de sorprenderme. Este fin de semana con motivo de un viaje que hacía a Barcelona para ver a Glen Hansard, un cantante folk que si no lo conocéis os lo recomiendo muchísimo :-), hice un sondeo por twitter por si había algún evento en esos dias a los que podía unirme.
Gracias a @urikpd que me habló de NScoders en un tweet pude profundizar en este tipo de eventos y ver que realmente hay una gran cantidad de desarrolladores iOS por toda España que quedan semanalmente basados en una idea norteamericana llamada Nscoders Night.
Curiosamente en 47 Degrees, llevábamos tiempo buscando un grupo de desarrolladores iOS para intercambiar opiniones y poder ver posibles ramificaciones de trabajo. Fue un placer compartir esos escasos minutos (ya que me tenia que ir corriendo) y conocer gente que a priori me pareció más que competente.
Si quereis saber más sobre Nscoders:
Nscoders Night
Nscoders Barcelona
Nscoders España
Podcast sobre Nscoders
Parte del equipo de 47 Degrees se ha comprometido a asistir a un evento organizado el 29 y el 30 de octubre en Vilanova, en el momento que sepa de los detalles lo posteo ;-)
5 notes
·
View notes
Text
Creando tu primer SPM plugin, imágenes, presentación y mucho más.
El pasado miércoles 19 de abril, Libranner Santos compartió con nosotros una estupenda charla sobre SPM plug-ins.
Lamentablemente, no pudo impartir la charla presencialmente, tal y como estaba originalmente previsto, pero eso no nos impido de disfrutar de una charla, con live-coding y de las instalaciones que amablemente nos cedió el equipo de Kindred, junto con cervezas y pizzas para todos.
El contenido de la presentación de Libranner puedes verlo aquí.
Además, Libranner ha compartido un excelente artículo donde se desgranan todos los pormenores de la charla, y desde donde podéis descargaros el código fuente.
Muchas gracias a todos los que asististeis, a Libranner por la excelente charla y por supuesto a Kindred por su amabilidad, cediéndonos sus oficinas, y además darnos de cenar.
Nos vemos en la próxima.
2 notes
·
View notes
Text
Reactive... all the way down? - Fotos y presentación
Impresionante la charla que nuestro amigo Alberto Guerrero nos obsequió en el pasado evento.
No se limitó a contarnos la introducción a la programación reactiva con Combine sino que añadió muchos ejemplos reales ligados a su experiencia, casos de uso y sobre todo antipatrones. Además, mantuvimos una conversación super constructiva sobre usos, comparación con async/await y futuro de la librería.
Podéis descargaros aquí la presentación de Alberto.
Nos vemos en la próxima.
1 note
·
View note
Text
Arquitectura en iOS. Mesa redonda.
¿Te apetece más que un highlander te apuñale en la ingle que montar una arquitectura VIPER? ¿Eres de los que usa MVC para todo? ¿Es MVVM la arquitectura de SwiftUI o el nuevo grupo de Rick Astley?
Acompáñanos a esta edición de la NSCoder MAD y participa en una mesa redonda liderada por Alfonso Miranda (Wabi Project) donde hablaremos de Arquitectura en iOS. A Alfonso le acompañarán Carlos García González y Yago De Martin López, ambos de NTT Data, que nos animarán a participar y dar nuestras opiniones sobre este tema del que tanto nos gusta discutir con una cerveza en la mano… aunque esta vez las cervezas vendrán después 😬
Donde y cuando:
Proximo miercoles 14/12/22 a partir de las 19h en el local Puerta de la Innovación, C. de Toledo, 110 · Madrid
Puedes registrarte en el siguiente link a MeetUp.
0 notes
Text
Uso y disfrute de Charles Proxy
En esta charla, nuestro querido Pedro nos hablará del uso y configuración de Charles Proxy en dispositivos Apple.
Charles es una app proxy que nos va a ayudar en el desarrollo de la capa de servicios de nuestras aplicaciones. Entre otras cosas nos permite:
Capturar el tráfico http y https de nuestro dispositivos. Tanto peticiones como respuestas.
Simular varios escenarios de conexiones lentas a internet.
Ver de forma cómoda las respuestas JSON y XML.
Repetir y modificar peticiones.
Modificar peticiones y respuestas para simular escenarios que necesitamos durante el desarrollo, como la simulación de errores.
Añadir breakpoints a peticiones, respuestas o ambas
¿How cool is that? Pues esto y más cositas es lo que veremos en la charla.
Anímate y ven. Hazte el favor.
Donde y cuando:
Próximo miércoles 17/04/2024 a partir de las 19h en el espacio Puerta de la Innovación, c/ Toledo 110., Madrid.
Puedes registrarte en el siguiente link a MeetUp:
3 notes
·
View notes