#didReceiveMemoryWarning
Explore tagged Tumblr posts
Video
youtube
Swift: Loading Images Asynchronously and storing with NSCache and NSURLCache
my review point is 9/10
https://youtu.be/BIgqHLTZ_a4?t=1m55s getting image from url ( NSURLSession.sharedSession().dataTaskWithURL )
https://youtu.be/BIgqHLTZ_a4?t=7m18s 개발자가 만들어 사용하는 image caching example
https://youtu.be/BIgqHLTZ_a4?t=10m45s memory low warning hook ( didReceiveMemoryWarning )
https://youtu.be/BIgqHLTZ_a4?t=11m30s apple에서 제공하는 NSCache를 이용한 caching 작업
https://youtu.be/BIgqHLTZ_a4?t=13m45s url작업은 기본 cache 기능이 있는데 이 기준치를 변경하는 방법 ( NSURLCache )
#ios#brian#facebook feed#facebook#NSCache#NSURLCache#image#dataTaskWithURL#NSURLSession#sharedSession#cache#memory#low memory#didReceiveMemoryWarning
0 notes
Link
ブログトップ Salesforce MobileSDKのセッション管理について考えてみた はじめに みなさ��、こんにちは。 走れるシステムエンジニア、溝口です。 Apple Watchが予約開始となりましたが、みなさん予約はされましたか!? 僕は即予約、アンド定時ダッシュで試着をして、Apple Watcherとしての想像と夢を膨らませておりました。 もちろん、冶金専門家が標準的な金よりも最大2倍硬くなるように開発した18Kで仕立てられた200万円超えのApple Watch Editionは華麗にスルーし、完全予定調和のSportsモデルを予約しました。 届くのが楽しみですね! Hybridアプリのセッション管理 それでは本題に参りましょう! 今回は先日執筆した「 WKWebViewとSalesforceでHybridアプリ開発」の補足的な内容となります。 前回の記事を見て気付いた方も居らっしゃると思いますが、WebViewでVisualforceのページを表示した際に、セッションの管理をどうするか、という点が考慮されていませんでした。 では、具体的に前回の記事の実装だとどうなるか見て行きましょう。 ここまでは前回と同じですね、普通にWebViewにVisualforceで実装した詳細画面が表示されています。 このままホームボタンを押して、セッション有効期間が切れるまで放置してみましょう。 ------------数時間後------------- さて、セッションが切れる時間となりました。 それでは、再度サンプルアプリを開いて見ましょう。 oh...、これはイケてないですね。 この様に、「セッションが切れた時にどうするか」という観点での実装が足りていなかった為、この様な現象が起きてしまいました。 Salesforceとの通信前にセッションのチェック 意図せずログイン画面が表示されてしまうのは、WebViewでVisualforceの画面を開いたままにした場合、「sid=」で付与しているセッションID(アクセストークン)の有効期間が切れてしまったまま、再度リクエストを投げてしまうことが原因でした。 「じゃあ、Salesforceとの通信の前に認証を行い、セッションのチェックをしよう!」ということで、前回のコードを以下の様に修正しました。 import UIKit import WebKit class DetailViewController: BaseViewController, WKNavigationDelegate, SFOAuthCoordinatorDelegate { var accountItem: AccountModel? var accountWebView: WKWebView? init(nibName: String, accountItem: AccountModel) { super.init(nibName: nibName, bundle: nil) self.accountItem = accountItem } required init(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } override func viewDidLoad() { super.viewDidLoad() SFRestAPI.sharedInstance().coordinator.delegate = self; setupDesign() setupWebView() } override func viewWillAppear(animated: Bool) { SVProgressHUD.showWithStatus("認証中") SFRestAPI.sharedInstance().coordinator.authenticate() } override func viewDidDisappear(animated: Bool) { SVProgressHUD.dismiss() } func setupDesign() { let refreshButton: UIBarButtonItem = UIBarButtonItem(barButtonSystemItem: .Refresh, target: self, action: "tapRefleshButton") self.navigationItem.rightBarButtonItem = refreshButton } func setupWebView() { accountWebView = WKWebView() self.view = accountWebView! accountWebView!.navigationDelegate = self } func createAccountRequest() NSURLRequest { let instanceUrl: String = SFRestAPI.sharedInstance().coordinator.credentials.instanceUrl.description let accessToken: String = SFRestAPI.sharedInstance().coordinator.credentials.accessToken let authUrl: String = instanceUrl + "/secur/frontdoor.jsp?sid=" + accessToken + "&retURL=" let accountUrl: String = instanceUrl + "/apex/AccountMobile?id=" + accountItem!.salesforceId! let request: NSURL = NSURL(string:authUrl + accountUrl)! let urlRequest: NSURLRequest = NSURLRequest(URL: request) return urlRequest } func webView(webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) { SVProgressHUD.showWithStatus("読み込み中") } func webView(webView: WKWebView, didFinishNavigation navigation: WKNavigation!) { SVProgressHUD.dismiss() self.title = accountWebView!.title } func webView(webView: WKWebView, didFailNavigation navigation: WKNavigation!, withError error: NSError) { SVProgressHUD.dismiss() } func webView(webView: WKWebView, decidePolicyForNavigationAction navigationAction: WKNavigationAction, decisionHandler: (WKNavigationActionPolicy) Void) { if (navigationAction.request.URL!.absoluteString!.hasPrefix("completed://")) { self.navigationController!.popViewControllerAnimated(true) } decisionHandler(WKNavigationActionPolicy.Allow) } func tapRefleshButton() { accountWebView!.reload() } func oauthCoordinatorDidAuthenticate(coordinator: SFOAuthCoordinator!, authInfo info: SFOAuthInfo!) { SVProgressHUD.dismiss() accountWebView!.loadRequest(createAccountRequest()) } func oauthCoordinator(coordinator: SFOAuthCoordinator!, didBeginAuthenticationWithView view: UIWebView!) {} } どこが変わったのか1つずつ見て行きましょう。 override func viewDidLoad() { super.viewDidLoad() SFRestAPI.sharedInstance().coordinator.delegate = self; setupDesign() setupWebView() } まず、ViewDidLoadでSFOAuthCoordinatorのDelegateを自身のクラスへ実装することを宣言します。 こうすることで、認証処理を行った後の処理を自身のクラス内で受け取れる様になります。 override func viewWillAppear(animated: Bool) { SVProgressHUD.showWithStatus("認証中") SFRestAPI.sharedInstance().coordinator.authenticate() } そしてViewWillAppearにて認証処理を実行するメソッドを呼び出します。 後は非同期で認証処理が走り、セッションID(アクセストークン)が切れていた場合、リフレッシュトークンにてセッションの書き換えが実行されます。 func oauthCoordinatorDidAuthenticate(coordinator: SFOAuthCoordinator!, authInfo info: SFOAuthInfo!) { SVProgressHUD.dismiss() accountWebView!.loadRequest(createAccountRequest()) } 最後に、認証が完了した際にこのメソッドが呼ばれます。 今回はこのDelegateメソッド内にSalesforceへリクエストを投げるメソッドを実装している為、必ず 認証(セッションの確認) → Salesforceへ通信 という経路を辿ることが出来ます。 最後に 如何だったでしょうか? 今回はちょっとしたTips的な内容となってしまいましたが、WebViewを使う上でセッションの管理をどう実装するのか、という部分は、モバイル開発を行う上でも重要なポイントと言えると思います。 今後はLightningなども出てきてモバイルの市場も更に活性化しそうですし、色々な点を考慮しながら楽しく開発していきたいですね!
0 notes
Text
Getting Started with Core Data Tutorial
This is an abridged chapter from our book Core Data by Tutorials, which has been completely updated for Swift 4 and iOS 11. This tutorial is presented as part of our iOS 11 Launch Party — enjoy!
Welcome to Core Data! In this tutorial, you’ll write your very first Core Data app. You’ll see how easy it is to get started with all the resources provided in Xcode, from starter code templates to the Data Model editor.
You’re going to hit the ground running right from the start. By the end of the tutorial you’ll know how to:
Model data using Xcode’s model editor
Add new records to Core Data
Fetch a set of records from Core Data
Display the fetched records using a table view.
You’ll also get a sense of what Core Data is doing behind the scenes, and how you can interact with the various moving pieces.
Getting Started
Open Xcode and create a new iOS project based on the Single View App template. Name the app HitList and make sure Use Core Data is checked.
Checking the Use Core Data box will cause Xcode to generate boilerplate code for what’s known as an NSPersistentContainer in AppDelegate.swift.
The NSPersistentContainer consists of a set of objects that facilitate saving and retrieving information from Core Data. Inside this container is an object to manage the Core Data state as a whole, an object representing the Data Model, and so on.
The standard stack works well for most apps, but depending on your your app and its data requirements, you can customize the stack to be more efficient.
Note: Not all Xcode templates under iOS/Application have the option to start with Core Data. In Xcode 9, only the Master-Detail App and Single View App templates have the Use Core Data checkbox.
The idea for this sample app is simple: There will be a table view with a list of names for your very own “hit list”. You’ll be able to add names to this list and eventually, you’ll use Core Data to make sure the data is stored between sessions. We don’t condone violence in the book, so you can think of this app as a favorites list to keep track of your friends too, of course!
Click on Main.storyboard to open it in Interface Builder. Select the view controller on the canvas and embed it inside a navigation controller. From Xcode’s Editor menu, select Embed In…\ Navigation Controller.
Click on the navigation controller’s navigation bar to select it, then click on Prefers Large Titles in the Attributes Inspector. This will give the sample app a fresh iOS 11 style.
Next, drag a Table View from the object library into the view controller, then resize it so it covers the entire view.
If not already open, use the icon located in the lower left corner of your canvas to open Interface Builder’s document outline.
Ctrl-drag from the Table View in the document outline to its parent view and select the Leading Space to Safe Area constraint:
Do this three more times, selecting the constraints Trailing Space to Safe Area, Top Space to Safe Area and finally, Bottom Space to Safe Area. Adding those four constraints makes the table view fill its parent view.
Next, drag a Bar Button Item and place it on the view controller’s navigation bar. Finally, select the bar button item and change its system item to Add. Your canvas should look similar to the following screenshot:
Every time you tap the Add button, an alert controller containing a text field will appear. From there you’ll be able to type someone’s name into the text field. Tapping Save will save the name, dismiss the alert controller and refresh the table view, displaying all the names you’ve entered.
But first, you need to make the view controller the table view’s data source. In the canvas, Ctrl-drag from the table view to the yellow view controller icon above the navigation bar, as shown below, and click on dataSource:
In case you’re wondering, you don’t need to set up the table view’s delegate since tapping on the cells won’t trigger any action. It doesn’t get simpler than this!
Open the assistant editor by pressing Command-Option-Enter or by selecting the middle button on the Editor toolset on the Xcode bar. Delete the didReceiveMemoryWarning() method. Next, Ctrl-drag from the table view onto ViewController.swift, inside the class definition to create an IBOutlet.
Next, name the new IBOutlet property tableView, resulting in the following line:
@IBOutlet weak var tableView: UITableView!
Next, Ctrl-drag from the Add button into ViewController.swift just below your viewDidLoad() definition. This time, create an action instead of an outlet, naming the method addName, with a type UIBarButtonItem:
@IBAction func addName(_ sender: UIBarButtonItem) { }
You can now refer to the table view and the bar button item’s action in code.
Next, you’ll set up the model for the table view. Add the following property to ViewController.swift below the tableView IBOutlet:
var names: [String] = []
names is a mutable array holding string values displayed by the table view. Next, replace the implementation of viewDidLoad() with the following:
override func viewDidLoad() { super.viewDidLoad() title = "The List" tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell") }
This will set a title on the navigation bar and register the UITableViewCell class with the table view.
Note: register(_:forCellReuseIdentifier:) guarantees your table view will return a cell of the correct type when the Cell reuseIdentifier is provided to the dequeue method.
Next, still in ViewController.swift, add the following UITableViewDataSource extension below your class definition for ViewController:
// MARK: - UITableViewDataSource extension ViewController: UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return names.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) cell.textLabel?.text = names[indexPath.row] return cell } }
If you’ve ever worked with UITableView, this code should look very familiar. First you return the number of rows in the table as the number of items in your names array.
Next, tableView(_:cellForRowAt:) dequeues table view cells and populates them with the corresponding string from the names array.
Next, you need a way to add new names so the table view can display them. Implement the addName IBAction method you Ctrl-dragged into your code earlier:
// Implement the addName IBAction @IBAction func addName(_ sender: UIBarButtonItem) { let alert = UIAlertController(title: "New Name", message: "Add a new name", preferredStyle: .alert) let saveAction = UIAlertAction(title: "Save", style: .default) { [unowned self] action in guard let textField = alert.textFields?.first, let nameToSave = textField.text else { return } self.names.append(nameToSave) self.tableView.reloadData() } let cancelAction = UIAlertAction(title: "Cancel", style: .default) alert.addTextField() alert.addAction(saveAction) alert.addAction(cancelAction) present(alert, animated: true) }
Every time you tap the Add button, this method presents a UIAlertController with a text field and two buttons, Save and Cancel.
Save inserts the text fields current text into the names array then reloads the table view. Since the names array is the model backing the table view, whatever you type into the text field will appear in the table view.
Finally, build and run your app for the first time. Next, tap the Add button. The alert controller will look like this:
Add four or five names to the list. You should see something similar to below:
Your table view will display the data and your array will store the names, but the big thing missing here is persistence. The array is in memory but if you force quit the app or reboot your device, your hit list will be wiped out.
Core Data provides persistence, meaning it can store data in a more durable state so it can outlive an app re-launch or a device reboot.
You haven’t added any Core Data yet, so nothing should persist after you navigate away from the app. Let’s test this out. Press the Home button if you’re using a physical device or the equivalent (Shift+⌘+H) if you’re using the Simulator. This will take you back to the familiar app grid on the home screen:
From the home screen, tap the HitList icon to bring the app back to the foreground. The names are still on the screen. What happened?
When you tap the Home button, the app currently in the foreground goes to the background. When this happens, the operating system flash-freezes everything currently in memory, including the strings in the names array. Similarly, when it’s time to wake up and return to the foreground, the operating system restores what used to be in memory as if you’d never left.
Apple introduced these advances in multitasking back in iOS 4. They create a seamless experience for iOS users but add a wrinkle to the definition of persistence for iOS developers. Are the names really persisted?
No, not really. If you had completely killed the app in the fast app switcher or turned off your phone, those names would be gone. You can verify this, as well. With the app in the foreground, double tap the Home button to enter the fast app switcher, like so:
From here, flick the HitList app snapshot upwards to terminate the app. There should be no trace of HitList in living memory (no pun intended). Verify the names are gone by returning to the home screen and tapping on the HitList icon to trigger a fresh launch.
The difference between flash-freezing and persistence may be obvious if you’ve worked with iOS for some time and are familiar with the way multitasking works. In a user’s mind, however, there is no difference. The user doesn’t care why the names are still there, whether the app went into the background and came back, or because the app saved and reloaded them.
All that matters is the names are still there when the app comes back!
So the real test of persistence, is whether your data is still there after a fresh app launch.
Modeling your Data
Now that you know how to check for persistence, you can dive into Core Data. Your goal for the HitList app is simple: persist the names you enter so they’re available for viewing after a fresh app launch.
Up to this point, you’ve been using plain old Swift strings to store the names in memory. In this section, you’ll replace these strings with Core Data objects.
The first step is to create a managed object model, which describes the way Core Data represents data on disk.
By default, Core Data uses a SQLite database as the persistent store, so you can think of the Data Model as the database schema.
Note: You’ll come across the word managed quite a bit in the book. If you see “managed” in the name of a class, such as in NSManagedObjectContext, chances are you are dealing with a Core Data class. “Managed” refers to Core Data’s management of the life cycle of Core Data objects.
However, don’t assume all Core Data classes contain the word “managed”. Actually, most don’t. For a comprehensive list of Core Data classes, check out the Core Data framework reference in the documentation browser.
Since you’ve elected to use Core Data, Xcode automatically created a Data Model file for you and named it HitList.xcdatamodeld.
Open HitList.xcdatamodeld. As you can see, Xcode has a powerful Data Model editor:
The Data Model editor has a lot of features, but for now, let’s focus on creating a single Core Data entity.
Click on Add Entity on the lower-left to create a new entity. Double-click the new entity and change its name to Person, like so:
You may be wondering why the model editor uses the term Entity. Weren’t you simply defining a new class? As you’ll see shortly, Core Data comes with its own vocabulary. Here’s a quick rundown of some terms you’ll commonly encounter:
An entity is a class definition in Core Data. The classic example is an Employee or a Company. In a relational database, an entity corresponds to a table.
An attribute is a piece of information attached to a particular entity. For example, an Employee entity could have attributes for the employee’s name, position and salary. In a database, an attribute corresponds to a particular field in a table.
A relationship is a link between multiple entities. In Core Data, relationships between two entities are called to-one relationships, while those between one and many entities are called to-many relationships. For example, a Manager can have a to-many relationship with a set of employees, whereas an individual Employee will usually have a to-one relationship with his manager.
Note: You’ve probably noticed that entities sound a lot like classes. Likewise, attributes and relationships sound a lot like properties. What’s the difference? You can think of a Core Data entity as a class definition and the managed object as an instance of that class.
Now that you know what an attribute is, you can add an attribute to Person object created earlier. Open HitList.xcdatamodeld. Next, select Person on the left-hand side and click the plus sign (+) under Attributes.
Set the new attribute’s name to, er, name and change its type to String:
Saving to Core Data
Open ViewController.swift, add the following Core Data module import below the UIKit import:
import CoreData
This import is all you need to start using the Core Data API in your code.
Next, replace the names property definition with the following:
var people: [NSManagedObject] = []
You’ll store Person entities rather than string names, so you rename the array serving as the table view’s data model to people. It now holds instances of NSManagedObject rather than simple strings.
NSManagedObject represents a single object stored in Core Data; you must use it to create, edit, save and delete from your Core Data persistent store. As you’ll see shortly, NSManagedObject is a shape-shifter. It can take the form of any entity in your Data Model, appropriating whatever attributes and relationships you defined.
Since you’re changing the table view’s model, you must also replace both data source methods implemented earlier. Replace your UITableViewDataSource extension with the following:
// MARK: - UITableViewDataSource extension ViewController: UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return people.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let person = people[indexPath.row] let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) cell.textLabel?.text = person.value(forKeyPath: "name") as? String return cell } }
The most significant change to these methods occurs in tableView(_:cellForRowAt:). Instead of matching cells with the corresponding string in the model array, you now match cells with the corresponding NSManagedObject.
Note how you grab the name attribute from the NSManagedObject. It happens here:
cell.textLabel?.text = person.value(forKeyPath: "name") as? String
Why do you have to do this? As it turns out, NSManagedObject doesn’t know about the name attribute you defined in your Data Model, so there’s no way of accessing it directly with a property. The only way Core Data provides to read the value is key-value coding, commonly referred to as KVC.
Note: KVC is a mechanism in Foundation for accessing an object’s properties indirectly using strings. In this case, KVC makes NSMangedObject behave more or less like a dictionary at runtime.
Key-value coding is available to all classes inheriting from NSObject, including NSManagedObject. You can’t access properties using KVC on a Swift object that doesn’t descend from NSObject.
Next, find addName(_:) and replace the save UIAlertAction with the following:
let saveAction = UIAlertAction(title: "Save", style: .default) { [unowned self] action in guard let textField = alert.textFields?.first, let nameToSave = textField.text else { return } self.save(name: nameToSave) self.tableView.reloadData() }
This takes the text in the text field and passes it over to a new method named save(name:). Xcode complains because save(name:) doesn’t exist yet. Add it below addName(_:):
func save(name: String) { guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return } // 1 let managedContext = appDelegate.persistentContainer.viewContext // 2 let entity = NSEntityDescription.entity(forEntityName: "Person", in: managedContext)! let person = NSManagedObject(entity: entity, insertInto: managedContext) // 3 person.setValue(name, forKeyPath: "name") // 4 do { try managedContext.save() people.append(person) } catch let error as NSError { print("Could not save. \(error), \(error.userInfo)") } }
This is where Core Data kicks in! Here’s what the code does:
Before you can save or retrieve anything from your Core Data store, you first need to get your hands on an NSManagedObjectContext. You can consider a managed object context as an in-memory “scratchpad” for working with managed objects.
Think of saving a new managed object to Core Data as a two-step process: first, you insert a new managed object into a managed object context; then, after you’re happy with your shiny new managed object, you “commit” the changes in your managed object context to save it to disk.
Xcode has already generated a managed object context as part of the new project’s template. Remember, this only happens if you check the Use Core Data checkbox at the beginning. This default managed object context lives as a property of the NSPersistentContainer in the application delegate. To access it, you first get a reference to the app delegate.
You create a new managed object and insert it into the managed object context. You can do this in one step with NSManagedObject’s static method: entity(forEntityName:in:).
You may be wondering what an NSEntityDescription is all about. Recall earlier, NSManagedObject was called a shape-shifter class because it can represent any entity. An entity description is the piece linking the entity definition from your Data Model with an instance of NSManagedObject at runtime.
With an NSManagedObject in hand, you set the name attribute using key-value coding. You must spell the KVC key (name in this case) exactly as it appears in your Data Model, otherwise your app will crash at runtime.
You commit your changes to person and save to disk by calling save on the managed object context. Note save can throw an error, which is why you call it using the try keyword within a do-catch block. Finally, insert the new managed object into the people array so it shows up when the table view reloads.
That’s a little more complicated than an array of strings, but not too bad. Some of the code here, such as getting the managed object context and entity, could be done just once in your own init() or viewDidLoad() then reused later. For simplicity, you’re doing it all in the same method.
Build and run the app, and add a few names to the table view:
If the names are actually stored in Core Data, the HitList app should pass the persistence test. Double-tap the Home button to bring up the fast app switcher. Terminate the HitList app by flicking it upwards.
From Springboard, tap the HitList app to trigger a fresh launch. Wait, what happened? The table view is empty:
You saved to Core Data, but after a fresh app launch, the people array is empty! That’s because the data is sitting on disk waiting for you, but you’re not showing it yet.
Fetching from Core Data
To get data from your persistent store into the managed object context, you have to fetch it. Open ViewController.swift and add this code below viewDidLoad():
override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) //1 guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return } let managedContext = appDelegate.persistentContainer.viewContext //2 let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Person") //3 do { people = try managedContext.fetch(fetchRequest) } catch let error as NSError { print("Could not fetch. \(error), \(error.userInfo)") } }
Step by step, this is what the code does:
Before you can do anything with Core Data, you need a managed object context. Fetching is no different! Like before, you pull up the application delegate and grab a reference to its persistent container to get your hands on its NSManagedObjectContext.
As the name suggests, NSFetchRequest is the class responsible for fetching from Core Data. Fetch requests are both powerful and flexible. You can use fetch requests to fetch a set of objects meeting the provided criteria (i.e. give me all employees living in Wisconsin and have been with the company at least three years), individual values (i.e. give me the longest name in the database) and more.
Fetch requests have several qualifiers used to refine the set of results returned. You’ll learn more about these qualifiers in Chapter 4, “Intermediate Fetching”; for now, you should know NSEntityDescription is a required one of these qualifiers.
Setting a fetch request’s entity property, or alternatively initializing it with init(entityName:), fetches all objects of a particular entity. This is what you do here to fetch all Person entities. Also note NSFetchRequest is a generic type. This use of generics specifies a fetch request’s expected return type, in this case NSManagedObject.
You hand the fetch request over to the managed object context to do the heavy lifting. fetch(_:) returns an array of managed objects meeting the criteria specified by the fetch request.
Note: Like save(), fetch(_:) can also throw an error so you have to use it within a do block. If an error occurred during the fetch, you can inspect the error inside the catch block and respond appropriately.
Build and run the application. Immediately, you should see the list of names you added earlier:
Great! They’re back from the dead (pun intended). Add a few more names to the list and restart the app to verify saving and fetching are working. Short of deleting the app, resetting the Simulator or throwing your phone off a tall building, the names will appear in the table view no matter what.
Where to Go From Here?
You can download the completed project for this tutorial here.
In just a few pages, you’ve already experienced several fundamental Core Data concepts: Data Models, entities, attributes, managed objects, managed object contexts and fetch requests.
If you enjoyed what you learned in this tutorial, why not check out the complete Core Data by Tutorials book, available in our store?
Here’s a taste of what’s in the book:
1. Chapter 1, Your First Core Data App: You’ll click File\New Project and write a Core Data app from scratch! This chapter covers the basics of setting up your data model and then adding and fetching records.
2. Chapter 2, NSManagedObject Subclasses: NSManagedObject is the base data storage class of your Core Data object graphs. This chapter will teach you how you customize your own managed object subclasses to store and validate data.
3. Chapter 3, The Core Data Stack: Under the hood, Core Data is made up of many parts working together. In this chapter, you’ll learn about how these parts fit together, and move away from the starter Xcode template to build your own customizable system.
4. Chapter 4, Intermediate Fetching: Your apps will fetch data all the time, and Core Data offers many options for getting the data to you efficiently. This chapter covers more advanced fetch requests, predicates, sorting and asynchronous fetching.
5. Chapter 5, NSFetchedResultsController: Table views are at the core of many iOS apps, and Apple wants to make Core Data play nicely with them! In this chapter, you’ll learn how NSFetchedResultsController can save you time and code when your table views are backed by data from Core Data.
6. Chapter 6, Versioning and Migration: As you update and enhance your app, its data model will almost certainly need to change. In this chapter, you’ll learn how to create multiple versions of your data model and then migrate your users forward so they can keep their existing data as they upgrade.
7. Chapter 7, Unit Tests: Testing is an important part of the development process, and you shouldn’t leave Core Data out of that! In this chapter, you’ll learn how to set up a separate test environment for Core Data and see examples of how to test your models.
8. Chapter 8, Measuring and Boosting Performance: No one ever complained that an app was too fast, so it’s important to be vigilant about tracking performance. In this chapter, you’ll learn how to measure your app’s performance with various Xcode tools and then pick up some tips for dealing with slow spots in your code.
9. Chapter 9, Multiple Managed Object Contexts: In this final chapter, you’ll expand the usual Core Data stack to include multiple managed object contexts. You’ll learn how this can improve perceived performance and help make your app architecture less monolithic and more compartmentalized.
And to help sweeten the deal, the digital edition of the book is on sale for $49.99! But don’t wait — this sale price is only available for a limited time.
Speaking of sweet deals, be sure to check out the great prizes we’re giving away this year with the iOS 11 Launch Party, including over $9,000 in giveaways!
To enter, simply retweet this post using the #ios11launchparty hashtag by using the button below:
Tweet !function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');
We hope you enjoy this update, and stay tuned for more book releases and updates!
The post Getting Started with Core Data Tutorial appeared first on Ray Wenderlich.
Getting Started with Core Data Tutorial published first on http://ift.tt/2fA8nUr
0 notes
Link
In my App I have a lot of rtf files that I read and put the text into a UITextView with AttributedText.
Now I want to put all those files into a MySQL database and read them with a PHP file and URLSession.
import UIKit class ViewController: UIViewController, URLSessionDataDelegate { var returnString = "" var aOverskrifter:NSMutableArray = [] var aLilleTekster:NSMutableArray = [] var aLangTekster:NSMutableArray = [] var styledText = NSMutableAttributedString() @IBOutlet var txtWikiTekst: UITextView! //** Button to get data from php file @IBAction func btnHentWiki_Click(_ sender: UIButton) { //** Læs fra nettet let myURLString = "xxxx.php" HentResponseString(url: myURLString) } //** Show rtf text in UITextView @IBAction func btnVisData_Click(_ sender: UIButton) { txtWikiTekst.attributedText = styledText } //** Function the gets the text from php page func HentResponseString(url: String) { let url = URL(string: url)! let request = URLRequest(url: url) let task = URLSession.shared.dataTask(with: request) { data, response, error in guard let data = data else { print("request failed \(error)") return } let responseString = String(data: data, encoding: .utf8) //** Bearbejd responseString let lines = responseString?.components(separatedBy: "#") for line in lines! { let fields = line.components(separatedBy: "$") var xcounter:Int = 0 for field in fields { //** Overskrift if xcounter == 0 { self.aOverskrifter.add(field) } //** Lille tekst if xcounter == 1 { self.aLilleTekster.add(field) } //** Lang tekst if xcounter == 2 { self.aLangTekster.add(field) styledText = field } xcounter+=1 } } } task.resume() } override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } }
But when I run this code I only see the rtf text in the UITextView and not the formatted text.
In the database I’m using UTF8 and in the PHP file i use UTF8, but it does not work correctly.
Does anyone know how to fix this or can you point me in the right direction.
The post swift 3: Get rtf formatted text from MySQL appeared first on Stackinqueue.
0 notes
Text
XAMARIN.IOS ILE MERHABA DÜNYA
XAMARIN.IOS
Bir seri halinde sizlerle Xamarin.iOS üzerinde nasıl uçtan uca bir uygulama geliştirilir bunu anlatacağız.
Konumuzun ilk bölümü olarak basit bir test uygulaması ile başlayıp, daha sonra konuları zorlaştırarak ilerletiyor olacağız.
HELLO WORLD
1. Öncelikle yeni bir proje yaratarak uygulamamıza başlayalım.
Proje tipimizi seçiyoruz.
Proje adımızı ve idmizi giriyoruz. Buradan proje içeriklerimizi ayrıca ayarlayabiliriz.
Proje lokasyonunu giriyoruz. Git repository kullanmak isteyip istemediğimizi ve TestFlight projesi ekleyip eklememeyi buradan seçebiliriz.
2. Projemiz içerisindeki AppDelegate bizim ilk giriş dosyamız. Bu dosyaya girdiğimizde aşağıdaki gibi boş olarak override edilmiş fonksiyonlar ile karşılaşırsınız.
AppDelagate.cs
3. Projemiz içerisindeki Main.storyboard dosyası ise bizim tasarım dosyamızdır. Bu dosya içerisinde sürükle bırak ile uygulamamıza öğeler ekleyebiliriz.
4. Sağ üstteki listeden ekranımıza bir adet buton ve bir adet label sürükleyelim. Daha sonra bu iki öğeyi seçip, sağ alttaki Properties ekranı içerisinden bir isim verelim ve ekrandaki Textlerini düzenleyelim.
Üstteki seçenekler ile ekran boyutumuzu iPhone4’ten itibaren ekran boyutlarına göre değiştirebiliriz.
5. Oluşturduğumuz ekranın Controller dosyası ViewController.cs olarak daha önceden hazır olarak gelmişti. Bu dosyayı açarak içerisini aşağıdaki gibi güncelleyerek ilk iPhone uygulamanıza kavuşmuş olacaksınız:using System;
using UIKit;
namespace Xamarin_iOS { public partial class ViewController : UIViewController { public ViewController (IntPtr handle) : base (handle) { }
public override void ViewDidLoad () { base.ViewDidLoad (); // Perform any additional setup after loading the view, typically from a nib.
testButton.TouchDown += (object sender, EventArgs e) => testLabel.Text = “Butona Basıldı.“; }
public override void DidReceiveMemoryWarning () { base.DidReceiveMemoryWarning (); // Release any cached data, images, etc that aren‘t in use. } } }
BU UYGULAMANIN KODLARINA
HTTPS://GITHUB.COM/UFUF/XAMARIN.IOS
ADRESINDE “PART 1” COMMITI ILE ERIŞEBILIRSINIZ.
0 notes
Link
original source : https://iphonecodecenter.wordpress.com/2015/10/06/life-cycle-of-view-controller-in-iphone/
Life cycle of view controller in iphoneViewController LifeCycle
Today we are going to discuss only about the ViewController LifeCycle and How we should use each of the methods provided in the lifecycle event.
What is LifeCycle?LifeCycle is an event which have certain steps from the point of creation to deletion. So how do we know about the steps during this period? A Sequence of methods are called as they progress through the LifeCycle.Now we may need to perform different kind of actions at different steps of the life cycle and thus we commonly override these methods and perform these actions.
As I said the Start of LifeCycle is Creation. Most of the MVCs are Instantiated through the StoryBoard. So what happen after the creation of the ViewController?
Outlet setting
View Appear and Disappear
Changes in the Geometry
Memory Warnings
At each of the above step iOS invokes methods on the viewControllers. We will discuss each of the methods in detail.
ViewController LifeCycle Methods
awakeFromNib
This is Strictly not part of the viewController lifeCycle but still play a role in the initialization of the viewController. This method is called on all the objects which come out of the StoryBoard. This happens before all the outlet are set i.e. before the loading of the view. Before you put any code in here you must think if you can put it somewhere else may be viewDidLoad or viewWillAppear.
Note: Init method is not called on the objects which came out of the StoryBoard. So you might want to put the code written in the Init method in the awakeFromNib method too.
viewDidLoad
– (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
This is good place to put your setup code for the View. Always call the super class method to complete the lifeCycle methods. At this point of time of LifeCycle we are not sure of the Geometry of the Device so you do not put any code that is based on the Geometry of the view.
viewWillAppear
– (void)viewWillAppear:(BOOL)
animated Notification to the viewController when view is just about to View on the screen. animated argument tells whether you are appearing Instantly or after sometime via an animation. This method can be overridden to change the color or something else of the status bar according to the orientation or as per the style of the view.
Note: As you understand that view will be loaded once, however it will appear and disappear again and again. So you do not want to write a piece of code in this method which actually belongs in viewDidLoad, otherwise you will be doing the same thing again and again.
viewWillDisappear
– (void)viewWillDisappear:(BOOL)
animated Notify the controller that view is about to be removed from the screen. This is the place you will write code like storing the state of the view or Cleaning up the resources being used. animated argument is again to tell whether are are disappearing instantly or via an animation.We might not want to write code thats time consuming. We can kick off some thread which can do the task in the background.There are did versions of both the viewWillAppear and viewWillDisapper methods viewDidAppear and viewDidDisappear which are called after the view is appeared and view is disappeared relatively.
viewWillLayoutSubviews
– (void)viewWillLayoutSubviews
This method is invoked when frame changed its layout and subviews were this re-layout. In this method you can reset the view controls to set for the new layout. However, with iOS 6 and later we do not need this. AutoLayout take care of these layout changes and we can add constraints to the application and this will happen automatically.
didReceiveMemoryWarning
– (void)didReceiveMemoryWarning
This method is rarely called. But if you are doing memory consuming tasks in your application like playing with the large images or playing sounds etc. than you should consider handling this method. To avoid memory warning anything which is memory consuming and can be recreated should be released means you should set the pointer to nil.
참고 사항 ) https://bradbambara.wordpress.com/2015/01/18/object-life-cycle-uiview/
initWithCoder:
layerClass
setNeedsDisplay
addConstraints:
addConstraint: (can happen multiple times)
willMoveToSuperview: invalidateIntrinsicContentSize didMoveToSuperview awakeFromNib willMoveToWindow: needsUpdateConstraints didMoveToWindow setNeedsLayout updateConstraints
intrinsicContentSize layoutSubviews (can happen multiple times) drawRect
#ios#lifecycle#didReceiveMemoryWarning#viewWillLayoutSubviews#viewWillDisappear#viewDidLoad#viewWillAppear#awakeFromNib
0 notes
Link
original source : https://developer.apple.com/library/content/featuredarticles/ViewControllerPGforiPhoneOS/index.html#//apple_ref/doc/uid/TP40007457-CH2-SW1
The Role of View Controllers
View controllers are the foundation of your app’s internal structure. Every app has at least one view controller, and most apps have several. Each view controller manages a portion of your app’s user interface as well as the interactions between that interface and the underlying data. View controllers also facilitate transitions between different parts of your user interface.
Because they play such an important role in your app, view controllers are at the center of almost everything you do. The UIViewController class defines the methods and properties for managing your views, handling events, transitioning from one view controller to another, and coordinating with other parts of your app. You subclass UIViewController (or one of its subclasses) and add the custom code you need to implement your app’s behavior.
There are two types of view controllers:
Content view controllers manage a discrete piece of your app’s content and are the main type of view controller that you create.
Container view controllers collect information from other view controllers (known as child view controllers) and present it in a way that facilitates navigation or presents the content of those view controllers differently. (content를 다루지 않는다. root view만 관리한다)
Most apps are a mixture of both types of view controllers.
View Management
The most important role of a view controller is to manage a hierarchy of views. Every view controller has a single root view that encloses all of the view controller’s content. To that root view, you add the views you need to display your content. Figure 1-1 illustrates the built-in relationship between the view controller and its views. The view controller always has a reference to its root view and each view has strong references to its subviews.
NOTE
It is common practice to use outlets to access other views in your view controller’s view hierarchy. Because a view controller manages the content of all its views, outlets let you store references to the views that you need. The outlets themselves are connected to the actual view objects automatically when the views are loaded from the storyboard.
A content view controller manages all of its views by itself. A container view controller manages its own views plus the root views from one or more of its child view controllers. The container does not manage the content of its children. It manages only the root view, sizing and placing it according to the container’s design. Figure 1-2 illustrates the relationship between a split view controller and its children. The split view controller manages the overall size and position of its child views, but the child view controllers manage the actual contents of those views.
For information about managing your view controller’s views, see Managing View Layout.
Data Marshaling
A view controller acts as an intermediary between the views it manages and the data of your app. The methods and properties of the UIViewController class let you manage the visual presentation of your app. When you subclass UIViewController, you add any variables you need to manage your data in your subclass. Adding custom variables creates a relationship like the one in Figure 1-3, where the view controller has references to your data and to the views used to present that data. Moving data back and forth between the two is your responsibility.
You should always maintain a clean separation of responsibilities within your view controllers and data objects. Most of the logic for ensuring the integrity of your data structures belongs in the data objects themselves. The view controller might validate input coming from views and then package that input in the format that your data objects require, but you should minimize the view controller’s role in managing the actual data.
A UIDocument object is one way to manage your data separately from your view controllers. A document object is a controller object that knows how to read and write data to persistent storage. When you subclass, you add whatever logic and methods you need to extract that data and pass it to a view controller or other parts of your app. The view controller might store a copy of any data it receives to make it easier to update views, but the document still owns the true data.
User Interactions
View controllers are responder objects and are capable of handling events that come down the responder chain. Although they are able to do so, view controllers rarely handle touch events directly. Instead, views usually handle their own touch events and report the results to a method of an associated delegate or target object, which is usually the view controller. So most events in a view controller are handled using delegate methods or action methods.
For more information about implementing action methods in your view controller, see Handling User Interactions. For information about handling other types of events, see Event Handling Guide for iOS.
Resource Management
A view controller assumes all responsibility for its views and any objects that it creates. The UIViewControllerclass handles most aspects of view management automatically. For example, UIKit automatically releases any view-related resources that are no longer needed. In your UIViewController subclasses, you are responsible for managing any objects you create explicitly.
When the available free memory is running low, UIKit asks apps to free up any resources that they no longer need. One way it does this is by calling the didReceiveMemoryWarning method of your view controllers. Use that method to remove references to objects that you no longer need or can recreate easily later. For example, you might use that method to remove cached data. It is important to release as much memory as you can when a low-memory condition occurs. Apps that consume too much memory may be terminated outright by the system to recover memory.
Adaptivity
View controllers are responsible for the presentation of their views and for adapting that presentation to match the underlying environment. Every iOS app should be able to run on iPad and on several different sizes of iPhone. Rather than provide different view controllers and view hierarchies for each device, it is simpler to use a single view controller that adapts its views to the changing space requirements.
In iOS, view controllers need to handle coarse-grained changes and fine-grained changes. Coarse-grained changes happen when a view controller’s traits change. Traits are attributes that describe the overall environment, such as the display scale. Two of the most important traits are the view controller’s horizontal and vertical size classes, which indicate how much space the view controller has in the given dimension. You can use size class changes to change the way you lay out your views, as shown in Figure 1-4. When the horizontal size class is regular, the view controller takes advantage of the extra horizontal space to arrange its content. When the horizontal size class is compact, the view controller arranges its content vertically.
Within a given size class, it is possible for more fine-grained size changes to occur at any time. When the user rotates an iPhone from portrait to landscape, the size class might not change but the screen dimensions usually change. When you use Auto Layout, UIKit automatically adjusts the size and position of views to match the new dimensions. View controllers can make additional adjustments as needed.
For more information about adaptivity, see The Adaptive Model.
다음 내용 ) https://developer.apple.com/library/content/featuredarticles/ViewControllerPGforiPhoneOS/TheViewControllerHierarchy.html#//apple_ref/doc/uid/TP40007457-CH33-SW1
#ios#Content view controllers#controller#view#views#controllers#contatiner view controllers#UIViewController#UIDocument#root#root view#didReceiveMemoryWarning#memeory#resource
0 notes
Video
youtube
my review point is 10/10
NSLayoutConstraint 사용법의 예시 (길이10분정도)
// ViewController.swift
// boundsAndFrame
//
// Created by AJ Norton on 8/27/15.
// Copyright (c) 2015 AJ Norton. All rights reserved.
//
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let v1 = UIView(frame: CGRectMake(50, 50, 300, 200))
v1.backgroundColor = UIColor.redColor()
self.view.addSubview(v1)
let v2 = UIView()
v2.backgroundColor = UIColor.greenColor()
v2.setTranslatesAutoresizingMaskIntoConstraints(false)
v1.addSubview(v2)
v1.addConstraint(
NSLayoutConstraint(item: v2,
attribute: NSLayoutAttribute.Left,
relatedBy: NSLayoutRelation.Equal,
toItem: v1,
attribute: .Left,
multiplier: 1,
constant: 0))
v1.addConstraint(
NSLayoutConstraint(item: v2,
attribute: NSLayoutAttribute.Right,
relatedBy: NSLayoutRelation.Equal,
toItem: v1,
attribute: .Right,
multiplier: 1,
constant: 0))
v1.addConstraint(
NSLayoutConstraint(item: v2,
attribute: NSLayoutAttribute.Top,
relatedBy: NSLayoutRelation.Equal,
toItem: v1,
attribute: .Top,
multiplier: 1,
constant: 0))
v1.addConstraint(
NSLayoutConstraint(item: v2,
attribute: NSLayoutAttribute.Height,
relatedBy: NSLayoutRelation.Equal,
toItem: v1,
attribute: .Height,
multiplier: 0.5,
constant: 0))
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
0 notes