- Denver, CO
- Other notes:
- Install the Xcode beta the week before the conference, in case you need to update the OS too
I definitely want to watch the videos from these later:
- Graphing with Custom Collection View Layouts
- Enumerating The Reasons
- Concurrency From the Ground Up
- It is all mind
- Building Augmented Reality Apps Using ARKit
- Making Analytics Interesting – A lesson in app UX design
- Machine Learning in human terms
- Jay Thrash
- @jaythrash
- jay@jaythrash.com
- https://jaythrash.com/talks
- Key Takeaways
- Consistency
- Importance of story-telling
- Practice practice practice
Notes
- Development Process
- Conceive
- Visualize
- Present
- Phase 1: Conceive
- Everything begins with a message
- Message begins with a purpose
- What are the fundamental goals of giving a presentation in the first place?
- Spreading ideas and motivating others
- Engage interest, and resonate with them to form a lasting impression
- Rule of 3 Ls: Listen, Learn, Last
- Listen: engaging the audience. Quality of the presentation, leveraging the medium (not just reading bullet points from the slides)
- Learn: relevant, quality content, acceptable risk
- Last: makes a lasting impression. Resonates, motivates change, spreads beyond the room
- Focus on reaching your audience
- Identify with your audience, empathize with their needs, prioritize their needs
- Amplify through authority and authenticity
- Don't fall into the trap of believing you need to be an expect before you can talk about a topic
- Problem: Don't need to solve all the problems, solve one problem
- Experience: You may have personal experience in the matter
- Audience: You might be one type of an expert when presenting to your own team, vs presenting at WWDC. Find the audience where you can be the expert in the topic at hand.
- Developing your message. Four steps:
- Topic
- eg: Struggle -> breakthrough
- eg: Message of success
- Brainstorm
- Quantity over quality
- Research: find other people who have had similar or contradicting results, to cover all bases
- Pick the highlights
- Divergent vs. convergent thinking: start with one thought and spread from there (divergent), or narrow down to the specific topics/areas that are good enough to include (convergent)
- Story
- Crafting your story
- Structure. Beginning, middle, end: three-act structure
- Quest. Hero's journey: hero, adventure, crisis, victory, return transformed
- Shape. Exposition, rising action, climax, falling action, denouement (note that this follows the hero's journey)
- Great presentations follow a common structure, up and down:
- What is: This is how things are
- What could be: the ideal we could be achieving
- Alternate back and forth
- End with the new norm, where the lofty goal you're tring to present is a norm that can be sustained
- Want to show the struggle and conflict, show that you've been at the "what is" where people in the audience may be, and have come out on top
- Crafting your story
- Structure
- Topic
- Phase 2: Visualize
- More than words: see what you're saying
- Color
- Keep it simple. Use 3, maybe 4 colors, define a pallette
- Use the same color when highlighting a particular idea throughout, to bring consistency to that topic
- Maybe use different pallettes for different sections. For example, Jay used different background colors for the three main sections of this talk
- Don't re-invent the color wheel. Some helpful sites
- Contrast is critical
- Also keep in mind that the environment you're presenting in might have more limited color range (projector vs. retina monitor)
- Suggestion: try all color combos in the pallete (blue on black, black on blue, etc) and check them out to see how they each look
- Typography
- Again: keep it simple. Find a few that you can use
- Just like color, assign the fonts a purpose. For example: title, subtitle, body text, flourish (something scripty for flavor), etc
- Make sure to pick a good monospace for code samples
- Look for fonts that look good huge: they're going to be big on-screen. Err on the side of larger, more readable text.
- Layout
- Unity, flow, contrast
- Unity affords consistency
- Flow conveys direction
- The flow of information on a slide might be obvious to you, but not to your audience. Be sure to give this consideration and make the flow obvious.
- Use size and perspective: make the primary item larger
- Animation: incrementally add information in the order appropriate (how to expose this in non-presented format like PDF of slides?)
- Make it explicit: number them, or draw an arrow
- Contrast provides importance
- Contrasting size, shape, color, proximity/position (clustering, separate item)
- Content guidelines
- Images
- Use the space: make images large, or even make them the background and overlay text
- Keep contrast in mind, if placing text over image
- Adjustments you can make: desaturate the image, or put a translucent color between the image and text
- Code
- Practice if you're doing live-coding
- Use presenter theme in Xcode
- Consider using a playground
- Highlight the key changes, whether coding live or showing it on a slide
- Motion/animation
- Less is more
- Use it as a seasoning
- Focus attention: draw to a specific thing, but not so much motion to distract from what you're saying
- Effective use: show a change/improvement, like on a graph
- Images
- Keynote has an outline mode
- You can paste a markdown outline in there, and it'll create the slides and stuff for you
- Phase 3: Present
- Confidence through preparation
- Prior to the event
- Practice practice practice
- Record and listen to yourself, then critique
- Repeat as necessary
- Presentation day
- Room recon
- Arrive early
- Check connections: need a video adapter? What's the mic setup?
- Room layout: Is there a podium? What's the layout? How much can I roam? Are there cables on the floor I need to watch out for?
- Create a test pattern slide to check your slide design
- Fill the screen
- Demonstrate the various text-on-background colors you're using, so you can check contrast on the projector
- Include some circles, so you can check if it's stretching your content
- Include your custom fonts, in case your slides will be going on a shared presentation machine, which might not have the fonts installed
- Check position of the screen. From the back row, will content at the bottom of the screen be blocked by other people? You might need to ensure your key points are in the top half.
- Preflight checklist: make sure you've got everything you need
- Have a backup copy of your presentation, in the cloud, on a thumb drive, etc, in case your laptop dies
- Gadgets and extra batteries: clicker, dongles
- "Clean your room"
- If you're transitioning from Keynote to Xcode, clean up your desktop, close other apps, etc
- Mute notifications (alt-click on notification center in menu bar)
- If you don't need a network connection, just turn off wifi
- Stand and deliver
- Try to think of it as a conversation with friends. Keep it relaxed.
- Develop a warm-up ritual that works for you
- Find your "mic-ed up voice" and make sure you talk consistently to the mic
- Relax and pace yourself. Pause after important points to give it a moment to sink in, take a look at the audience and see if they're "getting it." Reiterate, check for questions, etc if needed.
- Eye contact, not slide contact. Look at the audience, not your own slides
- Find some anchors, people who seem to be getting it. If you notice they look confused by something, that might be a good read on how the rest of the audience is feeling.
- It's a wrap, you've done it
- Be available for questions
- Take some time to reflect and evaluate your performance
- Determine message effectiveness
- Refine and repeat: present again elsewhere, with your adjustments
- Room recon
- Final thoughts
- Books that are helpful
- Slide:ology (Nancy Duarte)
- Resonate (Nancy Duarte)
- Presenation Zen
- It's the Way You Say It
- Finding "anchors" in the audience
- Not much to it: who's paying attention? Who's making eye contact?
- Getting feedback
- Conferences often collect and provide feedback, which is really helpful
- Presenter notes/display
- You can increase the font on presenter notes to make them easier to read while presenting
- The more you have in your notes, the more you'll rely on them. Takes you out of presenting a bit, makes it harder to connect with audience.
- Books that are helpful
- Misc links
- https://www.deckset.com: Good for code samples, reveal some code at a time
- Jenny Chang Ho
- GrubHub
- @TipTopGS
Notes
- Four ways to think about A/B testing
- Testing a hypothesis
- Feature flagging
- Controlling rollout of new features
- Innovating while minimizing risks
- Testing can be messy
- Dead code: variant no longer used, but code is still in place
- Increased testing scope
- It's not for everyone: if you don't have a lot of users, you can't really achieve statistical significance
- Experiment examples
- Include option to schedule future deliveries
- Default starting tab when launching the app
- "Fail early, fail often, but always fails forward"
- How to be a good loser
- Understand what could go wrong, and question assumptions
- Fully understand the experiment and what is being tested
- Ask product owners questions
- Make sure you're clear about potential conflicts with other experiments
- Evaluate the tools: testing framework setup and customization
- Some frameworks offer ways to qualify a user for an experiment: eg, new vs. returning customer
- Should every feature havfe a feature flag?
- Create debug settings (for QA)
- Automate tests
- Experiments can take a long time, and regression testing control and experiment over time can become a big effort
- Unit test default feature flag values (control)
- Write code that's easier to make permanent, or delete, depending on experiment outcome
- Composition over inheritance
- Use multiple nibs, for different design variations
- Setup a cleanup process
- Use the results from other platform
- Test something on Android, and make use of that data
- Understand what could go wrong, and question assumptions
- Take aways
- Check the assumptions
- Setup a cleanup process
- Decide between feature flag and kill switch (not a feature flag as we use them)
- Automate tests as much as possible
- Agnes Vasarhelyi
- @vasarhelyia
- https://blog.alltheflow.com
Notes
- Handling background transfers
- URLSession API: need to move away from completion handlers to delegate-based APIs
- Example: start a background task, then background the app. It's suspended. It's not running code: need a delegate method to call when it's launched in the background to handle that response.
- Good to know: users can turn off background transfer capability in Settings
- Tasks have an isDiscretionary property. Set this for stuff that isn't time-sensitive, and the OS will execute when the conditions are right (phone charged, etc)
- Tasks started in the background default to true on this
- URLSession API: need to move away from completion handlers to delegate-based APIs
- Silent (content) push notifications
- content-available flag set
- App is resumed in background, with limited time: around 30 seconds
- No user permission required
- Similar to background fetch, but triggered remotely instead of scheduled locally
- Surprises
- Users can switch it off, by disabling background refresh
- Lesson: don't implement critical functionality here
- Rate limited by APNS
- No more than 2-3 per hour
- Won't be received when the app was terminated
- Users can switch it off, by disabling background refresh
- Authentication
- No client trust validation in background session. Bug report open for 4 years.
- Server trust validation options
- Cert pinning: simple, secure
- No self-signed certs valid in the background, needs to use system-trusted CA (ATS restriction: get around it by disabling ATS)
- Rolling certs: public key has to be static, so you need to maintain backup keys in the app
- Longer-living certs cost $$$
- Authentication challenge handlers
- Easier to implement
- Too many resumes to the app in the background (?)
- Custom authentication scheme (recommended approach)
- Ask for token in the foreground session and authenticate that request, somehow
- Use that token in the background
- Cert pinning: simple, secure
- Resume rate limiter
- nsurlsessiond has a delay value
- Doubles with each resume
- Resets to 0 when user activates the app or delay elapses without new task
- Applies to your app as a whole, not per session
- Custom authentication implementation doubles the resumes, which considerably impacts this delay time
- How to make the rate limiter happy
- Batch transfers
- Authentication without additional resumes
- Surprises
- Free pass for Xcode builds: resume rate limiter ignores debug builds, and doesn't default isDiscretionary to true
- Call registerForRemoteNotifications on every launch
- nsurlsessiond has a delay value
- Testing
- Hard to test
- Debugging: make use of Console.app
- Look at nsurlsessiond logs for networking
- Look at dasd logs for scheduling
- Search for your bundle ID
- Put the pieces together
- Watch for pid values to string together
- Tips
- Only use background transfer for time-insensitive work
- Design networking around the resume rate limiter
- Same for authentication
- Master usage of Console.app
- Jen Kelley
- @thehulkstory
Notes
-
- Things that everyone says you should do
- Break things into smaller pieces
- Tests
-
- General Computer Things
- Source control
- Networking
- Immutability vs mutability
-
- iOS-specific things
- Know your platform and common pitfalls
- Tools, like Xcode
- View lifecycle, responder chain
- Sizing, constraints
- Common design elements, like table views
- Don't rebuild the wheel
- Third party dependencies
-
- Overall knowledge
- "Classic" computer science books
- Code by Petzold
- Working Effectively with Legacy Code by Feathers
- Design Patterns by Gang of Four
- Go to meetups/conferences
- Learn how much you actually know
- Communicate
- Ask questions
- Everybody starts out knowing nothing
- More-experienced people tend to use slang/acronyms—don't hesitate to ask
- If someone can't explain something they seem to know about, they probably don't actually understand it
- The big difference between junior and mid-level devs: the ability to answer "why" in addition to "how"
- Questions
- Anything you didn't know for a while and wish you knew sooner?
- Decoupling code and what it really means. Provide code examples
- Same for mutable vs. immutable
- Impostor syndrome among folks without CS degrees
- Don't need a degree. You can figure out what you need to know from books and stuff.
- Anything you didn't know for a while and wish you knew sooner?
- Eric
- Key Takeaways
NSStringVariableWidthRuleType
Notes
- Strings dict files
- Handles numbers (ex: 0 apples, 1 apple, 17 apples)
- Localizable.stringsdict
- NSStringLocalizedFormatKey, can include variables
- Variables have rules for one, zero, other
let format = NSLocalizedString("label.itemLocalizedDescription", comment: "Some label")String.localizedStringWithFormat(format, count)
- Display context-specific strings
- NSStringVariableWidthRuleType
- Refers to the number of em units that can fit in the available width
- Kind of like size classes for strings
- XLIFF support
- Interchange format, not embedded in your project
- Industry standard for localization
- Automatically generate Localizable.strings
- Built from NSLocalizedString() calls
- Xcode 9 added XLIFF support for stringsdict files
- That support includes knowledge of language-specific localization rules
- eg: exports more options for Russian than other languages
- That support includes knowledge of language-specific localization rules
- Does not include full support for variable width strings: don't try to edit those and import, Xcode will wipe out the different width variants
- Xcode 9.3 adds support for custom …LocalizedString() prefixes, for automatic generation
- Xcode 10
- Introduced Localization bundle
- Notes directory can contain anythng you want
- Source Contents contains localized strings from nibs and such
- Translation Generation
- Generation logic used to export XLIFFs
- Seems to use the "first" instance of a localzation key as the base language version
- Tips
- Don't fight the tools. If you're fighting the tooling, you might be coming at it wrong
- Segregate variable width strings (you may need to fight the tools for this one)
- Avoid reusing localization keys
- Centarlize your reused stirngs with static localizations
- Ellen Mey
- Detroit Labs
- https://github.com/eisforellen/talks
- https://twitter.com/el_is_for_ellen
Notes
- As long as the type of each property in a Codable also conforms to Codable, you're good to go
- To change the JSON key for values:
enum CodingKeys- Need to include all properties
case chanceOfRain, temperature // Keys match propperty namescase details = "weathDescription" // Different key
- Containers
- Three types
- Keyed containers: dictionary
- Unkeyed container: ordered values, like array
- Single value container: raw value, no container
- Have to be mutable
- Need to specify keys
- Three types
- keyDecodingStrategy
let decoder = JSONDecoder(); deocder.keyDecodingStrategy = .convertFromSnakeCase- Other option:
.custom(([CodingKey]) -> CodingKey)
- Other stuff
- PropertyListEncoder
- Creating customer encoders: enable coding to and from XML, for example
- dateDecodingStrategy is limited but helpful
- Handling floats
- Utilizing Codable with other frameworks like RxSwift
- Jake Schwartz
- Life 360
Notes
- When to Rewrite
- Probably never
- Takes longer than you expect
- Opportunity cost
- Might make sense when the market is stable and changes infrequent, because you can make time to rebuild
- Key benefits of rewrite
- You're all immediately expects in the codebase
- Rejuvenate with best-practices
- Throw away years of tech debt (unused images, etc)
- Planning
- Paired with Android engineer and investigated different design patterns
- Looked at VIPER
- Settled on RIBS: https://github.com/uber/RIBs/wiki
- Guiding principles
- Architectural parity across platforms
- Use the same class names
- Using RxSwift and RxJava
- Realm DB
- Modularity, for the future
- Built one tab of the app as a standlone POC that could then be re-added to the main app
- Highly-tested
- RIBs
- Split business logic into interactors, with little else in them
- Interactors are highly testable, then
- Architectural parity across platforms
- Launch
- Internal testing: 100 people. Found most crashes and bugs
- TestFlight: under 10,000. Found some more crashes
- App Store: 15 million. Too big: want to roll out slower than that
- Currently-shipping app has legacy and new code bases, using a feature flag to toggle between them
- Phased rollout suggestions
- English users only, to avoid localization issues during initial rollout
- Free users, then paid users (or vice versa)
- Know what you're measuring: build dashboards to track relevant metrics
- Jay Freeman
- Orchid
Notes
- Compared fall of Rome and Easter Isle to that of Microsoft and the jailbreak community
Notes
- Choices
- Web-based or wrapped: PhoneGap, Cordova
- Cross platform: Titanium, React Native, Xamarin
- Fully native apps: one in Swift/ObjC, one in Java/Kotlin
- Choosing depends on your situtation:
- Entrepreneur? Corpoate?
- What are you building?
- Web-based
- Not great for native experience
- Slow when using hardware feature
- Need to know about both platforms
- Third-party library support is not good
- Pro: great for an MVP or app with limited distribution
- Cross platform
- Good for apps with 80% or more shared code base
- "Native-looking" experience
- Good for apps that require heavy hardware usage
- Same issues as web-based: limited third-party support, need to know both platforms, need lots of test devices
- Big con: you MUST build and test on both platforms in parallel
- Native
- Challenging to maintain two codebases with feature parity
- May need to find a partner dev for the other platform, if you're an entrepreneur or freelancer
- Legacy projects may require two languages for one platform (eg: Swift and ObjC)
- Pros: best user experience, can focus on one library, SDK and third-party support
- Tradeoff: go deep on one platform (specialize), or go broad on both (jack of all trades)
- Recommendations
- Mix and match, cross-platform with native, if you have the talent to support it
- Code reuse where possible: add RN modules or Titanium modules to native code
- If fully funded: go all-natice
- Use web-based/wrapped if it's just a POC and you're planning to rewrite anyway
Joe C
- Designer, entrepreneur, developer
- hard to explain that to other people
- also: podcaster, musician, conference planner
- Multipotentialite: fancy word for "I don't know what I want to do when I grow up"
- assimilation and accommodation: complementary things your brain does when you learn
- expand definition of a thing (eg, dog) as we learn more about what fits in that "box"—accommodate
- then, with something else (eg, cat), we accommodate, and start a new box
- examples of people changing: sting switching musical styles. Cynthia Nixon going from actress to politician
- "if I can convince people I'm a terrible developer, I can probably convince them I'm a good one, too"
- people want a clear box to put you in. Give them one.
- "a lot of us didn't see enough dogs before we saw our first cat." Boxes are too small: we put other people in a box before we know enough about them to do so
- figure out what you want to be, so you can start telling other people
- Aijaz Ansari
- gogo Business Aviation
- https://github.com/aijaz/lldbPythonScripts/
Notes
xed .opens the workspace or project in the current directoryexpr self.navigationItem.Title = "wha?"- Variables shown in debug console: shows what LLDB thinks is a good representation of the object/data
- For example:
indexPathappears as "2 indices", which isn't useful type summary add --summary-string "(Section: ${var._indexes.pair.0} Row: ${var._indexes.pair.1})" IndexPath
- For example:
- Want that to happen every time: add it to
~/.lldbinit scriptto start Python interpreterframe = lldb.frame: SBFrame. Swig Object (bridge to LLDB)
- Can call Python functions from LLDB: needs to have
(valobj, internal_dict)paramsvalobjis an SBValue
- To define
type summary addfor types specific to your project:- Add a breakpoint in applicationDidFinishLaunching
- Add debugger action:
command script import ~/lldb/typeformatter.py
- Note that there may be a delay before these type summaries appear in the debug console, while the Python is executing. It does have a performance impact on debug builds.
jq: JSON parse/filter
- Rachel Hyman
- Slides: https://github.com/rachelhyman/360idev
- Key Takeaways
- Do actual testing in VoiceOver with the screen curtain on
- Get designers on board with Dynamic Type
Notes
- Affordances: little things you can do to make your app usable by everyone
- 1 in 5 people in the US have a disability
- UIAccessibility protocol
- Set
isAccessibilityElementtrue on custom controls accessibilityLabel: localized string, read to the useraccessibilityTraits: bitmask, with various trait typesaccessibilityValue: for values that can changeaccessibilityHint: optional, if other properties don't adequately describe the control. This can be turned off by the user. Example: camera-switcher button in the camera, because "Camera switcher" doesn't necessarily explain what it does.
- Set
- Accessibility properties: label vs. value vs. identifier
- value: changing value. Basically, state
- identifier: not part of the UIAccessibility protocol. Only used for UI testing
- Flow & discoverability
- VoiceOver users will discover things in order
- May need to group things together so VoiceOver labels make sense
- Accessibility containers can be used for this: groups items together for accessibility
- Use titles: nav bar titles are the first thing read on a new screen
- Accessibility Auditing
- Accessibility Inspector
- "Run Audit" button: can help find many (but not all) accessibility issues
- Examples: contrast fail, hit area too small, dynamic type not supported
- Better way to discover things: just use it with VoiceOver
- Screen curtain: blacks out the screen. Tap screen 3 times, with three fingers
- Better simulates the experience for someone unfamiliar with your app who is only using VoiceOver
- Dymanic Type
- Apple has a chart that shows the font size for each text style at various levels
- Acccessibility Inspector has an option to change the dynamic font size
- In IB: check the Automatically Adjusts Font box on labels. This will update them automatically when returning from the Settings app if the user changes font size there.
- UIFontMetrics can be used to scale custom fonts
- Resources
- Applevis: tracks accessibility issues in Apple apps
- Why?
- Better apps for everyone
- Empathy
- Mike Lee
Notes
- Apple is a conservative company
- They are not moving fast and breaking things
- They are not trying to be first to market
- They are happy to watch competitors go to market and fail, so they can learn from them
- Apple tends to release things incrememebtally. In hindsight, you can connect the dots and see how they were setting up for the future.
- Right now: seem to be in an awkward place, product-wise.
- ARKit is the new UIKit
- Siri will be the main interface
- Every tool is also a weapon
- Easy money is in replacing humans; smart money is in augmenting humans
- Derek Selander
- https://github.com/DerekSelander/lldb
Notes
- Mach-O is the layout for executables running on any Apple platform
- Apps, kernels, extensions, everything
- Mach-O terminaology
- Modules: the main executable, UIKit, etc
- Mach-O Header, at offset 0
- Tells you if it's compiled for 32 or 64 bit
- Load commands: right after the header. Variable-size structs that detail how to load the module into memory?
- Segment: Area on disk that will have the same memory protections as the app
- Actual code will be stored in segments
__TEXT__DATA
- Section: 0 or more sections in each segment
- One section will store the hard-coded UTF8 strings in your app
__TEXT.__cstring__TEXT.__text__DATA.__objc_classlist
- Demo
- macho header file loader.h
struct mach_header_64: mach header. Has 8 properties, each 4 bytesxxd -l 32 $(which grep): get the first 32 bytes—the whole header- Apple platforms run on little-endian, and the output is grouped into 2 bytes
xxd -l 32 -e $(which grep): -e flag fixes bit endianness00000000: cffa edfe 0700 0001 0300 0080 0200 0000 ................00000010: 1300 0000 4007 0000 8500 2000 0000 0000 ....@..... .....- Corresponds to the items in the header:
struct mach_header {
uint32_t magic; /* mach magic number identifier */
cpu_type_t cputype; /* cpu specifier */
cpu_subtype_t cpusubtype; /* machine specifier */
uint32_t filetype; /* type of file */
uint32_t ncmds; /* number of load commands */
uint32_t sizeofcmds; /* the size of all the load commands */
uint32_t flags; /* flags */
};
Dump strings position in grep:
$ otool -l $(which grep) | grep _cstring -A4
sectname __cstring
segname __TEXT
addr 0x0000000100003a5e
size 0x00000000000004df
offset 14942
Dump the actual strings, using offset and size:
$ xxd -s 14942 -l 0x00000000000004df $(which grep)
- LLDB commands
tvto toggle view on and offpo [0x203232032 retainCount]search -r 0x203232032to see items retaining itsectionprints out segments for the main executablesection MachOFunwill list all for the MachOFun executablesection MachOFun __TEXTwill list text sections?
_dyld_image_count: how many loaded images there are in the process. UIKit, Foundation, your own app, etc
- Kaya Thomas
- Slack
- Twitter: https://twitter.com/kthomas901
- Repo: https://github.com/kmt901/Notifications-iOS12
- Her site: https://kayathomas.info
Notes
- Mostly focusing on local notifications for this talk
- Create UNMutableNotificationContent with title and body set
- For a recurring notification, create a DateComponents representation of the day of the week it should file
- UNCalendarNotificationTrigger, use that to create a UNNotificationRequest
- Use UNUserNotificationCenter to post hte request
- Notification service extension
- Triggered if content-available set to 1
- Can be used to decrypt data or download attachments
- Notification content extension
- Allows you to customize the look of the notification
- Ex: Lyft notification shows image of the car and driver, license plate, etc
- Allows the user to take action from the notification
- What's new in iOS 12?
- Authorization options: allow the user to customize how notifications appear
- New Deliver Quietly option: they'll show up in notification center, but not as a banner
- Provisional Authorizations: you don't need to ask permission to send these notifications "quietly," directly to the notification center
- When reqestugin notification permission (badge, sound, etc), include
.provisionaloption
- When reqestugin notification permission (badge, sound, etc), include
- Users can also turn off all notifications for your app from one notification
- If you have custom notifications page, Apple will include a deep-link to that view in your app. This is also linked from your app settings in the Settings app.
- Also include
.providesAppNotificationSettingsflag when requesting authorization for notifications - Callback method in app delegate:
openSettingsFor(notification:) - User info dictionary includes payload, so you know what notification they are coming from
- Keep in mind they can also come from the Settings app, so the user info will be
nil
- Grouped notifications
- Defaults to one group for the app, but the app can specify custom groups for it
- The user can override this, and force to group all per app
- Set the
threadIdentifierstring on theUNMutableNotificationContent. For example, use the name of the podcast that you're notifying about a new episode.- Back-end can set this in
aps.thread-idin the JSON
- Back-end can set this in
- Group notification summary: "2 more episodes of StartUp"
summaryFormat = "%lu more episodes of %@"- Apple fills it in for you
- Summary format for hidden previews (like when previews are turned off for Messages notifications). This can give context without content, instead of just showing "Notification"
UNNotificationCategorytakes these format strings in initializer- Use this to set the category property on the
UNNotificationCenter
- Use this to set the category property on the
- Include the category on
UNMutableNotificationContent
- Defaults to one group for the app, but the app can specify custom groups for it
- Dynamic category actions
- Create Notification Content Extension target
- Customize the plist for the target to set some values for notifications
UNNotificationExtensionUserInteractionEnabledUNNotificationExtensionDefaultContentHidden: set to YES or else the default notificatoin view will be shown in addition to yoursUNNotificationExtensionCategory: has to match the category used on notificatoins you want to route to the extension
- Create a
UNNotificationActionfor each action shown on the notification- In extension:
didReceive(_ response)method is called when actions are tapped - Check
response.actionIdentifierto determine which action was tapped - This handler can set new actions on the
extensionContext - Need to call completion closure with a response option, to dismiss the notification, or go to the app, etc
- In extension:
- User interaction in notifications
- Can now handle user interaction in the content extension, like including buttons in the content view, above the action buttons
- Add the view in the content extension
- Authorization options: allow the user to customize how notifications appear
- Summary
- Determine if provisional authorization is appropriate for your app
- Make sure you provide a deeplink option to your custom settings view
- Use thread identifiers to group notifications
- Rob Napier
Notes
- Security through obscurity vs. security by design
- La Cryptographie Militaire
- In essence: a system should be secure even if everything about the system is known, except for the key
- Obfuscation vs Obscurity
- Obscurity: you don't tell anybody how the system works
- Obfuscation: you try to make it hard to figure out the system
- Cryptography
- If you lose your secure key, everyone else using the same scheme is fine. If the obfuscation that protects your scheme is figured out, then everyone using the scheme is at risk.
- Don't think: I want to make it twice as hard to break. You need to make it 10x, 100x harder.
strings -n 8 AppNamedumps all the strings in AppName- Hopper: another tool
- Optimized code is harder to reverse-engineer
- So what can you actually do?
- Get secrets out entirely—fewer secrets
- Don't store API keys in your app
- Don't talk to third-party services: talk to your own server, and have your server talk to the other service
- Authenticate users, not apps
- You cannot authenticate apps or devices
- Honey tokens
- Put fake URLs or tokens in the source code, then monitor those things
- Then you know when someone is attacking you
- In Swift, global variables are never optimized away, even if they're not being used
- You have to pay attention
- Get secrets out entirely—fewer secrets
- Hiding stuff
- Don't base64 encode stuff: it goes into the string space
echo somestring | base64 -D | xxd -i- Gives you code you can import into the app, in the data space. Still not hard to find, but better.
- AES keys should be random bytes, not a string you could type from a keyboard
- Generate one:
head -c32 /dev/random | xxd -i - 100 trillion types better
- Generate one:
- For API keys that you can't change: find creative ways to scramble them
- Example: get x random bytes (x is size of your key) and zip it with your key using xor (^)
- Now you have a random mask, and a seemingly-random encoded key—which both serve as honey tokens, too
- Don't base64 encode stuff: it goes into the string space
- Certificate pinning
- He has another talk about this
- iOS 11 has 170 root certificates
- https://github.com/rnapier/CertificateValidator
- What to do?
- Invest in Hopper and Charles
- Spend an hour or two poking around to see what you can find
- Need to launch without Xcode, and using a release build
xcrun simctl launch booted com.bestbuy.whatever --wait-for-debuggerto debug with Hopper (need the super-expensive version to do this on device)
- Hardening, instead of obfuscation
- Makes it harder to attach a debugger: introduce dead-ends, bloat the code, etc
- Hard to develop with
- Costly
- Takeaways
- Obfuscation is for you, not users
- Focus on the basics: strings, networks
- Test in Hopper and Charles
Notes
- Observability
- Product
- Analytics, push notification analytics, user reviews, sales/download reports
- Developer
- Device logging, crash reports, error reports
- Crash reporting: the fires you can see
- Error reporting: the fires you can't see
- Logging: how the fires are starting
- Product
- Logging
- OSLog
- Introduced in iOS 10
- Works across all their OSs
- Unification of syslog and Apple System Logger APIs
- Reasons to use OSLog
- Simplicity: single API call:
os_log() - Thread safe
- Fast
os_logdoesn't format dates at call time, but when you view the log
- Powerful
- Filtering: hide or show by process, category, type, etc
- Simplicity: single API call:
- OSLog
- Console.app
- Right-click on the column headers to add other columns, like category and subsystem
- Can save an active filter as bookmark (to just filter to your app's activity, for example)
- Using OSLog
import os.log- Call
os_log() - Create an
OSLogwith a category/subsystem, to pass in theos_log()calls - Levels: debug, info, default, fault, error
- Fault: involves multiple processes
- Error: Error in current process or framework
- Disk vs. memory:
- Debug and info go to Memory, not written to file. You can watch it in Console, but it won't be in any logs you get from a user.
- Default, Fault, and Error go to disk
- Private Data
- When using placeholders for values in log messages, the OS will replace it with
<private>in the saved logs - Use
%{public}@placeholder (instead of%@) if you want to include it in the log - Note that this doesn't apply to numbers: public by default.
- To make it private:
%{private}@(for an account number, for example)
- To make it private:
- When using placeholders for values in log messages, the OS will replace it with
- Data formatting
os_log("Laiumched at %{time_t}d", time_t(launchDate.timeIntervalSince1970))- Formatted on the fly when you view it
%{BOOL}dor%{bool}dwill do "YES" or "true" respectivelyman os_loglists them all
- Error handling
- Error formatters:
%{errno},%{signal},%{mode} - Works with things like POSIX errors, prints a nice error message
- With
codefrom anNSError, unknown error - The workaround he uses: ErrorReporting protocol
- Error formatters:
- How to get logs from users?
sysdiagnose- Push all the buttons on the device. In a few minutes, there's a log file that can be sent out from the analytics section of the settings
- Limitations
- No file-based logging
- ObjC designed, Swift friendly
- No way to adjust logging settings on iOS devices (to have it persist debug and info logs, for example). Supposed to be a way to do it, but he couldn't get it to work.
- Binary log formats are not backwards compatible
- Improvements only come as Apple needs them
- Best Practices
- Don't wrap the API—no seriously, don't wrap the API. You'll get duplicate logs.
- Use a single subsystem for your application.
- Use a small subset of categories
- GitHub repo has sample code
- Stephen Tramer
- Code and slides: https://github.com/sptramer/360idev-2018-swift
Notes
- Why should you care?
- Appls says Swift is a "systems programming language."
- Swift is an application programming language with ambitions to be a systems programming language
- De-mystify compilers
- Learn whree any why Swift breaks long-established rules
- Knowing that ABI stability is good and understanding why are two different things
- Appls says Swift is a "systems programming language."
- Compiler pipeline
- Swift -> SIL (Swift intermediate language) -> LLVM IR (intermediate representation, aka bitcode) -> ASM (assembly) -> MachO binaries
swiftc -emit-silto generate SILswiftc -emit-irto generate LLVM IR
- ABI Stability
- Ensures that two pieces of software built with different versions of the compiler at differnt times can still link togehter
- Allows shipping binary frameworks
- Currently, Swift apps build with the runtime
- Ensures a level of compatability, for future-proofing
- Sets the groundwork for allowing other languages to call into Swift
- Data Layouts
- 4.2 had locked data layouts
- …except for vtables (virtual function dispatch tables)
- …and payloaded enums (associated values)
- Witness tables are locked: unlike vtables, relate to protocol conformance
- Three layers:
- What happens in SIL?
- What happens in IR?
- What does the compiler source say?
- 4.2 had locked data layouts
- Lifetimes and ownership
- Last major feature for Swift 5.0
- Fully opt-in except for exlusivity enforcement
- The law of exclusivity: anyone can read memory unless it's being written to. Then, only the writer can read it.
-
Josh Michaels (https://www.jetsoncreative.com/360idev/) and John Wilker
-
Misconceptions about going indie
- first step is quitting your job. Not ideally. First step might be losing your job.
- first real step is to ship something
- indie means not having s boss
- Apple is kind of a boss
- You also need to be the boss and make difficult decisions
- indie is "living the dream"
- The dream is a nightmare
- it's hard work
- successful indie devs are rich
- part of being successful is spending modestly
- everyone will want my app
- this might have been believable at one point, years ago
- a good app markets itself
- indie means being well known
- some indies are well known, run podcasts, etc, but not most
- it's apples fault
- so easy to blame apple
- one success is all it takes
- it takes all the successes
- indie means by yourself
- first step is quitting your job. Not ideally. First step might be losing your job.