#nscoder
Explore tagged Tumblr posts
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:
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
Resumen segunda NSCoderNight Mérida

La última reunión NSCoderNight en Mérida fue bastante interesante. Estuvimos charlando sobre las últimas noticias de Apple: cómo son las primeras experiencias con iCloud, lo probamos en un iPad con iOS 5 beta 4; los rumores sobre el iPhone 5, cómo será su aspecto, las fechas de salida; la caida del EC2 de Amazon.
Acordamos cambiar de nuevo la periodicidad de las NSCoderNight en Mérida a una reunión mensual, en la que los voluntarios que se animen preparen mini tutoriales rápidos en los que aprender algo interesante en las reuniones. Hoy estuvimos improvisando con Appcelerator y una de iniciacion a iOS.
Emilio Ortíz estuvo asesorando a Luis Miguel Cabezas sobre el diseño de la interfaz e su app, pendiente de aprobación en la App Store: Mnemonicosis, una app dedicada para magos profesionales.
También Emilio fue el encargado de explicarnos cómo funciona Appcelerator. Una

herramienta muy interesante para crear rápidamente prototipos en muchas plataformas, que luego pueden convertirse en aplicaciones totalmente funcionales.
El otro minitutorial lo realizó Pako González, sobre iniciación en la programación para iOS. Creó una aplicación simple de ejemplo describiendo brevemente algunos componentes esenciales a la hora de crear proyectos iOS en XCode.

