The lineup was fantastic again this year, which means few time slots had were a no-brainer session choice for me. These are the ones that I didn't get to see in person—I'm going to make sure to watch the videos once they're posted.
- With Great Power Comes Great Responsibility: The Implications of the Code We Write
- Evolution of Deep Linking
- The Trouble with Pentagons: Developing Off the Grid
- Beyond Byte: Prototyping with iPad Playgrounds
- Getting Past No: The Science of Moving Others
- Dynamic Typography & Adaptive Layouts in iOS 11
- The Art of Responding to Criticism
- Creating adaptable layouts using Trait Collections and Container Views
- Life Beyond Storyboards: Building your UI in code
- Learning from iOS Animations
- Threads, Queues, and Things to Come: The Present and Future of Concurrency in Swift
- How Open Source Development Can Make You A Better Developer
- How I Learned To Stop Worrying and Love Autolayout
- Agile Swift
http://tinyurl.com/360iDev2017-KHG-Xcode
- Behavior tab in preferences
- Search Starts: show new tab. Opens a new tab to prevent messing up with you're doing
- Running Starts
- Same thing, for starts and pauses: uses a debug tab to avoid messing up your workspace
- Debugging
- Visual debugging
- Use instruments to simulate low memory state
- Instruments can simulate background fetch
- Visual debugging
https://github.com/sammyd/360iDev_iOS11
- Serialization with Codable
- Many languages use reflection for this
- Swift 4 uses code generation instead: you specify the fields and whatnot
- For basic use cases: just conform to Codablele protocol
- Drag and Drop
- localContext on the UIDragSession is specific to the current app, and can be set to anything context data around
- Natural Language Processing
Souroush Khanlou http://khanlou.com/
Three tips
-
Empathy. Often writes blog posts with a past version of himself in mind, writing to him 6 months or two years in the past.
-
Momentum. Just start writing. Intro is easier than the conclusion. When another idea strikes, stop mid-sentence and write down that thought.
-
The first cut (is the deepest). First draft.
-
Your idols have been doing this for a long time. Don't compare youself to people who have been doing this much longer than you have.
- Natasha the Robot, daring fireball, MKGHB
- They put in the time
-
Copy your idols: you can start by mimicking the people you admire, but it will be obvious if you're copying them too closely.
- Smash your idols. The thing you think you're making might not wind up being the thing you end up making.
-
Find your voice. Find your niche. The internet is a big, deep place with room for all sorts of weird things.
- TempleOS
- Dwarf Fortress
-
Representation matters. Be a mirror for people like you who might not see people like them doing interesting things.
-
Brandon Alexander, Black Pixel
-
Based on blog series he wrote earlier this year: https://medium.com/bpxl-craft/event-delivery-on-ios-part-1-8e68b3a3f423
-
Touch detection
- Symbolic breakpoint on hit test method, that logs information about the first argument passed to it. Shows the list of view controller hierarchy of views that are checked for the one(s) that want to accept the hit.
- Mac Debugging Magic (or iOS Debugging Magic): article with info about registers for various arguments
-
UIKit API
- UIControl
- Target-action pattern
- Actions based on control events
- Messages to targets ALL flow though
[UIApplication sendAction:to:from:forEvent:]
. Breakpoint on that symbol to identify problems with actions. - UIControl actions (like IBAction methods)
- Three options: no params, sender, or sender & UIEvent
- UIResponder
- Backbone of the responder chain
- Defines handlers of different types of system events
- First Responder dictates the event flow. No first responder by default: must register by becomeFirstResponder
- UIControl
-
Responder Chain
- Using a nil-targeted action on UIControl subclasses
- Create an event, then send it using
[[UIApplication shared] sendAction to:nil]
(pseudocode) - If there is a first responder, it will be the first one to get the opportunity to respond to that action. The action works its way up the responder chain, it's just a question of whether it starts with a first responder.
- In Swift, you can be more strictly typed. Extend Selector to add a static var for a given selector, which is defined by a protocol. Conform to that protocol on objects you want to respond to actions on that.
- Neem Serra
- Asynchrony
- St Louis Women Techmakers lead
Cupcakes are just as healthy as donuts, so how come nobody ever brings them for breakfast?
- Bias
- Favoring a person/group/idea over another
- Helps your brain categorize information
- Bias is influenced by your family, friends, where you live, the news, where you live, everything
- Unconscious bias vs. conscious
- Unconscious: don't know you're acting on that bias
- Conscious: "I don't like spiders"
- Implicit association test
- http://implicit.harvard.edu
- Can help you identify unconscious bias
- Found that 70% of white people had a preference for white people—but so do 50% of black people
- Found that in many areas, the minority group has a preference for majority group
- Also found it with asking kids to choose a doll: mostly choose majority group
- Vocab
- In-group: group you identify with. Judge on potential (donuts)
- Out-group: group that you do NOT identify with. Judge on accomplishments (cupcake)
- Intersectionality: someone in a lot of out-groups will have compounding disadvantages
- Why do we care
- Diversity leads to more innovation
- Disney wrote a book about this?
- When you get people from an in-group in a room, they tend to engage in group think. Diversifying the group breaks up that groupthink
- Diversity leads to more innovation
- 1% bias simulation, run 20 times
- Men can get rated up to 101%, women only up to 100%
- 15% attrition at each of 8 levels in the company, backfill with top performer
- At the base level, 53% women
- At the top level (8), only 35% women
- Bias examples
- In early YouTube uploads on the iPhone, 5-10% of videos were upside down
- Left-handed people tended to rotate their phone the other direction, and right-handed dev hadn't considered that usage
- Early airbags killed women and children because the test dummies were based on men
- Early voice recognition only worked with men, because that's who was building it
- VR: women got motion-sick a lot more because the VR was calibrated to an average height, and that average was the dudes building it
- In early YouTube uploads on the iPhone, 5-10% of videos were upside down
- Who do you have testing your app or tech? Is it people just like you, who won't notice this stuff either?
- The power of bias
- Study with identical resumes, using either male of female names at the top. For every 8 men recommended for hire, only 5 women were.
- For 6 European-sounding names, only 4 African-American sounding names were recommended
- The "right sounding" name was equivalent to adding 8 years of experience
- "Right sounding" names with criminal backgrounds were more likely to be hired than those with "ethnic sounding" names
- Daily interactions
- In identical stories, "Howard" was perceived as likable and more appealing, while "Heidi" was seen as selfish and a self-promoter
- GW Bush: "Too often, we judge other groups by their worst examples while judging ourselves by our best intentions"
- How do we speak? Are we being pushy? Treating users like children? Always/Never?
- Who is in your circles? Are the people around you just like you?
- How do you attribute traits?
- Do you attribute some trait to a particular group? Example: "Indian people always veer to the left when walking on the sidewalk" with a sample size of 2
- Seek forgiveness
- When you realize you have acted on bias, apologize for it
- What can I do?
- Listen, believe, acknowledge
- Challenge and counter stereotypes
- Assess your relationship with out-groups
- Be an active bystander
- Be aware and understand the impact of your bias
- Become a scientist of your own behavior: e.g., who do you go sit next to at a conference?
- Check the context of information. Eg: "This angry black woman at the mall was yelling at this poor girl" is loaded with bias and assumptions about the people involved
- Tim Mitra
- Jaime Lopez
More Than Just Code podcast
- How we learn
- Unconscious incompetence: you don't know what you don't know
- Conscious incompetence
- Conscious competence: still learning, need to concentrate. Most of us stay in this zone, in most things.
- Unconscious competence: can do the thing without having to focus, almost by habit. Second nature.
- How we learn
- 20% of what we hear, 30% of what we see, 90% of what we do
- First step can be "what are you even talking about": make sure that everyone is using the same acronyms and meanings
- Building a portfolio
- Teaching what you know: good way to hone what you know
- Twitter, podcasts, blogging: good way to get your name out there as an expert and articulate what you know
- Meetup or conference talks: force you to collect and share your thoughts
Aijaz Ansari
- Links
- Sample project: conference app
- List of sessions, tap for detail. Speaker detail view from there.
- Session and Speaker models
- Minor annoyances: In the debug panel, useless variable summaries: memory address, or "2 indices"
- LLDB command:
type summary add --summary-string "${var.title} by ${var.speaker.name} MyConf.Session
- Same kind of thing for IndexPath
- LLDB command:
- How can we repeat that on every Xcode launch?
.lldbinit
in home directory- Copy-paste the
type summary add
line in there - This will apply to all projects
- Same thing for project-specific types
- Python terminal can be opened in LLDB by running
script
- Can use python function to process values of variables
- Use a continuing breakpoint in didFInishLaunching to load a python script into LLDB
- Python uses SBValue: basically wraps a variable from another language
- LLDB will look for
__lldb_init_module
method in python and run it - In the lldb file for the project:
command script import sessionFormatter.py
- Import that LLDB init file using the continuing breakpoint in didFinishLaunching
command source my-project-lldb-init-file
- Then, all of this is in source control, except for that breakpoint
- But, the breakpoint could be set in in the LLDB init file, since it's just LLDB commands
- jq: C application that can be used for pretty-printing JSON, among other things
- Import the jq python script
- Then in LLDB:
jq '.' someJsonString
to pretty print the value of someJsonString - Use jq filters to find specific data in the JSON object
- e.g.:
jq '.speakers[] | select(.name=="Chad Perk") | .id' jsonString
to print the speaker ID for Chad Perk- it loops over the speakers and finds the one with the name key == "Chad Perk" and gets the value of the id key
- Aijaz's method
- Write the JSON to a file to run jq on that. Otherwise, LLDB can crash if it's holding all that data
- Bureau of labor and stats: 1 million CS jobs will go unfillfed in 2020
- Less than 25% of high schools offer AP CS class. Lack of instructors is the primary reason.
- Class options:
- Intro to programming (Sometimes)
- AP CS principals: mostly conceptual, barely covers actual coding
- AP CS A: actually covers coding
- Signup form: https://docs.google.com/forms/d/14550bbXAhaO3dLFmwyfi7fHXc5tvsdNeL7ZaKVxoGhU/viewform?usp=sharing&edit_requested=true
Rob Napier
- Links
- Encrypt your traffic
- Use HTTPS
- Even if you screw it up, it's better than nothing
- Don't disable ATS
- Certificate pinning
- 168 roots in the iOS keychain
- You are trusting all those people, and it's always riskier to trust yourself and someone else, than to just trust yourself
- Pinning: Only trust your own cert
- How to do this
- https://github.com/rnapier/CertificateValidator
- Create URLSession with a CertificateValidator as delegate
- See also: TrustKit (datatheorem/TrustKit)
- Certificate Rotation
- How he does this:
- buy a five-year app and pin it in the app.
- After one year, buy another, and put that in the app
- On year 2, remove the original one, and switch to a third
- Doing this every year helps guard against forgetting to do it, or forgetting HOW to do it
- How he does this:
- Use HTTPS
- Data protection
- Device Encryption: tie flash storage to a CPU. Out of your control, so it doesn't matter.
- Data protection: file-level protection
- NSFileProtectionComplete
- System derives a key (using the user's passcode) and immediately encrypts the file
- The key remains available so the file contents are available to the app. It's all transparent.
- When the user locks the device, the key is destroyed. It lives in a separate part of the memory that's expressly for this purpose.
- When the user logs in, a new key is generated so you can read the file again
- Potential problem: key goes away when the user locks the device, so you can't keep doing things in the background.
- Protection levels
- Complete: always, when the phone is locked. Use this by default.
- Complete, unless open: Leaves it unlocked until the file is "closed". Use this for background access.
- Complete until first user authentication: remains unencrypted until the device is rebooted? Not super great, but projects in cases when the device is powered down.
- How easy to use?
- Just turns on Data Protection in app entitlements
- Do this from the beginning, not right before you ship
- In code
- When using data.write(to:options:) pass one of those protection levels as the option
- This is true for any class that has a write method that takes options: String, Data, etc
- FileManager can set a protectionKey attribute (using setAttributes method on FileManager
- This can be done at any time, on any thread
- This can be used to touch all your docs to set their permission correctly, like when going into the background
- Very fast
- Can be used on any kind of file—core data, images, etc
- App Delegate has methods:
applicationProtectedDataWillBecomeUnavailable
andapplicationProtectedDataDidBecomeAvailable
- Also notifications and
isProtectedDataAvailable
bool onUIApplication
- Also notifications and
- Apple docs: https://www.apple.com/business/docs/iOS_Security_Guide.pdf
- Handling Passwords
- Even if you're not protecting anything important, people reuse passwords. The one you're using for cat videos is probably also being used for their bank account
- The best way to protect passwords is to never see them
- Simplest: hashing. Don't send a password to the server, send a hash.
- Choosing your hash
- SHA-2
- There are no other answers
- MD5 is broken and can be reversed
- SHA-1 has been kind of cracked
- You don't see SHA-2 though, you see:
- SHA-224, SHA-256. SHA-512, etc
- Only need SHA-256 and SHA-512. 512 is 64 bytes, 256 is 32 bytes
- What went wrong at LinkedIn?
- Attackers stole logins as SHA-1 hashes
- Using a rainbow table, they could track some back
- Salting
- Adding some extra data to the password before it is hashed
- Deterministic salt: some rule to use the same salt
- For example, bundle ID and username:
com.example.MyGreatApp:[email protected]
- Stretching
- Make things slow, to make guessing expensive
- Add 80 milliseconds to a login attempt. A user won't notice, but time to brute-force an 8-char password goes from 2 months to 15 million years.
- PBKDF2 is a common tool: Krzyzanowskim/CryptoSwift
- Use a big number for iterations, like 10 or 100k. That's not about security, it's about slowing things down
- Also, use SHA-256 as the option for output
- Store a hash
- Before storing the hash from the client in the DB, hash it one more time with SHA-2
- Never store the actual value (hash or password) sent from the client. If an attacker gets the actual value in the DB, and can use that directly to login, you're done
- Correct AES Encryption
- Great encryption, if you use it right. Using it incorrectly is like leaving the key in a super great lock
- Rob's library to do this right: https://github.com/RNCryptor
- Supported on lots of platforms
- RNCryptor is a WAY of encrypting. You need to use it on all systems if you're going to use it
- AES takes 16 bytes of plaintext and turns it into 16 bytes of cypher text, using a key (one of three kinds of key) that is randomized
- The helpers
- Key generation
- Block cypher modes
- Incorrect key generation: using the user's password as a key
- The things you could type on a US keyboard would only fill about 0.0001% of the keyspace
- Use a PBKDF
- Requirement 1: use a salt
- Initialization vector
- ECB: breaking the content into 16 byte chunks and encrypting each (since AES encrypts only 16 bytes at a time)
- But: that reveals patterns. For example, an image encrypted this way can still kind of be read to see the general shape
- Cipher block chain instead: injects values along the way, using an initialization vector
- Unauthenticated Encryption
- HMAC: hash-based message authentication code
Cassie Shut, ThoughtWorks
- MVVM
- Data binding, works well with React
- Manipulate model in result of view actions
- Works with model objects explicitly
- More testable than MVC
- VIPER
- Better decoupling
- Better reusability
- More layers
- Clean code
- SwiftLint
- CPD: checks for code duplication
- Deployment
- fastlane
- TestFlight
- LinkedIn used an internal beta build before it was deployed to production, and found most of their bugs then instead of in production
- Testing
- Testing pyramid
- Manual testing at the top, tools like XCTest and quick at the bottom
- The ideal is to have automated tests at the base, and some manual tests at the top
- Most companies have it inverted, and most tests are manual, with few automated tests
- Ice cream cone instead of a pyramid
- Manual tests are a lot slower, and often more expensive
- As much as possible, push down the pyramid
- Continuous integration
- Compile/unit tests
- Functional test
- User acceptance test
- Staging
- Testing pyramid
- Jez Humble's 3-step test
- Every dev commits to master/trunk every day
- Every commit triggers build and test
- Failures usually fixed in minutes
- Xcode server is included in Xcode 9
- The bot has parallel testing
- App Store releases
- Using fast lane to automate screenshots in multiple languages
Ellen Mey
- Growth mindset: whether you think you can or think you can't, you're right.
- Embrace the suck
- Set goals, and write them down. Share them with others who can share your success or encourage you.
- Build a community
Rob Napier
- Links
- Von Neumann style
- Fortran, C
- Step by step imperative programming
- Swift is NOT a functional programming language
- But, there are many lessons we can learn form that world
- Poking parts of a model into subviews on a cell is not MVC
- Like UILabel, we should just hand the whole model over to the cell, and let that handle it
- Lifted type
- Type in a context
- Ex: swift optionals
- Use stronger types
- Don't use Any: get it down to real types
- In Swift 3, the strongest type is
- public enum Never {}
- fatalError technically returns Never
- Compiler knows that the method can not return anything, because there are no possible values
- More-strongly typed values
- For example,
let id: Int
- An identifier should not have math performed on it. It should not be added or divided. So, lift the type and give it context:
struct ID { let value: Int }
- Then,
let id: ID
on the main struct
- For example,
- Other example:
extension Dictionary where Key==String, Value==UIImage
- Lift it to give it content:
struct ImageCache { let items: [String: UIImage] }
- Strong types, weak protocols
- Small number of methods on protocols
- Anther example: completion method that takes a
(String?, Error?)
- What is that string? What can it be?
- Lift the type:
struct Token { let value: String }
- If username and password are always passed around together, use a grammar: wrap them in a Credential struct
- Break it down, build it back up
Eyal Keren, CTO at Rollout.io
- https://github.com/ekeren
- Managing multiple streams of work
- Long-lived branches cause merge conflicts
- Continues merges, tightly coupled work
- Feature flagging is not a silver bullet. They come with a price:
- Messier code
- Testing challenges
- Not all changes lend themselves to feature flagging
- Need a plan to expire flags
Jake Schwartz
- Life360: like a social network for families
- 1.8 billion mobile API hits per day
- Mobile challenges
- Mobile data usage
- Battery consumption
- Caching
- Updating underlying technologies
- Model store
- Core data backing the network requests
- Bicameral code base
- User-facing features
- Model store: handles data storage, network requests, etc
- Network syncing
- Data persistence
- Data fetching and change notifications
- Data mutation
- Use multiple data stores
- Member store: syncing, persisting, searching members
- Benefits
- Decoupled code
- Faster feature dev
- Skill specialization: someone who loves animation can focus on the UI side
- Helps with hiring
Kyle Richter
- Mentoring doesn't work well remote
- It's not for everyone
- Socializing, especially for extroverts
- Finding a remote job
- WeWorkRemotely.com, Remote.co, FlexJobs.com
- Networking with remote companies and employees
- Be prepared to negotiate and compromise
- Simply ask: if recruiters are coming to you, ask if you can work remotely
- When all else fails, create your own
- Common issues (and solutions)
- Being disconnected: over-communicate. Make it clear what you're working on and how it's going.
- Distractions: build a routine and stick to it
- "Arch" office: have a separate space. Walking through that door is like walking through an arch into your actual office.
- Networking: conferences
- There's a difference between being good at your job and being good at DOING your job.
Derek Selander
-
GoDaddy, and Ray Wenderlich
-
Book: Advanced Apple Debugging and Reverse Engineering
-
Objective-C blocks
- Everything boils down to C structs