1155 lines
92 KiB
HTML
1155 lines
92 KiB
HTML
<!DOCTYPE HTML>
|
||
<html lang="en" class="coal" dir="ltr">
|
||
<head>
|
||
<!-- Book generated using mdBook -->
|
||
<meta charset="UTF-8">
|
||
<title>Swift Cheat Sheet - Andrew's Blog</title>
|
||
|
||
|
||
<!-- Custom HTML head -->
|
||
|
||
<meta name="description" content="Andrew Ryan's Blog">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<meta name="theme-color" content="#ffffff">
|
||
|
||
<link rel="icon" href="../../favicon.svg">
|
||
<link rel="shortcut icon" href="../../favicon.png">
|
||
<link rel="stylesheet" href="../../css/variables.css">
|
||
<link rel="stylesheet" href="../../css/general.css">
|
||
<link rel="stylesheet" href="../../css/chrome.css">
|
||
|
||
<!-- Fonts -->
|
||
<link rel="stylesheet" href="../../FontAwesome/css/font-awesome.css">
|
||
<link rel="stylesheet" href="../../fonts/fonts.css">
|
||
|
||
<!-- Highlight.js Stylesheets -->
|
||
<link rel="stylesheet" href="../../highlight.css">
|
||
<link rel="stylesheet" href="../../tomorrow-night.css">
|
||
<link rel="stylesheet" href="../../ayu-highlight.css">
|
||
|
||
<!-- Custom theme stylesheets -->
|
||
<link rel="stylesheet" href="../../src/style/custom.css">
|
||
|
||
<!-- MathJax -->
|
||
<script async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
|
||
</head>
|
||
<body class="sidebar-visible no-js">
|
||
<div id="body-container">
|
||
<!-- Provide site root to javascript -->
|
||
<script>
|
||
var path_to_root = "../../";
|
||
var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "coal" : "coal";
|
||
</script>
|
||
|
||
<!-- Work around some values being stored in localStorage wrapped in quotes -->
|
||
<script>
|
||
try {
|
||
var theme = localStorage.getItem('mdbook-theme');
|
||
var sidebar = localStorage.getItem('mdbook-sidebar');
|
||
|
||
if (theme.startsWith('"') && theme.endsWith('"')) {
|
||
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
|
||
}
|
||
|
||
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
|
||
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
|
||
}
|
||
} catch (e) { }
|
||
</script>
|
||
|
||
<!-- Set the theme before any content is loaded, prevents flash -->
|
||
<script>
|
||
var theme;
|
||
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
|
||
if (theme === null || theme === undefined) { theme = default_theme; }
|
||
var html = document.querySelector('html');
|
||
html.classList.remove('coal')
|
||
html.classList.add(theme);
|
||
var body = document.querySelector('body');
|
||
body.classList.remove('no-js')
|
||
body.classList.add('js');
|
||
</script>
|
||
|
||
<input type="checkbox" id="sidebar-toggle-anchor" class="hidden">
|
||
|
||
<!-- Hide / unhide sidebar before it is displayed -->
|
||
<script>
|
||
var body = document.querySelector('body');
|
||
var sidebar = null;
|
||
var sidebar_toggle = document.getElementById("sidebar-toggle-anchor");
|
||
if (document.body.clientWidth >= 1080) {
|
||
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
|
||
sidebar = sidebar || 'visible';
|
||
} else {
|
||
sidebar = 'hidden';
|
||
}
|
||
sidebar_toggle.checked = sidebar === 'visible';
|
||
body.classList.remove('sidebar-visible');
|
||
body.classList.add("sidebar-" + sidebar);
|
||
</script>
|
||
|
||
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
||
<div class="sidebar-scrollbox">
|
||
<ol class="chapter"><li class="chapter-item affix "><a href="../../index.html">Andrew's Blog</a></li><li class="chapter-item "><a href="../../posts/linux/linux.html"><strong aria-hidden="true">1.</strong> linux</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/linux/install_linux.html"><strong aria-hidden="true">1.1.</strong> install linux</a></li><li class="chapter-item "><a href="../../posts/linux/bash_profile.html"><strong aria-hidden="true">1.2.</strong> bash profile</a></li><li class="chapter-item "><a href="../../posts/linux/command_list.html"><strong aria-hidden="true">1.3.</strong> command list</a></li><li class="chapter-item "><a href="../../posts/linux/git_guide.html"><strong aria-hidden="true">1.4.</strong> git guide</a></li><li class="chapter-item "><a href="../../posts/linux/tar.html"><strong aria-hidden="true">1.5.</strong> tar</a></li><li class="chapter-item "><a href="../../posts/linux/run_x86_elf_in_x64_setup.html"><strong aria-hidden="true">1.6.</strong> run x86 elf in x64 setup</a></li></ol></li><li class="chapter-item "><a href="../../posts/mac/mac.html"><strong aria-hidden="true">2.</strong> mac</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/mac/macos_profiles.html"><strong aria-hidden="true">2.1.</strong> macos profiles</a></li></ol></li><li class="chapter-item expanded "><a href="../../posts/swift/swift.html"><strong aria-hidden="true">3.</strong> swift</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/swift/learn_swift.html"><strong aria-hidden="true">3.1.</strong> learn swift basics</a></li><li class="chapter-item "><a href="../../posts/swift/swift_extensions.html"><strong aria-hidden="true">3.2.</strong> Swift extensions</a></li><li class="chapter-item "><a href="../../posts/swift/swiftui_extension.html"><strong aria-hidden="true">3.3.</strong> SwiftUI extensions</a></li><li class="chapter-item "><a href="../../posts/swift/install_swift.html"><strong aria-hidden="true">3.4.</strong> install swift</a></li><li class="chapter-item "><a href="../../posts/swift/task_planner.html"><strong aria-hidden="true">3.5.</strong> implment task panner app with SwiftUI</a></li><li class="chapter-item expanded "><a href="../../posts/swift/swift_cheat_sheet.html" class="active"><strong aria-hidden="true">3.6.</strong> Swift Cheat Sheet</a></li><li class="chapter-item "><a href="../../posts/swift/yinci_url.html"><strong aria-hidden="true">3.7.</strong> Personal privacy protocol</a></li><li class="chapter-item "><a href="../../posts/swift/swift_regular_exressions.html"><strong aria-hidden="true">3.8.</strong> Swift regular exressions</a></li><li class="chapter-item "><a href="../../posts/ios/how_to_create_beautiful_ios_charts_in_swift.html"><strong aria-hidden="true">3.9.</strong> How to Create Beautiful iOS Charts in鑱絊wift</a></li><li class="chapter-item "><a href="../../posts/swift/swiftui_source_code.html"><strong aria-hidden="true">3.10.</strong> SwiftUI source code</a></li><li class="chapter-item "><a href="../../posts/swift/use_swift_fetch_iciba_api.html"><strong aria-hidden="true">3.11.</strong> use swift fetch iciba API</a></li></ol></li><li class="chapter-item "><a href="../../posts/ios/ios.html"><strong aria-hidden="true">4.</strong> ios</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/ios/cocaposd_setup_and_install_for_ios_project.html"><strong aria-hidden="true">4.1.</strong> cocaposd setup and install for ios project</a></li><li class="chapter-item "><a href="../../posts/ios/swiftui_show_gif_image.html"><strong aria-hidden="true">4.2.</strong> SwiftUI show gif image</a></li><li class="chapter-item "><a href="../../posts/ios/implement_task_planner_app.html"><strong aria-hidden="true">4.3.</strong> implement Task planner App</a></li></ol></li><li class="chapter-item "><a href="../../posts/objective_c/objective_c.html"><strong aria-hidden="true">5.</strong> objective_c</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/objective_c/objective_c_cheat_sheet.html"><strong aria-hidden="true">5.1.</strong> Objective-C Cheat Sheet</a></li><li class="chapter-item "><a href="../../posts/objective_c/objective_c_for_absolute_beginners_read_note.html"><strong aria-hidden="true">5.2.</strong> Objective-C Note</a></li></ol></li><li class="chapter-item "><a href="../../posts/dart/dart.html"><strong aria-hidden="true">6.</strong> dart</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/dart/flutter.html"><strong aria-hidden="true">6.1.</strong> Flutter Cheat Sheet</a></li><li class="chapter-item "><a href="../../posts/dart/dart_cheat_sheet.html"><strong aria-hidden="true">6.2.</strong> Dart Cheat Sheet</a></li><li class="chapter-item "><a href="../../posts/flutter/flutter_dev_test.html"><strong aria-hidden="true">6.3.</strong> Flutter dev test</a></li></ol></li><li class="chapter-item "><a href="../../posts/rust/rust.html"><strong aria-hidden="true">7.</strong> rust</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/rust/offline_use_rust.html"><strong aria-hidden="true">7.1.</strong> Offline use rust</a></li><li class="chapter-item "><a href="../../posts/rust/rust_grammer.html"><strong aria-hidden="true">7.2.</strong> rust grammar</a></li><li class="chapter-item "><a href="../../posts/rust/pase_string_and_decimal_conversion.html"><strong aria-hidden="true">7.3.</strong> pase string and decimal conversion</a></li><li class="chapter-item "><a href="../../posts/rust/parse_types.html"><strong aria-hidden="true">7.4.</strong> rust types</a></li><li class="chapter-item "><a href="../../posts/rust/rust_life_cycle.html"><strong aria-hidden="true">7.5.</strong> Rust life cycle</a></li><li class="chapter-item "><a href="../../posts/rust/rust_generic.html"><strong aria-hidden="true">7.6.</strong> rust generics</a></li><li class="chapter-item "><a href="../../posts/rust/rust_implment_matrix.html"><strong aria-hidden="true">7.7.</strong> Rust implement matrix</a></li><li class="chapter-item "><a href="../../posts/rust/rust_sort.html"><strong aria-hidden="true">7.8.</strong> Rust implement sort algorithms</a></li><li class="chapter-item "><a href="../../posts/rust/implement_aes_encryption.html"><strong aria-hidden="true">7.9.</strong> Rust implement AEC encryption and decryption</a></li><li class="chapter-item "><a href="../../posts/rust/implement_trie_data_structure.html"><strong aria-hidden="true">7.10.</strong> implement trie data structure</a></li><li class="chapter-item "><a href="../../posts/rust/rust_implement_tree.html"><strong aria-hidden="true">7.11.</strong> implement tree data_structure</a></li><li class="chapter-item "><a href="../../posts/rust/list_dir.html"><strong aria-hidden="true">7.12.</strong> list dir</a></li><li class="chapter-item "><a href="../../posts/rust/fast_way_to_implment_object_trait.html"><strong aria-hidden="true">7.13.</strong> fast way to implment object trait</a></li><li class="chapter-item "><a href="../../posts/rust/compress_rust_binary_size.html"><strong aria-hidden="true">7.14.</strong> compress rust binary size</a></li><li class="chapter-item "><a href="../../posts/rust/implment_file_upload_backend.html"><strong aria-hidden="true">7.15.</strong> impliment file upload</a></li><li class="chapter-item "><a href="../../posts/rust/this_is_add_post_cli_implementation_in_rust.html"><strong aria-hidden="true">7.16.</strong> this is add_post cli implementation in rust</a></li><li class="chapter-item "><a href="../../posts/rust/use_rust_implment_a_copyclipbord_cli.html"><strong aria-hidden="true">7.17.</strong> Use rust implment a copyclipbord CLI</a></li><li class="chapter-item "><a href="../../posts/rust/sqlite_database_add_delete_update_show_in_rust.html"><strong aria-hidden="true">7.18.</strong> sqlite database add delete update show in rust</a></li><li class="chapter-item "><a href="../../posts/rust/implementing_tokio_joinhandle_for_wasm.html"><strong aria-hidden="true">7.19.</strong> Implementing tokio JoinHandle for wasm</a></li><li class="chapter-item "><a href="../../posts/rust/rust_implement_a_crate_for_encode_and_decode_brainfuck_and_ook.html"><strong aria-hidden="true">7.20.</strong> rust implement a crate for encode and decode brainfuck and ook</a></li><li class="chapter-item "><a href="../../posts/rust/slint_builtin_elements.html"><strong aria-hidden="true">7.21.</strong> Slint Builtin Elements</a></li><li class="chapter-item "><a href="../../posts/rust/corporate_network_install_rust_on_windows.html"><strong aria-hidden="true">7.22.</strong> Corporate network install Rust on windows</a></li><li class="chapter-item "><a href="../../posts/rust/rust_binary_file_how_to_judge_static_link_or_dynamic_link_in_macos.html"><strong aria-hidden="true">7.23.</strong> rust binary file how to judge static link or dynamic link in Macos</a></li><li class="chapter-item "><a href="../../posts/rust/rust_binary_include_dir_and_get_contents.html"><strong aria-hidden="true">7.24.</strong> rust binary include dir and get contents</a></li><li class="chapter-item "><a href="../../posts/rust/rust_logger_non-block.html"><strong aria-hidden="true">7.25.</strong> rust logger non-block</a></li><li class="chapter-item "><a href="../../posts/rust/rust_connect_sql_server_database.html"><strong aria-hidden="true">7.26.</strong> rust connect sql server database</a></li><li class="chapter-item "><a href="../../posts/rust/rust_websocket_implment.html"><strong aria-hidden="true">7.27.</strong> rust websocket implment</a></li></ol></li><li class="chapter-item "><a href="../../posts/java/java.html"><strong aria-hidden="true">8.</strong> java</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/java/java_grammar.html"><strong aria-hidden="true">8.1.</strong> java grammar and codewar</a></li><li class="chapter-item "><a href="../../posts/java/run_jar.html"><strong aria-hidden="true">8.2.</strong> java run .jar</a></li><li class="chapter-item "><a href="../../posts/java/java_pomxml_add_defaultgoal_to_build.html"><strong aria-hidden="true">8.3.</strong> Java pomxml add defaultGoal to build</a></li><li class="chapter-item "><a href="../../posts/java/java_set_mvn_mirror.html"><strong aria-hidden="true">8.4.</strong> Java set mvn mirror</a></li></ol></li><li class="chapter-item "><a href="../../posts/python/python.html"><strong aria-hidden="true">9.</strong> python</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/python/convert_pesn.html"><strong aria-hidden="true">9.1.</strong> convert pesn</a></li><li class="chapter-item "><a href="../../posts/python/find_remove_dir.html"><strong aria-hidden="true">9.2.</strong> find and remove dir</a></li><li class="chapter-item "><a href="../../posts/python/timing_message.html"><strong aria-hidden="true">9.3.</strong> wechat send message</a></li><li class="chapter-item "><a href="../../posts/python/use_python_openpyxl_package_read_and_edit_excel_files.html"><strong aria-hidden="true">9.4.</strong> Use python openpyxl package read and edit excel files</a></li></ol></li><li class="chapter-item "><a href="../../posts/go/go.html"><strong aria-hidden="true">10.</strong> go</a></li><li class="chapter-item "><a href="../../posts/js/js.html"><strong aria-hidden="true">11.</strong> js</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/js/js_tutorial.html"><strong aria-hidden="true">11.1.</strong> js tutorial</a></li><li class="chapter-item "><a href="../../posts/js/js_tutorial_map.html"><strong aria-hidden="true">11.2.</strong> ja map</a></li><li class="chapter-item "><a href="../../posts/js/js_tutorial_math.html"><strong aria-hidden="true">11.3.</strong> js math</a></li><li class="chapter-item "><a href="../../posts/js/js_tutorial_object.html"><strong aria-hidden="true">11.4.</strong> js object</a></li><li class="chapter-item "><a href="../../posts/js/js_tutorial_set.html"><strong aria-hidden="true">11.5.</strong> js set</a></li><li class="chapter-item "><a href="../../posts/js/single_thread_and_asynchronous.html"><strong aria-hidden="true">11.6.</strong> single thread and asynchronous</a></li><li class="chapter-item "><a href="../../posts/js/this.html"><strong aria-hidden="true">11.7.</strong> js this</a></li><li class="chapter-item "><a href="../../posts/js/js_implment_aes.html"><strong aria-hidden="true">11.8.</strong> js implment aes</a></li><li class="chapter-item "><a href="../../posts/js/getting_started_with_ajax.html"><strong aria-hidden="true">11.9.</strong> getting started with ajax</a></li><li class="chapter-item "><a href="../../posts/js/BinarySearchTree.html"><strong aria-hidden="true">11.10.</strong> binary search tree</a></li><li class="chapter-item "><a href="../../posts/js/goole_zx.html"><strong aria-hidden="true">11.11.</strong> goole zx</a></li><li class="chapter-item "><a href="../../posts/js/es6.html"><strong aria-hidden="true">11.12.</strong> es6</a></li></ol></li><li class="chapter-item "><a href="../../posts/ruby/ruby.html"><strong aria-hidden="true">12.</strong> ruby</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/ruby/rails_setup_env.html"><strong aria-hidden="true">12.1.</strong> ruby on rails setup environment</a></li><li class="chapter-item "><a href="../../posts/ruby/learn_ruby.html"><strong aria-hidden="true">12.2.</strong> learn ruby</a></li><li class="chapter-item "><a href="../../posts/ruby/ruby_note.html"><strong aria-hidden="true">12.3.</strong> Ruby Note</a></li><li class="chapter-item "><a href="../../posts/ruby/setup_ruby_for_ctf.html"><strong aria-hidden="true">12.4.</strong> Setup ruby for CTF</a></li></ol></li><li class="chapter-item "><a href="../../posts/react/react.html"><strong aria-hidden="true">13.</strong> react</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/react/react_life_cycle.html"><strong aria-hidden="true">13.1.</strong> react life cycle</a></li><li class="chapter-item "><a href="../../posts/react/react_router.html"><strong aria-hidden="true">13.2.</strong> react router</a></li><li class="chapter-item "><a href="../../posts/react/react_this.html"><strong aria-hidden="true">13.3.</strong> react this</a></li><li class="chapter-item "><a href="../../posts/react/react_interviw.html"><strong aria-hidden="true">13.4.</strong> react interview</a></li><li class="chapter-item "><a href="../../posts/react/important_react_interview.html"><strong aria-hidden="true">13.5.</strong> important react interview</a></li><li class="chapter-item "><a href="../../posts/react/react_quick_reference.html"><strong aria-hidden="true">13.6.</strong> react quick reference</a></li><li class="chapter-item "><a href="../../posts/react/redux_quick_reference.html"><strong aria-hidden="true">13.7.</strong> redux quick reference</a></li></ol></li><li class="chapter-item "><a href="../../posts/vue/vue.html"><strong aria-hidden="true">14.</strong> vue</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/vue/vue_ajax.html"><strong aria-hidden="true">14.1.</strong> vue ajax</a></li></ol></li><li class="chapter-item "><a href="../../posts/angular/angular.html"><strong aria-hidden="true">15.</strong> angular</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/angular/controller_communication.html"><strong aria-hidden="true">15.1.</strong> controller communication</a></li><li class="chapter-item "><a href="../../posts/angular/creating_custom_directives.html"><strong aria-hidden="true">15.2.</strong> creating custom directives</a></li><li class="chapter-item "><a href="../../posts/angular/directive_notes.html"><strong aria-hidden="true">15.3.</strong> directive notes</a></li><li class="chapter-item "><a href="../../posts/angular/directive_communication.html"><strong aria-hidden="true">15.4.</strong> directive communication</a></li><li class="chapter-item "><a href="../../posts/angular/post_params.html"><strong aria-hidden="true">15.5.</strong> post params</a></li><li class="chapter-item "><a href="../../posts/angular/read_json_angular.html"><strong aria-hidden="true">15.6.</strong> read json angular</a></li><li class="chapter-item "><a href="../../posts/angular/same_route_reload.html"><strong aria-hidden="true">15.7.</strong> same route reload</a></li></ol></li><li class="chapter-item "><a href="../../posts/css/css.html"><strong aria-hidden="true">16.</strong> css</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/css/use_css_media.html"><strong aria-hidden="true">16.1.</strong> use css media</a></li></ol></li><li class="chapter-item "><a href="../../posts/php/php.html"><strong aria-hidden="true">17.</strong> php</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/php/for_php_string_implment_some_extemtion_functions.html"><strong aria-hidden="true">17.1.</strong> for php string implment some extemtion functions</a></li><li class="chapter-item "><a href="../../posts/php/php_cheatsheet.html"><strong aria-hidden="true">17.2.</strong> PHP cheatsheet</a></li></ol></li><li class="chapter-item "><a href="../../posts/leetcode/leetcode.html"><strong aria-hidden="true">18.</strong> leetcode</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/leetcode/rust_leetcode.html"><strong aria-hidden="true">18.1.</strong> rust leetcode</a></li><li class="chapter-item "><a href="../../posts/leetcode/rust_codewar.html"><strong aria-hidden="true">18.2.</strong> rust codewar</a></li><li class="chapter-item "><a href="../../posts/leetcode/swift_codewar.html"><strong aria-hidden="true">18.3.</strong> swift codewar</a></li><li class="chapter-item "><a href="../../posts/leetcode/js_leetcode.html"><strong aria-hidden="true">18.4.</strong> js leetcode</a></li><li class="chapter-item "><a href="../../posts/leetcode/java_leetcode.html"><strong aria-hidden="true">18.5.</strong> java leetcode</a></li><li class="chapter-item "><a href="../../posts/leetcode/rust_huawei.html"><strong aria-hidden="true">18.6.</strong> huawei test</a></li><li class="chapter-item "><a href="../../posts/leetcode/rust_utils.html"><strong aria-hidden="true">18.7.</strong> rust common functions</a></li><li class="chapter-item "><a href="../../posts/leetcode/olympiad_training.html"><strong aria-hidden="true">18.8.</strong> Computer olympiad training</a></li></ol></li><li class="chapter-item "><a href="../../posts/ctf/CTF.html"><strong aria-hidden="true">19.</strong> ctf</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/ctf/CTF_Note.html"><strong aria-hidden="true">19.1.</strong> CTF Note</a></li><li class="chapter-item "><a href="../../posts/ctf/0.1_Web.html"><strong aria-hidden="true">19.2.</strong> Web</a></li><li class="chapter-item "><a href="../../posts/ctf/4.1_Misc.html"><strong aria-hidden="true">19.3.</strong> Misc</a></li><li class="chapter-item "><a href="../../posts/ctf/3.2_PWN_note.html"><strong aria-hidden="true">19.4.</strong> PWN</a></li><li class="chapter-item "><a href="../../posts/ctf/3.1_Crypto.html"><strong aria-hidden="true">19.5.</strong> Crypto</a></li><li class="chapter-item "><a href="../../posts/ctf/3.4_RSA_note.html"><strong aria-hidden="true">19.6.</strong> Rsa attack</a></li><li class="chapter-item "><a href="../../posts/ctf/3.5_Base64.html"><strong aria-hidden="true">19.7.</strong> Base64</a></li><li class="chapter-item "><a href="../../posts/ctf/0.0_SQL Injection Cheatsheet.html"><strong aria-hidden="true">19.8.</strong> SQL Injection Cheatsheet</a></li><li class="chapter-item "><a href="../../posts/ctf/1.1_SQL_injection.html"><strong aria-hidden="true">19.9.</strong> SQL Injection</a></li><li class="chapter-item "><a href="../../posts/ctf/1.2_SQL_injection_UNION_attacks.html"><strong aria-hidden="true">19.10.</strong> SQL Injection UNION attacks</a></li><li class="chapter-item "><a href="../../posts/ctf/1.3_Blind SQL injection.html"><strong aria-hidden="true">19.11.</strong> Blind SQL Injection</a></li><li class="chapter-item "><a href="../../posts/ctf/1.4_Code Injection.html"><strong aria-hidden="true">19.12.</strong> Code Injection</a></li><li class="chapter-item "><a href="../../posts/ctf/1.5_SSRF.html"><strong aria-hidden="true">19.13.</strong> SSRF</a></li><li class="chapter-item "><a href="../../posts/ctf/1.6_OS command injection.html"><strong aria-hidden="true">19.14.</strong> OS command injection</a></li><li class="chapter-item "><a href="../../posts/ctf/1.7_Local file inclusion.html"><strong aria-hidden="true">19.15.</strong> Local file inclusion</a></li><li class="chapter-item "><a href="../../posts/ctf/1.8_Remote file inclusion.html"><strong aria-hidden="true">19.16.</strong> Remote file inclusion</a></li><li class="chapter-item "><a href="../../posts/ctf/1.9_CSRFm.html"><strong aria-hidden="true">19.17.</strong> CSRF</a></li><li class="chapter-item "><a href="../../posts/ctf/1.10_NoSQL injection.html"><strong aria-hidden="true">19.18.</strong> NoSQL injection</a></li><li class="chapter-item "><a href="../../posts/ctf/1.11_JSON injection.html"><strong aria-hidden="true">19.19.</strong> JSON injection</a></li><li class="chapter-item "><a href="../../posts/ctf/1.12_CTF_Web_SQL_Note.html"><strong aria-hidden="true">19.20.</strong> CTF Web SQL Note</a></li><li class="chapter-item "><a href="../../posts/ctf/2.1_XXE.html"><strong aria-hidden="true">19.21.</strong> XXE</a></li><li class="chapter-item "><a href="../../posts/ctf/2.2_XSS.html"><strong aria-hidden="true">19.22.</strong> XSS</a></li><li class="chapter-item "><a href="../../posts/ctf/2.3_Upload File.html"><strong aria-hidden="true">19.23.</strong> Upload File</a></li><li class="chapter-item "><a href="../../posts/ctf/2.4_serialize_unserialize.html"><strong aria-hidden="true">19.24.</strong> serialize unserialize</a></li><li class="chapter-item "><a href="../../posts/ctf/2.5_Race condition.html"><strong aria-hidden="true">19.25.</strong> Race condition</a></li><li class="chapter-item "><a href="../../posts/ctf/3.2_PWN_note.html"><strong aria-hidden="true">19.26.</strong> PWN_note</a></li><li class="chapter-item "><a href="../../posts/ctf/3.3_pwn HCTF2016 brop.html"><strong aria-hidden="true">19.27.</strong> pwn HCTF2016 brop</a></li><li class="chapter-item "><a href="../../posts/ctf/pwn_patch_defense_skill.html"><strong aria-hidden="true">19.28.</strong> PWN Patch defense skill</a></li><li class="chapter-item "><a href="../../posts/ctf/pwn_stack_overflow.html"><strong aria-hidden="true">19.29.</strong> PWN stack overflow</a></li><li class="chapter-item "><a href="../../posts/ctf/pwn_heap_overflow.html"><strong aria-hidden="true">19.30.</strong> PWN heap overflow</a></li><li class="chapter-item "><a href="../../posts/ctf/pwn_format_string_vulnerability.html"><strong aria-hidden="true">19.31.</strong> PWN Format String Vulnerability</a></li><li class="chapter-item "><a href="../../posts/ctf/kali_linux_tutorials.html"><strong aria-hidden="true">19.32.</strong> Kali linux tutorials</a></li><li class="chapter-item "><a href="../../posts/ctf/google_dorks_2023_lists.html"><strong aria-hidden="true">19.33.</strong> Google Dorks 2023 Lists</a></li><li class="chapter-item "><a href="../../posts/ctf/dvwa_writeup.html"><strong aria-hidden="true">19.34.</strong> DVWA WriteUp</a></li><li class="chapter-item "><a href="../../posts/ctf/bwapp_writeup.html"><strong aria-hidden="true">19.35.</strong> bWAPP WriteUp</a></li><li class="chapter-item "><a href="../../posts/ctf/sqlilabs_writeup.html"><strong aria-hidden="true">19.36.</strong> sqlilabs WriteUp</a></li><li class="chapter-item "><a href="../../posts/ctf/ctf_train_at_hangzhou.html"><strong aria-hidden="true">19.37.</strong> ctf train at hangzhou</a></li><li class="chapter-item "><a href="../../posts/ctf/ctf_common_mindmap_list.html"><strong aria-hidden="true">19.38.</strong> ctf common mindmap list</a></li><li class="chapter-item "><a href="../../posts/ctf/error_based_sql_injection.html"><strong aria-hidden="true">19.39.</strong> Error Based SQL Injection</a></li><li class="chapter-item "><a href="../../posts/ctf/urlfinder_tutorial.html"><strong aria-hidden="true">19.40.</strong> URLFinder Tutorial</a></li><li class="chapter-item "><a href="../../posts/ctf/observer_ward_tutorial.html"><strong aria-hidden="true">19.41.</strong> observer_ward Tutorial</a></li><li class="chapter-item "><a href="../../posts/ctf/mysql_udf_.html"><strong aria-hidden="true">19.42.</strong> MySQL UDF 提权</a></li><li class="chapter-item "><a href="../../posts/ctf/nuclei__tutorial.html"><strong aria-hidden="true">19.43.</strong> Nuclei Tutorial</a></li><li class="chapter-item "><a href="../../posts/ctf/2024_ctf_solution_thinking.html"><strong aria-hidden="true">19.44.</strong> 2024 ctf solution thinking</a></li><li class="chapter-item "><a href="../../posts/ctf/man_che_si_te_bian_ma.html"><strong aria-hidden="true">19.45.</strong> 曼彻斯特编码</a></li></ol></li></ol>
|
||
</div>
|
||
<div id="sidebar-resize-handle" class="sidebar-resize-handle">
|
||
<div class="sidebar-resize-indicator"></div>
|
||
</div>
|
||
</nav>
|
||
|
||
<!-- Track and set sidebar scroll position -->
|
||
<script>
|
||
var sidebarScrollbox = document.querySelector('#sidebar .sidebar-scrollbox');
|
||
sidebarScrollbox.addEventListener('click', function(e) {
|
||
if (e.target.tagName === 'A') {
|
||
sessionStorage.setItem('sidebar-scroll', sidebarScrollbox.scrollTop);
|
||
}
|
||
}, { passive: true });
|
||
var sidebarScrollTop = sessionStorage.getItem('sidebar-scroll');
|
||
sessionStorage.removeItem('sidebar-scroll');
|
||
if (sidebarScrollTop) {
|
||
// preserve sidebar scroll position when navigating via links within sidebar
|
||
sidebarScrollbox.scrollTop = sidebarScrollTop;
|
||
} else {
|
||
// scroll sidebar to current active section when navigating via "next/previous chapter" buttons
|
||
var activeSection = document.querySelector('#sidebar .active');
|
||
if (activeSection) {
|
||
activeSection.scrollIntoView({ block: 'center' });
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<div id="page-wrapper" class="page-wrapper">
|
||
|
||
<div class="page">
|
||
<div id="menu-bar-hover-placeholder"></div>
|
||
<div id="menu-bar" class="menu-bar sticky">
|
||
<div class="left-buttons">
|
||
<label id="sidebar-toggle" class="icon-button" for="sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
|
||
<i class="fa fa-bars"></i>
|
||
</label>
|
||
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
|
||
<i class="fa fa-paint-brush"></i>
|
||
</button>
|
||
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
|
||
<li role="none"><button role="menuitem" class="theme" id="light">Light</button></li>
|
||
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
|
||
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
|
||
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
|
||
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
|
||
</ul>
|
||
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
|
||
<i class="fa fa-search"></i>
|
||
</button>
|
||
</div>
|
||
|
||
<h1 class="menu-title">Andrew's Blog</h1>
|
||
|
||
<div class="right-buttons">
|
||
<a href="https://gitlink.org.cn/dnrops/dnrops.gitlink.net.git" title="Git repository" aria-label="Git repository">
|
||
<i id="git-repository-button" class="fa fa-github"></i>
|
||
</a>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
<div id="search-wrapper" class="hidden">
|
||
<form id="searchbar-outer" class="searchbar-outer">
|
||
<input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
|
||
</form>
|
||
<div id="searchresults-outer" class="searchresults-outer hidden">
|
||
<div id="searchresults-header" class="searchresults-header"></div>
|
||
<ul id="searchresults">
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
|
||
<script>
|
||
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
|
||
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
|
||
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
|
||
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
|
||
});
|
||
</script>
|
||
|
||
<div id="content" class="content">
|
||
<main>
|
||
<h1 id="swift-cheat-sheet"><a class="header" href="#swift-cheat-sheet">Swift Cheat Sheet</a></h1>
|
||
<p>Want to help improve this? File an issue or open a pull request! :)
|
||
This is not meant to be a beginner’s guide or a detailed discussion about Swift; it is meant to be a quick reference to common, high level topics.
|
||
If something isn’t mentioned here, it’s probably covered in detail in one of these:</p>
|
||
<ul>
|
||
<li><a href="https://developer.apple.com/library/mac/documentation/Swift/Conceptual/Swift_Programming_Language/GuidedTour.html">Apple: A Swift Tour</a></li>
|
||
<li><a href="https://developer.apple.com/library/mac/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html#//apple_ref/doc/uid/TP40014097-CH5-XID_467">Apple: Swift Programming Language</a></li>
|
||
<li><a href="https://itunes.apple.com/us/book/swift-programming-language/id881256329?mt=11">Apple iBooks: Swift Programming Language</a></li>
|
||
<li><a href="https://developer.apple.com/library/ios/documentation/swift/conceptual/buildingcocoaapps/index.html">Apple: Using Swift with Objective-C and Cocoa</a></li>
|
||
<li><a href="http://www.objc.io">objc.io</a></li>
|
||
<li><a href="http://nshipster.com">NSHipster</a></li>
|
||
<li><a href="http://www.objc.io/books/">Functional Programming in Swift</a></li>
|
||
</ul>
|
||
<h3 id="table-of-contents"><a class="header" href="#table-of-contents">Table of Contents</a></h3>
|
||
<ul>
|
||
<li><a href="#commenting">Commenting</a></li>
|
||
<li><a href="#data-types">Data Types</a></li>
|
||
<li><a href="#operators">Operators</a></li>
|
||
<li><a href="#operator-overloading">Operator Overloading</a></li>
|
||
<li><a href="#declaring-classes">Declaring Classes</a></li>
|
||
<li><a href="#declarations">Declarations</a></li>
|
||
<li><a href="#literals">Literals</a></li>
|
||
<li><a href="#functions">Functions</a></li>
|
||
<li><a href="#constants-and-variables">Constants and Variables</a></li>
|
||
<li><a href="#naming-conventions">Naming Conventions</a></li>
|
||
<li><a href="#closures">Closures</a></li>
|
||
<li><a href="#generics">Generics</a></li>
|
||
<li><a href="#control-statements">Control Statements</a></li>
|
||
<li><a href="#extending-classes">Extending Classes</a></li>
|
||
<li><a href="#error-handling">Error Handling</a></li>
|
||
<li><a href="#passing-information">Passing Information</a></li>
|
||
<li><a href="#user-defaults">User Defaults</a></li>
|
||
<li><a href="#common-patterns">Common Patterns</a></li>
|
||
<li><a href="#unicode-support">Unicode Support</a></li>
|
||
</ul>
|
||
<h2 id="commenting"><a class="header" href="#commenting">Commenting</a></h2>
|
||
<p>Comments should be used to organize code and to provide extra information for future refactoring or for other developers who might be reading your code. Comments are ignored by the compiler so they do not increase the compiled program size.
|
||
Two ways of commenting:</p>
|
||
<pre><code class="language-swift">// This is an inline comment
|
||
/* This is a block comment
|
||
and it can span multiple lines. */
|
||
// You can also use it to comment out code
|
||
/*
|
||
func doWork() {
|
||
// Implement this
|
||
}
|
||
*/
|
||
</code></pre>
|
||
<h3 id="mark"><a class="header" href="#mark">MARK</a></h3>
|
||
<p>Using <code>MARK</code> to organize your code:</p>
|
||
<pre><code class="language-swift">// MARK: - Use mark to logically organize your code
|
||
// Declare some functions or variables here
|
||
// MARK: - They also show up nicely in the properties/functions list in Xcode
|
||
// Declare some more functions or variables here
|
||
</code></pre>
|
||
<h3 id="fixme"><a class="header" href="#fixme">FIXME</a></h3>
|
||
<p>Using <code>FIXME</code> to remember to fix your code:</p>
|
||
<pre><code class="language-swift">// Some broken code might be here
|
||
// FIXME: Use fixme to create a reminder to fix broken code later
|
||
</code></pre>
|
||
<p><code>FIXME</code> works a lot like <code>MARK</code> because it makes organizing code easier, but it’s used exclusively when you need to remember to fix something.</p>
|
||
<h3 id="todo"><a class="header" href="#todo">TODO</a></h3>
|
||
<p>Using <code>TODO</code> to remember to add, delete, or generally refactor your code:</p>
|
||
<pre><code class="language-swift">// Some incomplete code might be here
|
||
// TODO: Use todo to create a reminder to finish things up later
|
||
</code></pre>
|
||
<p><code>TODO</code> is very similar to <code>FIXME</code> and <code>MARK</code>, but it’s used exclusively when you need to remember to add, delete, or change your code later.
|
||
<strong>Auto-generating method documentation:</strong>
|
||
In a method’s preceding line, press <code>⌥ Option + ⌘ Command + /</code> to automatically generate a documentation stub for your method.</p>
|
||
<h2 id="data-types"><a class="header" href="#data-types">Data Types</a></h2>
|
||
<h3 id="size"><a class="header" href="#size">Size</a></h3>
|
||
<p>Permissible sizes of data types are determined by how many bytes of memory are allocated for that specific type and whether it’s a 32-bit or 64-bit environment. In a 32-bit environment, <code>long</code> is given 4 bytes, which equates to a total range of <code>2^(4*8)</code> (with 8 bits in a byte) or <code>4294967295</code>. In a 64-bit environment, <code>long</code> is given 8 bytes, which equates to <code>2^(8*8)</code> or <code>1.84467440737096e19</code>.
|
||
For a complete guide to 64-bit changes, please <a href="https://developer.apple.com/library/mac/documentation/Darwin/Conceptual/64bitPorting/transition/transition.html#//apple_ref/doc/uid/TP40001064-CH207-TPXREF101">see the transition document</a>.</p>
|
||
<h3 id="c-primitives"><a class="header" href="#c-primitives">C Primitives</a></h3>
|
||
<p>Unless you have a good reason to use C primitives, you should just use the Swift types to ensure compability going foward.
|
||
In fact, Swift just aliases C types to a Swift equivalent:</p>
|
||
<pre><code class="language-swift">// C char is aliased as an Int8 and unsigned as UInt8
|
||
let aChar = CChar()
|
||
let anUnsignedChar = CUnsignedChar()
|
||
print("C char size: \(MemoryLayout.size(ofValue: aChar)) with min: \(Int8.min) and max: \(Int8.max)")
|
||
// C char size: 1 with min: -128 and max: 127
|
||
print("C unsigned char size: \(MemoryLayout.size(ofValue: anUnsignedChar)) with min: \(UInt8.min) and max: \(UInt8.max)")
|
||
// C unsigned char size: 1 with min: 0 and max: 255
|
||
// C short is aliased as an Int16 and unsigned as UInt16
|
||
let aShort = CShort()
|
||
let unsignedShort = CUnsignedShort()
|
||
print("C short size: \(MemoryLayout.size(ofValue: aShort)) with min: \(Int16.min) and max: \(Int16.max)")
|
||
// C short size: 2 with min: -32768 and max: 32767
|
||
print("C unsigned short size: \(MemoryLayout.size(ofValue: unsignedShort)) with min: \(UInt16.min) and max: \(UInt16.max)")
|
||
// C unsigned short size: 2 with min: 0 and max: 65535
|
||
// C int is aliased as an Int32 and unsigned as UInt32
|
||
let anInt = CInt()
|
||
let unsignedInt = CUnsignedInt()
|
||
print("C int size: \(MemoryLayout.size(ofValue: anInt)) with min: \(Int32.min) and max: \(Int32.max)")
|
||
// C int size: 4 with min: -2147483648 and max: 2147483647
|
||
print("C unsigned int size: \(MemoryLayout.size(ofValue: unsignedInt)) with min: \(UInt32.min) and max: \(UInt32.max)")
|
||
// C unsigned int size: 4 with min: 0 and max: 4294967295
|
||
// C long is aliased as an Int and unsigned as UInt
|
||
let aLong = CLong()
|
||
let unsignedLong = CUnsignedLong()
|
||
print("C long size: \(MemoryLayout.size(ofValue: aLong)) with min: \(Int.min) and max: \(Int.max)")
|
||
// C long size: 8 with min: -9223372036854775808 and max: 9223372036854775807
|
||
print("C unsigned long size: \(MemoryLayout.size(ofValue: unsignedLong)) with min: \(UInt.min) and max: \(UInt.max)")
|
||
// C unsigned long size: 8 with min: 0 and max: 18446744073709551615
|
||
// C long long is aliased as an Int64 and unsigned as UInt64
|
||
let aLongLong = CLongLong()
|
||
let unsignedLongLong = CUnsignedLongLong()
|
||
print("C long long size: \(MemoryLayout.size(ofValue: aLongLong)) with min: \(Int64.min) and max: \(Int64.max)")
|
||
// C long long size: 8 with min: -9223372036854775808 and max: 9223372036854775807
|
||
print("C unsigned long long size: \(MemoryLayout.size(ofValue: unsignedLongLong)) with min: \(UInt64.min) and max: \(UInt64.max)")
|
||
// C unsigned long long size: 8 with min: 0 and max: 18446744073709551615
|
||
</code></pre>
|
||
<p>From the <a href="https://developer.apple.com/library/ios/documentation/swift/conceptual/buildingcocoaapps/InteractingWithCAPIs.html">docs</a>:
|
||
C Type | Swift Type
|
||
:—: | :—:
|
||
| bool | CBool
|
||
| char, signed char | CChar
|
||
| unsigned char | CUnsignedChar
|
||
| short | CShort
|
||
| unsigned short | CUnsignedShort
|
||
| int | CInt
|
||
| unsigned int | CUnsignedInt
|
||
| long | CLong
|
||
| unsigned long | CUnsignedLong
|
||
| long long | CLongLong
|
||
| unsigned long long | CUnsignedLongLong
|
||
| wchar_t | CWideChar
|
||
| char16_t | CChar16
|
||
| char32_t | CChar32
|
||
| float | CFloat
|
||
| double | CDouble</p>
|
||
<h4 id="integers"><a class="header" href="#integers">Integers</a></h4>
|
||
<p>Integers can be signed or unsigned. When signed, they can be either positive or negative and when unsigned, they can only be positive.
|
||
Apple states: <em>Unless you need to work with a specific size of integer, always use <code>Int</code> for integer values in your code. This aids code consistency and interoperability. Even on 32-bit platforms, <code>Int</code> […] is large enough for many integer ranges.</em>
|
||
<strong>Fixed width integer types with their accompanying byte sizes as the variable names:</strong></p>
|
||
<pre><code class="language-swift">// Exact integer types
|
||
let aOneByteInt: Int8 = 127
|
||
let aOneByteUnsignedInt: UInt8 = 255
|
||
let aTwoByteInt: Int16 = 32767
|
||
let aTwoByteUnsignedInt: UInt16 = 65535
|
||
let aFourByteInt: Int32 = 2147483647
|
||
let aFourByteUnsignedInt: UInt32 = 4294967295
|
||
let anEightByteInt: Int64 = 9223372036854775807
|
||
let anEightByteUnsignedInt: UInt64 = 18446744073709551615
|
||
// Minimum integer types
|
||
let aTinyInt: Int8 = 127
|
||
let aTinyUnsignedInt: UInt8 = 255
|
||
let aMediumInt: Int16 = 32767
|
||
let aMediumUnsignedInt: UInt16 = 65535
|
||
let aNormalInt: Int32 = 2147483647
|
||
let aNormalUnsignedInt: UInt32 = 4294967295
|
||
let aBigInt: Int64 = 9223372036854775807
|
||
let aBigUnsignedInt: UInt64 = 18446744073709551615
|
||
// The largest supported integer type
|
||
let theBiggestInt: IntMax = 9223372036854775807
|
||
let theBiggestUnsignedInt: UIntMax = 18446744073709551615
|
||
</code></pre>
|
||
<h4 id="floating-point"><a class="header" href="#floating-point">Floating Point</a></h4>
|
||
<p>Floats cannot be signed or unsigned.</p>
|
||
<pre><code class="language-swift">// Single precision (32-bit) floating-point. Use it when floating-point values do not require 64-bit precision.
|
||
let aFloat = Float()
|
||
print("Float size: \(MemoryLayout.size(ofValue: aFloat))")
|
||
// Float size: 4
|
||
// Double precision (64-bit) floating-point. Use it when floating-point values must be very large or particularly precise.
|
||
let aDouble = Double()
|
||
print("Double size: \(MemoryLayout.size(ofValue: aDouble))")
|
||
// Double size: 8
|
||
</code></pre>
|
||
<h4 id="boolean"><a class="header" href="#boolean">Boolean</a></h4>
|
||
<pre><code class="language-swift">// Boolean
|
||
let isBool: Bool = true // Or false
|
||
</code></pre>
|
||
<p>In Objective-C comparative statements, <code>0</code> and <code>nil</code> were considered <code>false</code> and any non-zero/non-nil values were considered <code>true</code>. However, this is not the case in Swift. Instead, you’ll need to directly check their value such as <code>if x == 0</code> or <code>if object != nil</code></p>
|
||
<h4 id="primitives"><a class="header" href="#primitives">Primitives</a></h4>
|
||
<p><strong>nil</strong> : Used to specify a null object pointer. When classes are first initialized, all properties of the class point to <code>nil</code>.</p>
|
||
<h3 id="enum--bitmask-types"><a class="header" href="#enum--bitmask-types">Enum & Bitmask Types</a></h3>
|
||
<p>Enumeration types can be defined as follows:</p>
|
||
<pre><code class="language-swift">// Specifying a typed enum with a name (recommended way)
|
||
enum UITableViewCellStyle: Int {
|
||
case default, valueOne, valueTwo, subtitle
|
||
}
|
||
// Accessing it:
|
||
let cellStyle: UITableViewCellStyle = .default
|
||
</code></pre>
|
||
<p>As of Swift 3, all enum options should be named in lowerCamelCased.</p>
|
||
<h4 id="working-with-bitmasks"><a class="header" href="#working-with-bitmasks">Working with Bitmasks</a></h4>
|
||
<p>Newer Swift versions have a nice substitute for the old <code>NS_OPTIONS</code> macro for creating bitmasks to compare to.
|
||
An example for posterity:</p>
|
||
<pre><code class="language-swift">struct Options: OptionSet {
|
||
let rawValue: Int
|
||
init(rawValue: Int) {
|
||
self.rawValue = rawValue
|
||
}
|
||
init(number: Int) {
|
||
self.init(rawValue: 1 << number)
|
||
}
|
||
static let OptionOne = Options(number: 0)
|
||
static let OptionTwo = Options(number: 1)
|
||
static let OptionThree = Options(number: 2)
|
||
}
|
||
let options: Options = [.OptionOne, .OptionTwo]
|
||
options.contains(.OptionOne) // true
|
||
options.contains(.OptionThree) // false
|
||
</code></pre>
|
||
<h3 id="type-casting"><a class="header" href="#type-casting">Type Casting</a></h3>
|
||
<p>Sometimes it is necessary to cast an object into a specific class or data type. Examples of this would be casting from a <code>Float</code> to an <code>Int</code> or from a <code>UITableViewCell</code> to a subclass such as <code>RPTableViewCell</code>.</p>
|
||
<h4 id="checking-types"><a class="header" href="#checking-types">Checking Types</a></h4>
|
||
<p>Swift uses <code>is</code> and <code>as</code> both for checking object types as well as conformance to a given protocol.</p>
|
||
<h4 id="operator-is"><a class="header" href="#operator-is">Operator: is</a></h4>
|
||
<p>Checking object type using <code>is</code>:</p>
|
||
<pre><code class="language-swift">if item is Movie {
|
||
movieCount += 1
|
||
print("It is a movie.")
|
||
} else if item is Song {
|
||
songCount += 1
|
||
print("It is a song.")
|
||
}
|
||
</code></pre>
|
||
<p>The <code>is</code> operator returns <code>true </code>if an instance is of that object type, or conforms to the specified protocol, and returns <code>false</code> if it does not.</p>
|
||
<h4 id="operators-as-and-as"><a class="header" href="#operators-as-and-as">Operators: as? and as!</a></h4>
|
||
<p>If you want to be able to easily access the data during one of these checks, you can use <code>as?</code> to optionally (or <code>as!</code> to force) unwrap the object when necessary:</p>
|
||
<pre><code class="language-swift">for item in library {
|
||
if let movie = item as? Movie {
|
||
print("Director: \(movie.director)")
|
||
} else if let song = item as? Song {
|
||
print("Artist: \(song.artist)")
|
||
}
|
||
}
|
||
</code></pre>
|
||
<p>The <code>as?</code> version of the downcast operator returns an optional value of the object or protocol’s type, and this value is <code>nil</code> if the downcast fails or this instance does not conform to the specified protocol.
|
||
The <code>as!</code> version of the downcast operator forces the downcast to the specified object or protocol type and triggers a runtime error if the downcast does not succeed.</p>
|
||
<h4 id="casting-from-generic-types"><a class="header" href="#casting-from-generic-types">Casting from Generic Types</a></h4>
|
||
<p>If you’re working with <code>AnyObject</code> objects given from the Cocoa API, you can use:</p>
|
||
<pre><code class="language-swift">for movie in someObjects as! [Movie] {
|
||
// do stuff
|
||
}
|
||
</code></pre>
|
||
<p>If given an array with <code>Any</code> objects, you can use a <code>switch</code> statement with the type defined for each <code>case</code>:</p>
|
||
<pre><code class="language-swift">var things = [Any]()
|
||
for thing in things {
|
||
switch thing {
|
||
case 0 as Int:
|
||
print("Zero as an Int")
|
||
case let someString as! String:
|
||
print("S string value of \"\(someString)\"")
|
||
case let (x, y) as! (Double, Double):
|
||
print("An (x, y) point at \(x), \(y)")
|
||
case let movie as! Movie:
|
||
print("A movie called '\(movie.name)' by director \(movie.director)")
|
||
default:
|
||
print("Didn't match any of the cases specified")
|
||
}
|
||
}
|
||
</code></pre>
|
||
<h4 id="basic-casting"><a class="header" href="#basic-casting">Basic Casting</a></h4>
|
||
<p>Swift also offers some simple methods of casting between it’s given data types.</p>
|
||
<pre><code class="language-swift">// Example 1:
|
||
let aDifferentDataType: Float = 3.14
|
||
let anInt: Int = Int(aDifferentDataType)
|
||
// Example 2:
|
||
let aString: String = String(anInt)
|
||
</code></pre>
|
||
<h2 id="operators"><a class="header" href="#operators">Operators</a></h2>
|
||
<p>Swift supports most standard C operators and improves several capabilities to eliminate common coding errors. The assignment operator <code>=</code> does not return a value, to prevent it from being mistakenly used when the equal to operator <code>==</code> is intended.
|
||
Arithmetic operators (<code>+</code>, <code>-</code>, <code>*</code>, <code>/</code>, <code>%</code>) detect and disallow value overflow, to avoid unexpected results when working with numbers that become larger or smaller than the allowed value range of the type that stores them.</p>
|
||
<h4 id="arithmetic-operators"><a class="header" href="#arithmetic-operators">Arithmetic Operators</a></h4>
|
||
<div class="table-wrapper"><table><thead><tr><th style="text-align: center">Operator</th><th>Purpose</th></tr></thead><tbody>
|
||
<tr><td style="text-align: center">+</td><td>Addition</td></tr>
|
||
<tr><td style="text-align: center">-</td><td>Subtraction</td></tr>
|
||
<tr><td style="text-align: center">*</td><td>Multiplication</td></tr>
|
||
<tr><td style="text-align: center">/</td><td>Division</td></tr>
|
||
<tr><td style="text-align: center">%</td><td>Remainder</td></tr>
|
||
</tbody></table>
|
||
</div>
|
||
<h4 id="comparative-operators"><a class="header" href="#comparative-operators">Comparative Operators</a></h4>
|
||
<div class="table-wrapper"><table><thead><tr><th style="text-align: center">Operator</th><th>Purpose</th></tr></thead><tbody>
|
||
<tr><td style="text-align: center">==</td><td>Equal to</td></tr>
|
||
<tr><td style="text-align: center">===</td><td>Identical to</td></tr>
|
||
<tr><td style="text-align: center">!=</td><td>Not equal to</td></tr>
|
||
<tr><td style="text-align: center">!==</td><td>Not identical to</td></tr>
|
||
<tr><td style="text-align: center">~=</td><td>Pattern match</td></tr>
|
||
<tr><td style="text-align: center">></td><td>Greater than</td></tr>
|
||
<tr><td style="text-align: center"><</td><td>Less than</td></tr>
|
||
<tr><td style="text-align: center">>=</td><td>Greater than or equal to</td></tr>
|
||
<tr><td style="text-align: center"><=</td><td>Less than or equal to</td></tr>
|
||
</tbody></table>
|
||
</div>
|
||
<h4 id="assignment-operators"><a class="header" href="#assignment-operators">Assignment Operators</a></h4>
|
||
<div class="table-wrapper"><table><thead><tr><th style="text-align: center">Operator</th><th>Purpose</th></tr></thead><tbody>
|
||
<tr><td style="text-align: center">=</td><td>Assign</td></tr>
|
||
<tr><td style="text-align: center">+=</td><td>Addition</td></tr>
|
||
<tr><td style="text-align: center">-=</td><td>Subtraction</td></tr>
|
||
<tr><td style="text-align: center">*=</td><td>Multiplication</td></tr>
|
||
<tr><td style="text-align: center">/=</td><td>Division</td></tr>
|
||
<tr><td style="text-align: center">%=</td><td>Remainder</td></tr>
|
||
<tr><td style="text-align: center">&=</td><td>Bitwise AND</td></tr>
|
||
<tr><td style="text-align: center">|=</td><td>Bitwise Inclusive OR</td></tr>
|
||
<tr><td style="text-align: center">^=</td><td>Exclusive OR</td></tr>
|
||
<tr><td style="text-align: center"><<=</td><td>Shift Left</td></tr>
|
||
<tr><td style="text-align: center">>>=</td><td>Shift Right</td></tr>
|
||
</tbody></table>
|
||
</div>
|
||
<h4 id="logical-operators"><a class="header" href="#logical-operators">Logical Operators</a></h4>
|
||
<div class="table-wrapper"><table><thead><tr><th style="text-align: center">Operator</th><th>Purpose</th></tr></thead><tbody>
|
||
<tr><td style="text-align: center">!</td><td>NOT</td></tr>
|
||
<tr><td style="text-align: center">&&</td><td>Logical AND</td></tr>
|
||
<tr><td style="text-align: center">||</td><td>Logical OR</td></tr>
|
||
</tbody></table>
|
||
</div>
|
||
<h4 id="range-operators"><a class="header" href="#range-operators">Range Operators</a></h4>
|
||
<div class="table-wrapper"><table><thead><tr><th style="text-align: center">Operator</th><th>Purpose</th></tr></thead><tbody>
|
||
<tr><td style="text-align: center">..<</td><td>Half-open range</td></tr>
|
||
<tr><td style="text-align: center">…</td><td>Closed range</td></tr>
|
||
</tbody></table>
|
||
</div>
|
||
<h4 id="bitwise-operators"><a class="header" href="#bitwise-operators">Bitwise Operators</a></h4>
|
||
<div class="table-wrapper"><table><thead><tr><th style="text-align: center">Operator</th><th>Purpose</th></tr></thead><tbody>
|
||
<tr><td style="text-align: center">&</td><td>Bitwise AND</td></tr>
|
||
<tr><td style="text-align: center">|</td><td>Bitwise Inclusive OR</td></tr>
|
||
<tr><td style="text-align: center">^</td><td>Exclusive OR</td></tr>
|
||
<tr><td style="text-align: center">~</td><td>Unary complement (bit inversion)</td></tr>
|
||
<tr><td style="text-align: center"><<</td><td>Shift Left</td></tr>
|
||
<tr><td style="text-align: center">>></td><td>Shift Right</td></tr>
|
||
</tbody></table>
|
||
</div>
|
||
<h4 id="overflow-and-underflow-operators"><a class="header" href="#overflow-and-underflow-operators">Overflow and Underflow Operators</a></h4>
|
||
<p>Typically, assigning or incrementing an integer, float, or double past it’s range would result in a runtime error. However, if you’d instead prefer to safely truncate the number of available bits, you can opt-in to have the variable overflow or underflow using the following operators:
|
||
Operator | Purpose
|
||
:—: | —
|
||
| &+ | Addition
|
||
| &- | Subtraction
|
||
| &* | Multiplication
|
||
Example for unsigned integers (works similarly for signed):</p>
|
||
<pre><code class="language-swift">var willOverflow = UInt8.max
|
||
// willOverflow equals 255, which is the largest value a UInt8 can hold
|
||
willOverflow = willOverflow &+ 1
|
||
// willOverflow is now equal to 0
|
||
var willUnderflow = UInt8.min
|
||
// willUnderflow equals 0, which is the smallest value a UInt8 can hold
|
||
willUnderflow = willUnderflow &- 1
|
||
// willUnderflow is now equal to 255
|
||
</code></pre>
|
||
<h4 id="other-operators"><a class="header" href="#other-operators">Other Operators</a></h4>
|
||
<div class="table-wrapper"><table><thead><tr><th style="text-align: center">Operator</th><th>Purpose</th></tr></thead><tbody>
|
||
<tr><td style="text-align: center">??</td><td>Nil coalescing</td></tr>
|
||
<tr><td style="text-align: center">?:</td><td>Ternary conditional</td></tr>
|
||
<tr><td style="text-align: center">!</td><td>Force unwrap object value</td></tr>
|
||
<tr><td style="text-align: center">?</td><td>Safely unwrap object value</td></tr>
|
||
</tbody></table>
|
||
</div>
|
||
<h2 id="operator-overloading"><a class="header" href="#operator-overloading">Operator Overloading</a></h2>
|
||
<p>Swift allows you to overwrite existing operators or define new operators for existing or custom types. For example, this is why in Swift you can join strings using the <code>+</code> operator, even though it is typically used for math.
|
||
Operator overloading is limited to the following symbols, <code>/ = - + * % < > ! & | ^ . ~</code>, however you cannot overload the <code>=</code> operator by itself (it must be combined with another symbol).
|
||
Operators can be specified as:</p>
|
||
<ul>
|
||
<li><code>prefix</code>: goes before an object such as <code>-negativeNumber</code></li>
|
||
<li><code>infix</code>: goes between two objects, such as <code>a + b</code></li>
|
||
<li><code>postfix</code>: goes after an object, such as <code>unwrapMe!</code>
|
||
Examples:</li>
|
||
</ul>
|
||
<pre><code class="language-swift">struct Vector2D: CustomStringConvertible {
|
||
var x = 0.0, y = 0.0
|
||
var description: String {
|
||
return "Vector2D(x: \(x), y: \(y))"
|
||
}
|
||
}
|
||
infix operator +-: AdditionPrecedence
|
||
extension Vector2D {
|
||
static func +- (left: Vector2D, right: Vector2D) -> Vector2D {
|
||
return Vector2D(x: left.x + right.x, y: left.y - right.y)
|
||
}
|
||
}
|
||
let firstVector = Vector2D(x: 1.0, y: 2.0)
|
||
let secondVector = Vector2D(x: 3.0, y: 4.0)
|
||
let plusMinusVector = firstVector +- secondVector
|
||
// plusMinusVector is a Vector2D instance with values of (4.0, -2.0)
|
||
</code></pre>
|
||
<h2 id="declaring-classes"><a class="header" href="#declaring-classes">Declaring Classes</a></h2>
|
||
<p>Classes are typically declared using separate <code>.swift</code> files, but multiple classes can also be created within the same file if you’d like to organize it that way.
|
||
Unlike Objective-C, there’s no need for an interface file (<code>.h</code>) in Swift.
|
||
The implementation file should contain (in this order):</p>
|
||
<ul>
|
||
<li>Any needed <code>import</code> statements</li>
|
||
<li>A <code>class</code> declaration which contains any constants or variables necessary for the class</li>
|
||
<li>All public and private functions
|
||
Example:
|
||
MyClass.swift</li>
|
||
</ul>
|
||
<pre><code class="language-swift">import UIKit
|
||
class MyClass {
|
||
// Declare any constants or variables at the top
|
||
let kRPErrorDomain = "com.myIncredibleApp.errors"
|
||
var x: Int, y: Int
|
||
// Use mark statements to logically organize your code
|
||
// MARK: - Class Methods, e.g. MyClass.functionName()
|
||
class func alert() {
|
||
print("This is a class function.")
|
||
}
|
||
// MARK: - Instance Methods, e.g. myClass.functionName()
|
||
init(x: Int, y: Int) {
|
||
self.x = x
|
||
self.y = y
|
||
}
|
||
// MARK: - Private Methods
|
||
private func pointLocation() -> String {
|
||
return "x: \(x), y: \(y)"
|
||
}
|
||
}
|
||
</code></pre>
|
||
<h4 id="instantiation"><a class="header" href="#instantiation">Instantiation</a></h4>
|
||
<p>When you want to create a new instance of a class, you use the syntax:</p>
|
||
<pre><code class="language-swift">let myClass = MyClass(x: 1, y: 2)
|
||
</code></pre>
|
||
<p>where <code>x</code> and <code>y</code> are variables that are passed in at the time of instantiation.</p>
|
||
<h2 id="declarations"><a class="header" href="#declarations">Declarations</a></h2>
|
||
<p>More info <a href="https://developer.apple.com/library/ios/documentation/swift/conceptual/Swift_Programming_Language/Declarations.html#//apple_ref/doc/uid/TP40014097-CH34-XID_704">here in the docs</a>.</p>
|
||
<h4 id="preprocessor"><a class="header" href="#preprocessor">Preprocessor</a></h4>
|
||
<p>Swift doesn’t come with a preprocessor so it only supports a limited number of statements for build time. Things like <code>#define</code> have been replaced with global constants defined outside of a class.
|
||
Directive | Purpose
|
||
:—: | —
|
||
| #if | An <code>if</code> conditional statement
|
||
| #elif | An <code>else if</code> conditional statement
|
||
| #else | An <code>else</code> conditional statement
|
||
| #endif | An <code>end if</code> conditional statement</p>
|
||
<h4 id="imports"><a class="header" href="#imports">Imports</a></h4>
|
||
<div class="table-wrapper"><table><thead><tr><th style="text-align: center">Directive</th><th>Purpose</th></tr></thead><tbody>
|
||
<tr><td style="text-align: center">import</td><td>Imports a framework</td></tr>
|
||
</tbody></table>
|
||
</div>
|
||
<h4 id="constants--variables"><a class="header" href="#constants--variables">Constants & Variables</a></h4>
|
||
<div class="table-wrapper"><table><thead><tr><th style="text-align: center">Directive</th><th>Purpose</th></tr></thead><tbody>
|
||
<tr><td style="text-align: center">let</td><td>Declares local or global constant</td></tr>
|
||
<tr><td style="text-align: center">var</td><td>Declares a local or global variable</td></tr>
|
||
<tr><td style="text-align: center">class</td><td>Declares a class-level constant or variable</td></tr>
|
||
<tr><td style="text-align: center">static</td><td>Declares a static type</td></tr>
|
||
</tbody></table>
|
||
</div>
|
||
<h4 id="classes-structure-functions-and-protocols"><a class="header" href="#classes-structure-functions-and-protocols">Classes, Structure, Functions and Protocols</a></h4>
|
||
<div class="table-wrapper"><table><thead><tr><th style="text-align: center">Directive</th><th>Purpose</th></tr></thead><tbody>
|
||
<tr><td style="text-align: center">typealias</td><td>Introduces a named alias of an existing type</td></tr>
|
||
<tr><td style="text-align: center">enum</td><td>Introduces a named enumeration</td></tr>
|
||
<tr><td style="text-align: center">struct</td><td>Introduces a named structure</td></tr>
|
||
<tr><td style="text-align: center">class</td><td>Begins the declaration of a class</td></tr>
|
||
<tr><td style="text-align: center">init</td><td>Introduces an initializer for a class, struct or enum</td></tr>
|
||
<tr><td style="text-align: center">init?</td><td>Produces an optional instance or an implicitly unwrapped optional instance; can return <code>nil</code></td></tr>
|
||
<tr><td style="text-align: center">deinit</td><td>Declares a function called automatically when there are no longer any references to a class object, just before the class object is deallocated</td></tr>
|
||
<tr><td style="text-align: center">func</td><td>Begins the declaration of a function</td></tr>
|
||
<tr><td style="text-align: center">protocol</td><td>Begins the declaration of a formal protocol</td></tr>
|
||
<tr><td style="text-align: center">static</td><td>Defines as type-level within struct or enum</td></tr>
|
||
<tr><td style="text-align: center">convenience</td><td>Delegate the init process to another initializer or to one of the class’s designated initializers</td></tr>
|
||
<tr><td style="text-align: center">extension</td><td>Extend the behavior of class, struct, or enum</td></tr>
|
||
<tr><td style="text-align: center">subscript</td><td>Adds subscripting support for objects of a particular type, normally for providing a convenient syntax for accessing elements in a collective, list or sequence</td></tr>
|
||
<tr><td style="text-align: center">override</td><td>Marks overriden initializers</td></tr>
|
||
</tbody></table>
|
||
</div>
|
||
<h4 id="operators-1"><a class="header" href="#operators-1">Operators</a></h4>
|
||
<div class="table-wrapper"><table><thead><tr><th style="text-align: center">Directive</th><th>Purpose</th></tr></thead><tbody>
|
||
<tr><td style="text-align: center">operator</td><td>Introduces a new infix, prefix, or postfix operator</td></tr>
|
||
</tbody></table>
|
||
</div>
|
||
<h4 id="declaration-modifiers"><a class="header" href="#declaration-modifiers">Declaration Modifiers</a></h4>
|
||
<div class="table-wrapper"><table><thead><tr><th style="text-align: center">Directive</th><th>Purpose</th></tr></thead><tbody>
|
||
<tr><td style="text-align: center">dynamic</td><td>Marks a member declaration so that access is always dynamically dispatched using the Objective-C runtime and never inlined or devirtualized by the compiler</td></tr>
|
||
<tr><td style="text-align: center">final</td><td>Specifies that a class can’t be subclassed, or that a property, function, or subscript of a class can’t be overridden in any subclass</td></tr>
|
||
<tr><td style="text-align: center">lazy</td><td>Indicates that the property’s initial value is calculated and stored at most once, when the property is first accessed</td></tr>
|
||
<tr><td style="text-align: center">optional</td><td>Specifies that a protocol’s property, function, or subscript isn’t required to be implemented by conforming members</td></tr>
|
||
<tr><td style="text-align: center">required</td><td>Marks the initializer so that every subclass must implement it</td></tr>
|
||
<tr><td style="text-align: center">weak</td><td>Indicates that the variable or property has a weak reference to the object stored as its value</td></tr>
|
||
</tbody></table>
|
||
</div>
|
||
<h4 id="access-control"><a class="header" href="#access-control">Access Control</a></h4>
|
||
<div class="table-wrapper"><table><thead><tr><th style="text-align: center">Directive</th><th>Purpose</th></tr></thead><tbody>
|
||
<tr><td style="text-align: center">open</td><td>Can be subclassed outside of its own module and its methods overridden as well; truly open to modification by others and useful for framework builders</td></tr>
|
||
<tr><td style="text-align: center">public</td><td>Can only be subclassed by its own module or have its methods overridden by others within the same module</td></tr>
|
||
<tr><td style="text-align: center">internal</td><td>(Default) Indicates the entities are only available to the entire module that includes the definition, e.g. an app or framework target</td></tr>
|
||
<tr><td style="text-align: center">fileprivate</td><td>Indicates the entities are available only from within the source file where they are defined</td></tr>
|
||
<tr><td style="text-align: center">private</td><td>Indicates the entities are available only from within the declaring scope within the file where they are defined (e.g. within the <code>{ }</code> brackets only)</td></tr>
|
||
</tbody></table>
|
||
</div>
|
||
<h2 id="literals"><a class="header" href="#literals">Literals</a></h2>
|
||
<p>Literals are compiler directives which provide a shorthand notation for creating common objects.
|
||
Syntax | What it does
|
||
:—: | —
|
||
| <code>"string"</code> | Returns a <code>String</code> object
|
||
| <code>28</code> | Returns an <code>Int</code>
|
||
| <code>3.14</code>, <code>0xFp2</code>, <code>1.25e2</code> | Returns a <code>Double</code> object
|
||
| <code>true</code>, <code>false</code> | Returns a <code>Bool</code> object
|
||
| <code>[]</code> | Returns an <code>Array</code> object
|
||
| <code>[keyName:value]</code> | Returns a <code>Dictionary</code> object
|
||
| <code>0b</code> | Returns a binary digit
|
||
| <code>0o</code> | Returns an octal digit
|
||
| <code>0x</code> | Returns a hexadecimal digit</p>
|
||
<h4 id="strings"><a class="header" href="#strings">Strings</a></h4>
|
||
<p>Special characters can be included:</p>
|
||
<ul>
|
||
<li>Null Character: <code>\0</code></li>
|
||
<li>Backslash: <code>\\</code> (can be used to escape a double quote)</li>
|
||
<li>Horizontal Tab: <code>\t</code></li>
|
||
<li>Line Feed: <code>\n</code></li>
|
||
<li>Carriage Return: <code>\r</code></li>
|
||
<li>Double Quote: <code>\"</code></li>
|
||
<li>Single Quote: <code>\'</code></li>
|
||
<li>Unicode scalar: <code>\u{n}</code> where n is between one and eight hexadecimal digits</li>
|
||
</ul>
|
||
<h4 id="array-access-syntax"><a class="header" href="#array-access-syntax">Array Access Syntax</a></h4>
|
||
<pre><code class="language-swift">let example = [ "hi", "there", 23, true ]
|
||
print("item at index 0: \(example[0])")
|
||
</code></pre>
|
||
<h4 id="dictionary-access-syntax"><a class="header" href="#dictionary-access-syntax">Dictionary Access Syntax</a></h4>
|
||
<pre><code class="language-swift">let example = [ "hi" : "there", "iOS" : "people" ]
|
||
if let value = example["hi"] {
|
||
print("hi \(value)")
|
||
}
|
||
</code></pre>
|
||
<h4 id="mutability"><a class="header" href="#mutability">Mutability</a></h4>
|
||
<p>For mutable literals, declare it with <code>var</code>; immutable with <code>let</code>.</p>
|
||
<h2 id="functions"><a class="header" href="#functions">Functions</a></h2>
|
||
<h4 id="declaration-syntax"><a class="header" href="#declaration-syntax">Declaration Syntax</a></h4>
|
||
<p>Functions without a return type use this format:</p>
|
||
<pre><code class="language-swift">// Does not return anything or take any arguments
|
||
func doWork() {
|
||
// Code
|
||
}
|
||
</code></pre>
|
||
<p><code>class</code> precedes declarations of class functions:</p>
|
||
<pre><code class="language-swift">// Call on a class, e.g. MyClass.someClassFunction()
|
||
class func someClassFunction() {
|
||
// Code
|
||
}
|
||
</code></pre>
|
||
<p><code>static</code> is similar to class functions where you don’t need an instance of the class or struct in order to call a method on it:</p>
|
||
<pre><code class="language-swift">// Call on a class/struct, e.g. MyStruct.someStaticFunction()
|
||
static func someStaticFunction() {
|
||
// Code
|
||
}
|
||
</code></pre>
|
||
<p>Declare instance functions:</p>
|
||
<pre><code class="language-swift">// Called on an instance of a class, e.g. myClass.someInstanceFunction()
|
||
func doMoreWork() {
|
||
// Code
|
||
}
|
||
</code></pre>
|
||
<p>Function arguments are declared within the parentheses:</p>
|
||
<pre><code class="language-swift">// Draws a point
|
||
func draw(point: CGPoint)
|
||
</code></pre>
|
||
<p>Return types are declared as follows:</p>
|
||
<pre><code class="language-swift">// Returns a String object for the given String argument
|
||
func sayHelloToMyLilFriend(lilFriendsName: String) -> String {
|
||
return "Oh hello, \(lilFriendsName). Cup of tea?"
|
||
}
|
||
</code></pre>
|
||
<p>You can have multiple return values, referred to as a tuple:</p>
|
||
<pre><code class="language-swift">// Returns multiple objects
|
||
func sayHelloToMyLilFriend(lilFriendsName: String) -> (msg: String, nameLength: Int) {
|
||
return ("Oh hello, \(lilFriendsName). Cup of tea?", countElements(lilFriendsName))
|
||
}
|
||
var hello = sayHelloToMyLilFriend("Rob")
|
||
print(hello.msg) // "Oh hello, Rob. Cup of tea?"
|
||
print(hello.nameLength) // 3
|
||
</code></pre>
|
||
<p>And those multiple return values can be optional:</p>
|
||
<pre><code class="language-swift">func sayHelloToMyLilFriend(lilFriendsName: String) -> (msg: String, nameLength: Int)?
|
||
</code></pre>
|
||
<p>By default, external parameter names are given when you call the function, but you can specify that one or more are not shown in the method signature by putting a <code>_</code> symbol in front of the parameter name:</p>
|
||
<pre><code class="language-swift">func sayHelloToMyLilFriend(_ lilFriendsName: String) {
|
||
// Code
|
||
}
|
||
sayHelloToMyLilFriend("Rob")
|
||
</code></pre>
|
||
<p>or you can rename the variable once within the method scope:</p>
|
||
<pre><code class="language-swift">func sayHelloToMyLilFriend(friendsName lilFriendsName: String) {
|
||
// Code
|
||
}
|
||
sayHelloToMyLilFriend(friendsName: "Rob") // and local variable is `lilFriendsName`
|
||
</code></pre>
|
||
<p>You can also specify default values for the parameters:</p>
|
||
<pre><code class="language-swift">func sayHelloToMyLilFriend(_ lilFriendsName: String = "Rob") {
|
||
// Code
|
||
}
|
||
sayHelloToMyLilFriend() // "Oh hello, Rob. Cup of tea?"
|
||
sayHelloToMyLilFriend("Jimbob") // "Oh hello, Jimbob. Cup of tea?"
|
||
</code></pre>
|
||
<p>Swift also supports variadic parameters so you can have an open-ended number of parameters passed in:</p>
|
||
<pre><code class="language-swift">func sayHelloToMyLilFriends(_ lilFriendsName: String...) {
|
||
// Code
|
||
}
|
||
sayHelloToMyLilFriends("Rob", "Jimbob", "Cletus")
|
||
// "Oh hello, Rob, Jimbob and Cletus. Cup of tea?"
|
||
</code></pre>
|
||
<p>And lastly, you can also use a prefix to declare input parameters as <code>inout</code>.
|
||
An in-out parameter has a value that is passed in to the function, is modified by the function, and is passed back out of the function to replace the original value.
|
||
You may remember <code>inout</code> parameters from Objective-C where you had to sometimes pass in an <code>&error</code> parameter to certain methods, where the <code>&</code> symbol specifies that you’re actually passing in a pointer to the object instead of the object itself. The same applies to Swift’s <code>inout</code> parameters now as well.</p>
|
||
<h4 id="calling-functions"><a class="header" href="#calling-functions">Calling Functions</a></h4>
|
||
<p>Functions are called using dot syntax: <code>myClass.doWork()</code> or <code>self.sayHelloToMyLilFriend("Rob Phillips")</code>
|
||
<code>self</code> is a reference to the function’s containing class.
|
||
At times, it is necessary to call a function in the superclass using <code>super.someMethod()</code>.</p>
|
||
<h2 id="constants-and-variables"><a class="header" href="#constants-and-variables">Constants and Variables</a></h2>
|
||
<p>Declaring a constant or variable allows you to maintain a reference to an object within a class or to pass objects between classes.
|
||
Constants are defined with <code>let</code> and variables with <code>var</code>. By nature, constants are obviously immutable (i.e. cannot be changed once they are instantiated) and variables are mutable.</p>
|
||
<pre><code class="language-swift">class MyClass {
|
||
let text = "Hello" // Constant
|
||
var isComplete: Bool // Variable
|
||
}
|
||
</code></pre>
|
||
<p>There are many ways to declare properties in Swift, so here are a few examples:</p>
|
||
<pre><code class="language-swift">var myInt = 1 // inferred type
|
||
var myExplicitInt: Int = 1 // explicit type
|
||
var x = 1, y = 2, z = 3 // declare multiple variables
|
||
let (a,b) = (1,2) // declare multiple constants
|
||
</code></pre>
|
||
<h4 id="access-levels"><a class="header" href="#access-levels">Access Levels</a></h4>
|
||
<p>The default access level for constants and variables is <code>internal</code>:</p>
|
||
<pre><code class="language-swift">class MyClass {
|
||
// Internal (default) properties
|
||
var text: String
|
||
var isComplete: Bool
|
||
}
|
||
</code></pre>
|
||
<p>To declare them publicly or openly, they should also be within a <code>public</code> or <code>open</code> class as shown below:</p>
|
||
<pre><code class="language-swift">public class MyClass {
|
||
// Public properties
|
||
public var text: String
|
||
public let x = 1
|
||
}
|
||
// Or
|
||
open class MyClass {
|
||
// Public properties
|
||
open var text: String
|
||
open let x = 1
|
||
}
|
||
</code></pre>
|
||
<p>File private variables and constants are declared with the <code>fileprivate</code> directive:</p>
|
||
<pre><code class="language-swift">class MyClass {
|
||
// Private properties
|
||
fileprivate var text: String
|
||
fileprivate let x = 1
|
||
}
|
||
</code></pre>
|
||
<h4 id="getters-and-setters"><a class="header" href="#getters-and-setters">Getters and Setters</a></h4>
|
||
<p>In Objective-C, variables were backed by getters, setters, and private instance variables created at build time. However, in Swift getters and setters are only used for computed properties and constants actually don’t have a getter or setter at all.
|
||
The getter is used to read the value, and the setter is used to write the value. The setter clause is optional, and when only a getter is needed, you can omit both clauses and simply return the requested value directly. However, if you provide a setter clause, you must also provide a getter clause.
|
||
You can overrride the getter and setter of a property to create the illusion of the Objective-C property behavior, but you’d need to store them as a private property with a different name (not recommended for most scenarios):</p>
|
||
<pre><code class="language-swift">private var _x: Int = 0
|
||
var x: Int {
|
||
get {
|
||
print("Accessing x...")
|
||
return _x
|
||
}
|
||
set {
|
||
print("Setting x...")
|
||
_x = newValue
|
||
}
|
||
}
|
||
</code></pre>
|
||
<h4 id="access-callbacks"><a class="header" href="#access-callbacks">Access Callbacks</a></h4>
|
||
<p>Swift also has callbacks for when a property will be or was set using <code>willSet</code> and <code>didSet</code> shown below:</p>
|
||
<pre><code class="language-swift">var numberOfEdits = 0
|
||
var value: String = "" {
|
||
willSet {
|
||
print("About to set value...")
|
||
}
|
||
didSet {
|
||
numberOfEdits += 1
|
||
}
|
||
}
|
||
</code></pre>
|
||
<h4 id="accessing"><a class="header" href="#accessing">Accessing</a></h4>
|
||
<p>Properties can be accessed using dot notation:</p>
|
||
<pre><code class="language-swift">myClass.myVariableOrConstant
|
||
self.myVariable // Self is optional here except within closure scopes
|
||
</code></pre>
|
||
<h4 id="local-variables"><a class="header" href="#local-variables">Local Variables</a></h4>
|
||
<p>Local variables and constants only exist within the scope of a function.</p>
|
||
<pre><code class="language-swift">func doWork() {
|
||
let localStringVariable = "Some local string variable."
|
||
self.doSomething(string: localStringVariable)
|
||
}
|
||
</code></pre>
|
||
<h2 id="naming-conventions"><a class="header" href="#naming-conventions">Naming Conventions</a></h2>
|
||
<p>The general rule of thumb: Clarity and brevity are both important, but clarity should never be sacrificed for brevity.</p>
|
||
<h4 id="functions-and-properties"><a class="header" href="#functions-and-properties">Functions and Properties</a></h4>
|
||
<p>These both use <code>camelCase</code> where the first letter of the first word is lowercase and the first letter of each additional word is capitalized.</p>
|
||
<h4 id="class-names-and-protocols"><a class="header" href="#class-names-and-protocols">Class names and Protocols</a></h4>
|
||
<p>These both use <code>CapitalCase</code> where the first letter of every word is capitalized.</p>
|
||
<h3 id="enums"><a class="header" href="#enums">Enums</a></h3>
|
||
<p>The options in an enum should be <code>lowerCamelCased</code></p>
|
||
<h4 id="functions-1"><a class="header" href="#functions-1">Functions</a></h4>
|
||
<p>These should use verbs if they perform some action (e.g. <code>performInBackground</code>). You should be able to infer what is happening, what arguments a function takes, or what is being returned just by reading a function signature.
|
||
Example:</p>
|
||
<pre><code class="language-swift">// Correct
|
||
func move(from start: Point, to end: Point) {}
|
||
// Incorrect (likely too expressive, but arguable)
|
||
func moveBetweenPoints(from start: Point, to end: Point) {}
|
||
// Incorrect (not expressive enough and lacking argument clarity)
|
||
func move(x: Point, y: Point) {}
|
||
</code></pre>
|
||
<h2 id="closures"><a class="header" href="#closures">Closures</a></h2>
|
||
<p>Closures in Swift are similar to blocks in Objective-C and are essentially chunks of code, typically organized within a <code>{}</code> clause, that are passed between functions or to execute code as a callback within a function. Swift’s <code>func</code> functions are actually just a special case of a closure in use.</p>
|
||
<h4 id="syntax"><a class="header" href="#syntax">Syntax</a></h4>
|
||
<pre><code class="language-swift">{ (params) -> returnType in
|
||
statements
|
||
}
|
||
</code></pre>
|
||
<h4 id="examples"><a class="header" href="#examples">Examples</a></h4>
|
||
<pre><code class="language-swift">// Map just iterates over the array and performs whatever is in the closure on each item
|
||
let people = ["Rob", "Jimbob", "Cletus"]
|
||
people.map({
|
||
(person: String) -> String in
|
||
"Oh hai, \(person)..."
|
||
})
|
||
// Oh hai, Rob
|
||
// Oh hai, Jimbob
|
||
// Oh hai, Cletus
|
||
// Closure for alphabetically reversing an array of names, where sorted is a Swift library function
|
||
let names = ["Francesca", "Joe", "Bill", "Sally", ]
|
||
var reversed = names.sorted { (s1: String, s2: String) -> Bool in
|
||
return s1 > s2
|
||
}
|
||
// Or on a single line:
|
||
reversed = names.sorted{ (s1: String, s2: String) -> Bool in return s1 > s2 }
|
||
// Or because Swift can infer the Bool type:
|
||
reversed = names.sorted { s1, s2 in return s1 > s2 }
|
||
// Or because the return statement is implied:
|
||
reversed = names.sorted { s1, s2 in s1 > s2 }
|
||
// Or even shorter using shorthand argument names, such as $0, $1, $2, etc.:
|
||
reversed = names.sorted { $0 > $1 }
|
||
// Or just ridiculously short because Swift's String greater-than operator implementation exactly matches this function definition:
|
||
reversed = names.sorted(by: >)
|
||
</code></pre>
|
||
<p>If the closure is the last parameter to the function, you can also use the trailing closure pattern. This is especially useful when the closure code is especially long and you’d like some extra space to organize it:</p>
|
||
<pre><code class="language-swift">func someFunctionThatTakesAClosure(closure: () -> ()) {
|
||
// function body goes here
|
||
}
|
||
// Instead of calling like this:
|
||
someFunctionThatTakesAClosure({
|
||
// closure's body goes here
|
||
})
|
||
// You can use trailing closure like this:
|
||
someFunctionThatTakesAClosure() {
|
||
// trailing closure's body goes here
|
||
}
|
||
</code></pre>
|
||
<h4 id="capturing-values"><a class="header" href="#capturing-values">Capturing Values</a></h4>
|
||
<p>A closure can capture constants and variables from the surrounding context in which it is defined. The closure can then refer to and modify the values of those constants and variables from within its body, even if the original scope that defined the constants and variables no longer exists.
|
||
In Swift, the simplest form of a closure that can capture values is a nested function, written within the body of another function. A nested function can capture any of its outer function’s arguments and can also capture any constants and variables defined within the outer function.</p>
|
||
<pre><code class="language-swift">func makeIncrementor(forIncrement amount: Int) -> () -> Int {
|
||
var runningTotal = 0
|
||
func incrementor() -> Int {
|
||
runningTotal += amount
|
||
return runningTotal
|
||
}
|
||
return incrementor
|
||
}
|
||
</code></pre>
|
||
<p>Swift determines what should be captured by reference and what should be copied by value. You don’t need to annotate a variable to say that they can be used within the nested function. Swift also handles all memory management involved in disposing of variables when they are no longer needed by the function.</p>
|
||
<h4 id="capturing-self"><a class="header" href="#capturing-self">Capturing Self</a></h4>
|
||
<p>If you create a closure that references <code>self.*</code> it will capture <code>self</code> and retain a strong reference to it. This is sometimes the intended behavior, but often could lead to retain cycles where both objects won’t get deallocated at the end of their lifecycles.
|
||
The two best options are to use <code>unowned</code> or <code>weak</code>. This might look a bit messy, but saves a lot of headache.
|
||
Use <code>unowned</code> when you know the closure will only be called if <code>self</code> still exists, but you don’t want to create a strong (retain) reference.
|
||
Use <code>weak</code> if there is a chance that <code>self</code> will not exist, or if the closure is not dependent upon <code>self</code> and will run without it. If you do use <code>weak</code> also remember that <code>self</code> will be an optional variable and should be checked for existence.</p>
|
||
<pre><code class="language-swift">typealias SomeClosureType = (_ value: String) -> ()
|
||
class SomeClass {
|
||
fileprivate var currentValue = ""
|
||
init() {
|
||
someMethod { (value) in // Retained self
|
||
self.currentValue = value
|
||
}
|
||
someMethod { [unowned self] (value) in // Not retained, but expected to exist
|
||
self.currentValue = value
|
||
}
|
||
someMethod { [weak self] value in // Not retained, not expected to exist
|
||
// Or, alternatively you could do
|
||
guard let sSelf = self else { return }
|
||
// Or, alternatively use `self?` without the guard
|
||
sSelf.currentValue = value
|
||
}
|
||
}
|
||
func someMethod(closure: SomeClosureType) {
|
||
closure("Hai")
|
||
}
|
||
}
|
||
</code></pre>
|
||
<p>Reference: <a href="https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html">Apple: Automatic Reference Counting</a></p>
|
||
<h2 id="control-statements"><a class="header" href="#control-statements">Control Statements</a></h2>
|
||
<p>Swift uses all of the same control statements that other languages have:</p>
|
||
<h4 id="if-else-if-else"><a class="header" href="#if-else-if-else">If-Else If-Else</a></h4>
|
||
<pre><code class="language-swift">if someTestCondition {
|
||
// Code to execute if the condition is true
|
||
} else if someOtherTestCondition {
|
||
// Code to execute if the other test condition is true
|
||
} else {
|
||
// Code to execute if the prior conditions are false
|
||
}
|
||
</code></pre>
|
||
<p>As you can see, parentheses are optional.</p>
|
||
<h4 id="ternary-operators"><a class="header" href="#ternary-operators">Ternary Operators</a></h4>
|
||
<p>The shorthand notation for an <code>if-else</code> statement is a ternary operator of the form: <code>someTestCondition ? doIfTrue : doIfFalse</code>
|
||
Example:</p>
|
||
<pre><code class="language-swift">func stringForTrueOrFalse(trueOrFalse: Bool) -> String {
|
||
return trueOrFalse ? "True" : "False"
|
||
}
|
||
</code></pre>
|
||
<h4 id="nil-coalescing-operators"><a class="header" href="#nil-coalescing-operators">Nil Coalescing Operators</a></h4>
|
||
<p>In Swift, we need to consider the use of <code>optional</code> values. One very basic way to handle <code>nil</code> cases is with an <code>if-else</code> statement:</p>
|
||
<pre><code class="language-swift">func stringForOptionalExistence(optionalValue: String?) -> String {
|
||
if optionalValue != nil {
|
||
return optionalValue
|
||
} else {
|
||
return "Empty"
|
||
}
|
||
}
|
||
</code></pre>
|
||
<p>In this particular case, we are returning <code>optionalValue</code> if it is not <code>nil</code>, and <code>"Empty"</code> if <code>optionalValue</code> is <code>nil</code>. The shorthand notation for this type of <code>if(!=nil)-else</code> statement is a nil coalescing operator of the form: <code>optionalValue ?? nonOptionalValue</code>
|
||
Example:</p>
|
||
<pre><code class="language-swift">func stringForOptionalExistence(optionalValue: String?) -> String {
|
||
return optionalValue ?? "Empty"
|
||
}
|
||
</code></pre>
|
||
<h4 id="for-loops"><a class="header" href="#for-loops">For Loops</a></h4>
|
||
<p>Swift enables you to use ranges inside of <code>for</code> loops now:</p>
|
||
<pre><code class="language-swift">for index in 1...5 {
|
||
print("\(index) times 5 is \(index * 5)")
|
||
}
|
||
// Or if you don't need the value of the index
|
||
let base = 3, power = 10
|
||
var answer = 1
|
||
for _ in 1...power {
|
||
answer *= base
|
||
}
|
||
print("\(base) to the power of \(power) is \(answer)")
|
||
// prints "3 to the power of 10 is 59049"
|
||
</code></pre>
|
||
<h4 id="enumerating-arrays--dictionaries"><a class="header" href="#enumerating-arrays--dictionaries">Enumerating arrays & dictionaries</a></h4>
|
||
<pre><code class="language-swift">// We explicitly cast to the Movie class from AnyObject class
|
||
for movie in someObjects as [Movie] {
|
||
// Code to execute each time
|
||
}
|
||
// Enumerating simple array
|
||
let names = ["Anna", "Alex", "Brian", "Jack"]
|
||
for name in names {
|
||
print("Hello, \(name)!")
|
||
}
|
||
// Enumerating simple dictionary
|
||
let numberOfLegs = ["spider": 8, "ant": 6, "cat": 4]
|
||
for (animalName, legCount) in numberOfLegs {
|
||
print("\(animalName)s have \(legCount) legs")
|
||
}
|
||
</code></pre>
|
||
<p>If you need to cast to a certain object type, see the earlier discussion about the <code>as!</code> and <code>as?</code> keywords.</p>
|
||
<h4 id="while-loop"><a class="header" href="#while-loop">While Loop</a></h4>
|
||
<pre><code class="language-swift">while someTestCondition {
|
||
// Code to execute while the condition is true
|
||
}
|
||
</code></pre>
|
||
<h4 id="repeat-while-loop"><a class="header" href="#repeat-while-loop">Repeat While Loop</a></h4>
|
||
<pre><code class="language-swift">repeat {
|
||
// Code to execute while the condition is true
|
||
} while someTestCondition
|
||
</code></pre>
|
||
<h4 id="switch"><a class="header" href="#switch">Switch</a></h4>
|
||
<p>Switch statements are often used in place of <code>if</code> statements if there is a need to test if a certain variable matches the value of another constant or variable. For example, you may want to test if an error code integer you received matches an existing constant value or if it’s a new error code.</p>
|
||
<pre><code class="language-swift">switch errorStatusCode {
|
||
case .network:
|
||
// Code to execute if it matches
|
||
case .wifi:
|
||
// Code to execute if it matches
|
||
default:
|
||
// Code to execute if nothing else matched
|
||
}
|
||
</code></pre>
|
||
<p>Switch statements in Swift do not fall through the bottom of each case and into the next one by default. Instead, the entire switch statement finishes its execution as soon as the first matching switch case is completed, without requiring an explicit <code>break</code> statement. This makes the switch statement safer and easier to use than in C, and avoids executing more than one switch case by mistake.</p>
|
||
<h4 id="exiting-loops"><a class="header" href="#exiting-loops">Exiting Loops</a></h4>
|
||
<p>Although <code>break</code> is not required in Swift, you can still use a <code>break</code> statement to match and ignore a particular case, or to break out of a matched case before that case has completed its execution.</p>
|
||
<ul>
|
||
<li><code>return</code> : Stops execution and returns to the calling function. It can also be used to return a value from a function.</li>
|
||
<li><code>break</code> : Used to stop execution of a loop.</li>
|
||
</ul>
|
||
<h2 id="user-defaults"><a class="header" href="#user-defaults">User Defaults</a></h2>
|
||
<p>User defaults are basically a way of storing simple preference values which can be saved and restored across app launches. It is not meant to be used as a data storage layer, like Core Data or sqlite.</p>
|
||
<h3 id="storing-values"><a class="header" href="#storing-values">Storing Values</a></h3>
|
||
<pre><code class="language-swift">let userDefaults = UserDefaults.standard
|
||
userDefaults.setValue("Some Value", forKey: "RPSomeUserPreference")
|
||
</code></pre>
|
||
<h3 id="retrieving-values"><a class="header" href="#retrieving-values">Retrieving Values</a></h3>
|
||
<pre><code class="language-swift">let userDefaults = UserDefaults.standard
|
||
let someValue = userDefaults.value(forKey: "RPSomeUserPreference") as AnyObject?
|
||
</code></pre>
|
||
<p>There are also other convenience functions on <code>UserDefaults</code> instances such as <code>bool(forKey:...)</code>, <code>string(forKey:...)</code>, etc.</p>
|
||
<h2 id="common-patterns"><a class="header" href="#common-patterns">Common Patterns</a></h2>
|
||
<p>For a comprehensive list of design patterns, as established by the Gang of Four, look here: <a href="https://github.com/ochococo/Design-Patterns-In-Swift">Design Patterns in Swift</a></p>
|
||
<h3 id="singletons"><a class="header" href="#singletons">Singletons</a></h3>
|
||
<p>Singleton’s are a special kind of class where only one instance of the class exists for the current process. They are a convenient way to share data between different parts of an app without creating global variables or having to pass the data around manually, but they should be used sparingly since they often create tighter coupling between classes.
|
||
To turn a class into a singleton, you use the following implementation where the function name is prefixed with <code>shared</code> plus another word which best describes your class. For example, if the class is a network or location manager, you would name the function <code>sharedManager</code> instead of <code>sharedInstance</code>.</p>
|
||
<pre><code class="language-swift">class MyClass {
|
||
// MARK: - Instantiation
|
||
// Naming convention:
|
||
// sharedInstance, sharedManager, sharedController, etc.
|
||
// depending on the class type
|
||
static let sharedInstance = MyClass()
|
||
// This prevents others from using the default '()' initializer for this class.
|
||
fileprivate init() {}
|
||
var isReady = true
|
||
// More class code here
|
||
}
|
||
</code></pre>
|
||
<p><strong>Explanation</strong>: The static constant <code>sharedInstance</code> is run as <code>dispatch_once</code> the first time that variable is accessed to make sure the initialization is atomic. This ensures it is thread safe, fast, lazy, and also bridged to ObjC for free. More from <a href="http://krakendev.io/blog/the-right-way-to-write-a-singleton">here</a>.
|
||
<strong>Usage</strong>: You would get a reference to that singleton class in another class with the following code:</p>
|
||
<pre><code class="language-swift">// Now you could do
|
||
let myClass = MyClass.sharedInstance
|
||
let answer = myClass.isReady ? "Yep!" : "Nope!"
|
||
print("Are you ready to rock and roll? \(answer)")
|
||
</code></pre>
|
||
<h2 id="unicode-support"><a class="header" href="#unicode-support">Unicode Support</a></h2>
|
||
<p>Although I don’t recommend this, Swift will compile even if you use emoji’s in your code since it offers Unicode support.
|
||
More info from Apple <a href="https://developer.apple.com/library/ios/documentation/swift/conceptual/Swift_Programming_Language/StringsAndCharacters.html">here</a></p>
|
||
|
||
</main>
|
||
|
||
<nav class="nav-wrapper" aria-label="Page navigation">
|
||
<!-- Mobile navigation buttons -->
|
||
<a rel="prev" href="../../posts/swift/task_planner.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||
<i class="fa fa-angle-left"></i>
|
||
</a>
|
||
|
||
<a rel="next prefetch" href="../../posts/swift/yinci_url.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||
<i class="fa fa-angle-right"></i>
|
||
</a>
|
||
|
||
<div style="clear: both"></div>
|
||
</nav>
|
||
</div>
|
||
</div>
|
||
|
||
<nav class="nav-wide-wrapper" aria-label="Page navigation">
|
||
<a rel="prev" href="../../posts/swift/task_planner.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||
<i class="fa fa-angle-left"></i>
|
||
</a>
|
||
|
||
<a rel="next prefetch" href="../../posts/swift/yinci_url.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||
<i class="fa fa-angle-right"></i>
|
||
</a>
|
||
</nav>
|
||
|
||
</div>
|
||
|
||
|
||
|
||
<script>
|
||
window.playground_line_numbers = true;
|
||
</script>
|
||
|
||
<script>
|
||
window.playground_copyable = true;
|
||
</script>
|
||
|
||
<script src="../../ace.js"></script>
|
||
<script src="../../editor.js"></script>
|
||
<script src="../../mode-rust.js"></script>
|
||
<script src="../../theme-dawn.js"></script>
|
||
<script src="../../theme-tomorrow_night.js"></script>
|
||
|
||
<script src="../../elasticlunr.min.js"></script>
|
||
<script src="../../mark.min.js"></script>
|
||
<script src="../../searcher.js"></script>
|
||
|
||
<script src="../../clipboard.min.js"></script>
|
||
<script src="../../highlight.js"></script>
|
||
<script src="../../book.js"></script>
|
||
|
||
<!-- Custom JS scripts -->
|
||
<script src="../../src/js/custom.js"></script>
|
||
|
||
|
||
</div>
|
||
</body>
|
||
</html>
|