Como colofón, Luis Miguel Cabezas, conocido profesionalmente como MagoLope, nos sorprendió con varios trucos de magia de cerca con cartas, al finalizar y durante el picoslabis que hubo después para cenar en Casa Benito.
Para la próxima, Raul Tierno nos iniciará en la programación con Android, Pako González describirá las partes esenciales de XCode, Luis Miguel Cabezas nos mostrará su primera aplicación publicada en la App Store: Mnemonicosis y Emilio Ortiz nos acercará al mundo del diseño con nociones sobre CSS3.
Si os animáis a mostrar algún tema interesante para esa reunión, no lo dudéis, sorprendednos ese día, o enviadnos al correo [email protected] vuestra propuesta, sobre todo para saber si dará tiempo en esa reunión o se puede dejar para la próxima.
En breve incluiremos esos minitutoriales en el blog nscoder-mer.tumblr.com.
¡Nos vemos en la próxima, pero ya en septiembre!
15 notes
·
View notes
Text
Introducción a Tuist: haz tu producto más escalable.
¡Hola a todo el mundo! ¿Otra maravillosa charla de la NSCoderNight Madrid? Sí, otra maravillosa charla de la NSCoderNight Madrid.
Esta vez, nuestro querido amigo Omar nos va a explicar cómo Tuist (tuist.io) puede ayudarnos con tareas repetitivas como hacer una build cuando los proyectos se vuelven enormes o cómo gestionar el cacheo de código o la definición del proyecto.
Se promete interesantísima, así que apúntate, alma cándida, que lo mismo después nos tomamos un zumo de gumibaya o similar.
Donde y cuando:
Próximo miércoles 22/11/23 a partir de las 19h en el local International Lab, en c/ Bailén, 41, Madrid.
Puedes registrarte en el siguiente link a MeetUp:
3 notes
·
View notes
Text
Nscoder Cádiz llamando a tierra!
Buenas a todos!
Estamos fraguando una quedada para inaugurar la primera Nscoder Night en Cádiz. Lo primero de todo... que es una Nscoder Night?
NSCoder Night es un evento semanal donde desarrolladores y diseñadores de iOS y Mac OS se reúnen en un ambiente informal y relajado.
Cositas a tener en cuenta:
No es necesario ser un experto. Ni programador.
Es un ambiente informal donde combinar iOS y cerveza
Este tipo de eventos es para gente que:
Es programador avanzado en Cocoa (Mac / iOS)
Quiere introducirte en este mundo pero no sabes por dónde empezar
Está dando tus primeros pasos
Busca un programador que plasme tu gran idea
Es un diseñador gráfico y te gustaría hacer diseños para Apps iPhone / iPad
Ya os iremos informando de donde se va a organizar la primera quedada, para empezar si te interesa el tema puedes seguirnos en nuestra cuenta twitter - > @nscoder_cad y en este tumblr.
PD: Gracias por la información de como empezar a organizar las quedadas a la gente de Nscoder Sev , en especial a Diego Freniche por este post :-)
8 notes
·
View notes
Text
CocoaHeads September Recap
This month, we teamed up with the Raleigh-based iPhone Developer group and did CocoaHeads in Raleigh for the first time. It was a great success and we'll definitely be doing this again. The current plan will be to swap months between Durham and Raleigh. So If you can't make it to the October meetup in Durham, we'll be back in Raleigh the next month.
Thanks to Katie at TekSystems for sponsoring us with both the meetup location and enough pizza to feed many hungry geeks.
Session: Lawrence Roufail on going "Beyond the SDK"
Lawrence went through several third party components he's used in his apps and added a few more to his list in this "interactive" session. The session quickly evolved to a discussion of his eleven apps and how he's developed, deployed and marketed his apps. It was a great session where we all shared a lot of great information.
Download the keynote from this presentation
I apologize, but we don't have the video here. The session recorded, but was all mangled on tape. Someday I'll need to update beyond tapes. :)
Session: Jay Thrash's (@jaythrash) recap from 360iDev
360iDev is a recurring conference focusing on all things iOS. Jay visited this year as a volunteer. Now back from Denver, Jay goes over his experiences.
Demo: Douglas Ivers with VerseByHeart
Doug showed off his app, VerseByHeart, and talked a little about how he designed it to work. Some very interesting ideas are used in helping the users remember lines via 3 different games.
Until next time
This was a great CocoaHeads meetup. The next meetup is tentatively scheduled for October 27th in Durham. Follow this blog, or ideally @trianglecocoa on twitter to keep up to date. Thanks to everyone for attending. See you next time!
8 notes
·
View notes
Link
Sometimes you're wondering what are stored in an NSCoder instance?
Here's a little utility exactly for this purpose, I called it UINibDecoderProxy. This is how you use it:
#import "UINibDecoderProxy.h" // Then override initWithCoder: - (id)initWithCoder:(NSCoder *)aDecoder { self = [super initWithCoder:[[UINibDecoderProxy alloc] initWithTarget:aDecoder]]; return self; }
Now go to UINibDecoderProxy.m and set a break point at -[UINibDecoderProxy forwardInvocation:] and log the necessary information for you. Notice at the inline comment below:
Hopefully not too tricky.
1 note
·
View note
Text
Primitives in Scene Kit iOS Tutorial
SceneKit is a high-level framework for adding 3d graphics to your application. In this tutorial the primitive objects will be positioned in 3d-coordinates and each primitive is assigned a color. This tutorial is made with Xcode 10 and built for iOS 12.
Open Xcode and create a new Prjoject. Choose the Game template.
For product name, use IOS12SceneKitTutorial and then fill out the Organization Name and Organization Identifier with your customary values. Enter Swift as Language and SceneKit as Game Technology and choose Next.
Add a new File to the project, name it MyScene and make it a sublass of SCNScene
At the top of the MyScene.swift file import the SceneKit framework
import SceneKit
Next, add the required initializer methods inside the class.
class MyScene: SCNScene { override init() { super.init() } required init(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } }
The custom code will be filled in at then end of the init method. First navigate to the GameViewController.swift file. The Game template has created some boilerplate code in this class. Delete all code inside the GameViewController class and add the viewDidLoad method
override func viewDidLoad() { super.viewDidLoad() let scnView = self.view as! SCNView scnView.scene = MyScene() scnView.backgroundColor = UIColor.black }
A SCNView is created with the scene property set to MyScene and with a black background. Go back to the MyScene.swift file and add the following code at the end of the init method.
let plane = SCNPlane(width: 1.0, height: 1.0) plane.firstMaterial?.diffuse.contents = UIColor.blue let planeNode = SCNNode(geometry: plane) rootNode.addChildNode(planeNode)
A plane object is created with a width and height of 1 unit. Scene Kit is node-based, which means the scene contains one rootNode and child nodes can be added to it. A node is created containing the blue plane object and this node is added as a child node to the root node. Build and Run the project.
The front view of the plane is visible. It should be nice if some camera control is available and some lightning is applied to the scene. Go to GameViewController.swift file and add the following lines to the end of viewDidLoad
scnView.autoenablesDefaultLighting = true scnView.allowsCameraControl = true
The default lightning of our scene is enabled and also the control of cameras on the simulator/device is allowed by using a one or two finger tap. Go back to the MyScene.swift file and add a new object at the end of the init method.
let sphere = SCNSphere(radius: 1.0) sphere.firstMaterial?.diffuse.contents = UIColor.red let sphereNode = SCNNode(geometry: sphere) sphereNode.position = SCNVector3(x: 0.0, y: 3.0, z: 0.0) rootNode.addChildNode(sphereNode)
A sphere is created with a radius of 1 unit. and a red color. The firstMaterial property is the type of material and the diffuse property is the base color of the material. With the SCNVector3 function the node can be positioned in 3 dimensions(x,y,z). Build and Run the project.
Two primitives are visible. The sphere is positioned above the plane, because the y-coordinate has value 3. The default coordinates of the plane is (0,0,0). Now add all other primitive objects at the end of the init method.
let box = SCNBox(width: 1.0, height: 1.0, length: 1.0, chamferRadius: 0.2) box.firstMaterial?.diffuse.contents = UIColor.green let boxNode = SCNNode(geometry: box) boxNode.position = SCNVector3(x: 0.0, y: -3.0, z: 0.0) rootNode.addChildNode(boxNode) let cylinder = SCNCylinder(radius: 1.0, height: 1.0) cylinder.firstMaterial?.diffuse.contents = UIColor.yellow let cylinderNode = SCNNode(geometry: cylinder) cylinderNode.position = SCNVector3(x: -3.0, y: 3.0, z: 0.0) rootNode.addChildNode(cylinderNode) let torus = SCNTorus(ringRadius: 1.0, pipeRadius: 0.3) torus.firstMaterial?.diffuse.contents = UIColor.white let torusNode = SCNNode(geometry: torus) torusNode.position = SCNVector3(x: -3.0, y: 0.0, z: 0.0) rootNode.addChildNode(torusNode) let capsule = SCNCapsule(capRadius: 0.3, height: 1.0) capsule.firstMaterial?.diffuse.contents = UIColor.gray let capsuleNode = SCNNode(geometry: capsule) capsuleNode.position = SCNVector3(x: -3.0, y: -3.0, z: 0.0) rootNode.addChildNode(capsuleNode) let cone = SCNCone(topRadius: 1.0, bottomRadius: 2.0, height: 1.0) cone.firstMaterial?.diffuse.contents = UIColor.magenta let coneNode = SCNNode(geometry: cone) coneNode.position = SCNVector3(x: 3.0, y: -2.0, z: 0.0) rootNode.addChildNode(coneNode) let tube = SCNTube(innerRadius: 1.0, outerRadius: 2.0, height: 1.0) tube.firstMaterial?.diffuse.contents = UIColor.brown let tubeNode = SCNNode(geometry: tube) tubeNode.position = SCNVector3(x: 3.0, y: 2.0, z: 0.0) rootNode.addChildNode(tubeNode)
Build and Run the Project. All primitives are positioned in the scene and they are all visible.
You can download the source code of the IOS12SceneKitTutorial at the ioscreator repository on Github.
0 notes