(Ebook) Core Data in Swift: Data Storage and Management for iOS and OS X by Marcus S. Zarra 2024 Scribd Download
(Ebook) Core Data in Swift: Data Storage and Management for iOS and OS X by Marcus S. Zarra 2024 Scribd Download
com
https://ebooknice.com/product/core-data-in-swift-data-
storage-and-management-for-ios-and-os-x-55604558
DOWLOAD EBOOK
ebooknice.com
ebooknice.com
https://ebooknice.com/product/core-data-apple-s-api-for-persisting-
data-on-mac-os-x-1311228
ebooknice.com
https://ebooknice.com/product/learn-swift-on-the-mac-for-os-x-and-
ios-55604892
ebooknice.com
(Ebook) Swift Pocket Reference, 2nd Edition: Programming
for iOS and OS X by Anthony Gray ISBN 9781491940075,
1491940077
https://ebooknice.com/product/swift-pocket-reference-2nd-edition-
programming-for-ios-and-os-x-5474500
ebooknice.com
https://ebooknice.com/product/mac-os-x-and-ios-internals-to-the-apple-
s-core-4586762
ebooknice.com
ebooknice.com
ebooknice.com
(Ebook) Pro Core Data for iOS: Data Access and Persistence
Engine for iPhone, iPad, and iPod touch by Michael Privat,
Robert Warner (auth.) ISBN 9781430236566, 9781430236573,
1430236566, 1430236574
https://ebooknice.com/product/pro-core-data-for-ios-data-access-and-
persistence-engine-for-iphone-ipad-and-ipod-touch-4391064
ebooknice.com
Early Praise for Core Data in Swift
Marcus’s books have long been my go-to recommendation for people who want
to learn about Core Data. With new information for beginners and experts alike,
they are a great insight into how you should be using Core Data and the features
that it offers.
➤ Daniel Tomlinson
Senior software engineer, Rocket Apps Ltd.
Marcus has a profound understanding of Core Data, and this book describes not
only the basics of working with Core Data, but also how to do so in a performant
manner, with explanations and examples. This is an indispensable reference,
alongside Apple’s documentation, and one that will quickly make Core Data your
go-to persistence mechanism. You’ll be able to deal with anything that comes up
with confidence.
➤ Abizer Nasir
Lead developer, Jungle Candy Software Ltd.
Marcus S. Zarra
Introduction . . . . . . . . . . . . . ix
1. Before We Begin . . . . . . . . . . . . 1
Test Application 1
The Storyboard 2
The Recipe List 4
The Recipe Detail 6
The Edit Workflow 7
Ready for Core Data 10
3. iOS: NSFetchedResultsController . . . . . . . 33
How to Use the NSFetchedResultsController 33
Under the Hood of the NSFetchedResultsController 40
Building Our Own: MSZContextWatcher 42
Wrapping Up 45
5. Performance Tuning . . . . . . . . . . . 65
Persistent Store Types 65
Optimizing Your Data Model 67
Fetching 71
Faulting 74
Access Patterns 77
Wrapping Up 78
6. Threading . . . . . . . . . . . . . 79
Threading and Core Data 80
Working on the Main Queue 81
Working off the Main Queue 83
Interqueue Communication 83
Parent/Child NSManagedObjectContext Design 86
Export Operation 87
Import Operation 93
Asynchronous Saving 98
Debug Concurrency Checking 101
Wrapping Up 102
Index . . . . . . . . . . . . . . 191
Introduction
It’s amazing to realize that as of the writing of this book, Core Data is over
12 years old. That’s an incredible number when you consider that it’s more
powerful and more popular today than it has ever been. For a framework,
that’s pretty spectacular.
In this book we discuss Core Data and work with the framework from the
perspective of Swift. Swift is a young language and has a lot of growing yet
to do, but its popularity can’t be denied.
It’s clear that Swift is important to Apple and therefore should be equally
important to developers who work on Apple’s platforms.
A good way to confirm that you know enough Cocoa to benefit from this book
is to take a look at Chapter 1, Before We Begin, on page 1. You should find
it dense, but every step should be familiar to you.
Of course, the problem with Interface Builder is that we still need to code the
other two parts! Both the controller and the model need to be developed in
code and made to work with the interface we just designed. That’s where Core
Data comes in. In a nutshell, Core Data deals with a third of that MVC design:
Core Data is the model.
When you start to learn Core Data, it’s best to think in terms of objects. Core
Data is a framework designed to manage your data and data object graph.
As a secondary function, it will persist that data to disk. However, its primary
function is to manage the objects.
Online Resources
The app and examples shown in this book can be found at the Pragmatic
Programmers website for this book.1 You’ll also find the community forum
and the errata-submission form, where you can report problems with the text
or make suggestions for future versions.
1. http://pragprog.com/book/mzswift/core-data-in-swift
Before We Begin
This is a book with two beginnings and one ending. The ending should be
obvious: to increase your knowledge and understanding of Core Data.
Of the two beginnings, you get to choose. If you’re relatively new to either iOS
development or Swift, then please read this chapter; it was written for you.
If, on the other hand, you’re intimately familiar with iOS—perhaps you even
prefer to build your test cases in your own way—then I suggest you jump to
Chapter 2, Under the Hood, on page 13. The chapter you’re currently reading
focuses on building a test application.
Test Application
When you’re learning how to write software using Swift or when you’re first
learning how to develop an iOS application, the book that’s helping you gen-
erally starts at zero, often referred to as the “Hello World” application.
This is not that kind of book. For us to explore Core Data a certain level of
knowledge is necessary—a foundation of knowledge that we can build upon.
This book expects that you understand the fundamentals of Swift. It’s written
in a such a way that you don’t need to be a master of Swift. We aren’t going
to be doing any complex coding using the unusual bits of Swift. We’re inten-
tionally avoiding those.
The focus of this book is to increase your knowledge of Core Data while
working in the Swift environment. Therefore, the code is as straightforward
as I can make it.
On our journey to learn about Core Data, we’re going to use an original iPhone
recipe application. While the application itself is fairly complex and contains
a large number of views, the concepts behind these views are standard and
will be familiar to anyone who has done work in Cocoa. If you haven’t yet
mastered Swift and Cocoa, then I highly suggest you review Chris Adamson
and Janie Clayton’s iOS 9 SDK Development, published by the Pragmatic
Bookshelf.
If you’re already comfortable with storyboards and the creation of iOS appli-
cations, feel free to skim the provided code sample and jump to Chapter 2,
Under the Hood, on page 13, in which we’ll begin to dive into the substance
of Core Data.
If you were a car mechanic and wanted to learn how to work on transmissions, you’d
buy a book that was specific to transmissions. However, that book wouldn’t teach
you how to build a car; it’d dive right into the workings and theories of a transmission.
The differences between car mechanics and programming show up right away. The
author of the book can be reasonably certain that the reader will have access to a
car and that it is already going to have a transmission built in that the reader can
use to apply the knowledge from the book. This isn’t necessarily true in programming.
Since I can’t be certain that you have an application in your possession that contains
Core Data already, I’m including one with this book. This chapter gives you a car to
tinker with while we explore the transmission.
The Storyboard
To keep the structure of our application as simple as possible, we’ll use a
storyboard to design the entire UI of our iPhone application. As you’ll recall
from your reading or experience, a storyboard allows us to view the entire
application interaction in one place. We can also control a greater portion of
the UI within the storyboard and thus allow for even less code to be introduced
to our project. You can see a zoomed-out version of our storyboard in the
following screenshot on page 3.
What Is a Storyboard?
When non-Apple developers think of storyboards, they think of playing with application
flow and designs—probably on a napkin or a whiteboard. However, with Apple’s
development tools, the word “storyboard” has a different meaning.
Within Xcode is a visual design tool called Interface Builder. Interface Builder can
produce a file referred to as a “storyboard.” These storyboards can be all or part of
an application’s user interface. It’s possible for every visual element within an appli-
cation to be stored inside a single storyboard file.
These storyboard files get compiled into the application and are used when the
application is run to display the user interface. They’re the latest iteration of Apple’s
user interface tool that previously produced “nib” and “xib” files.
This storyboard seems complex—and it is. However, most of the code needed
to support these views is minimal, and there’s a fair amount of view controller
reuse that will make the application easier to develop and maintain.
There are three primary elements to this application: a list of recipes, a detailed
view of a single recipe, and the ability to add/edit recipes. The add/edit feature
is the most complex, so we’ll save it for last.
switch identifier {
case "showRecipe":
prepareForDetailSegue(segue)
case "addRecipe":
prepareForAddRecipeSegue(segue)
default:
fatalError("Unexpected segue: \(identifier)")
}
}
The first segue brings in the PPRDetailViewController and displays a single recipe
in detail. The method prepareForDetailSegue(:) demonstrates the dependency
injection pattern. We obtain a reference to the about-to-be exposed UIViewCon-
troller, and we inject the information that it needs. We’ll use this pattern
extensively throughout the book.
PPRecipes/PPRecipes/PPRMasterViewController.swift
func prepareForAddRecipeSegue(segue: UIStoryboardSegue) {
let tempController = segue.destinationViewController
let controller = tempController as! PPREditRecipeViewController
let moc = managedObjectContext!
let recipe = NSEntityDescription.insertNewObjectForEntityForName("Recipe",
inManagedObjectContext: moc) as! PPRRecipeMO
controller.recipeMO = recipe
}
The second segue branches us into the editing capabilities of our application.
This is our first bit of code reuse.
Instead of having an “add” logic path and an “edit” logic path, the paths are
combined. In fact, their functionality is 99 percent identical. The 1 percent
difference between them concerns whether an object is being created or an
existing object is being edited. By again using dependency injection, we pull
that 1 percent difference out of the logic path and let the parent UIViewController
make the decision. As far as the rest of our editing workflow is concerned,
there’s no difference. It’s being handed a data object, and it doesn’t matter
whether the object has been created anew or whether it previously existed.
In our UIViewController, we’ll take the data object that was passed to us and
display it in one (potentially) lengthy UIScrollView.
The edit button in the UINavigationBar is the interesting part of this view con-
troller. When the edit button is tapped, we enter the edit workflow (we’ll dis-
cuss this further in the next section). This process is identical to the add
workflow we discussed in The Recipe List, on page 4. With this code reuse,
we can now enter the same workflow from the view controller that allows us
to view a recipe as we did from the list recipes view controller. Both of these
produce the same effect: we can edit a recipe, and it doesn’t matter if that
recipe is new or existing.
PPRecipes/PPRecipes/PPRDetailViewController.swift
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
guard let identifier = segue.identifier else {
fatalError("Unidentified segue")
}
assert(identifier == "editRecipe", "Unexpected identifier: \(identifier)")
controller.recipeMO = recipeMO
}
Note the subtle difference in this reuse. In the previous version of the edit
workflow, we created a new data object. In this version, we take our existing
reference to the data object and hand it off to the edit workflow.
The bulk of the complexity of the edit workflow is in the very first UIViewController.
To begin with, this UITable ViewController uses static cells, as opposed to prototype
cells. In this design, we have a known quantity of cells, and each cell displays
a different piece of information.
can have the storyboard do the bulk of that work for us. Each cell in this
UITableViewController has a segue to another UIViewController. Each of those segues
is named, and we can therefore do away with a large portion of code. Our
UITableViewController subclass needs to look only at the identifier of the segue
and inject the right dependencies.
PPRecipes/PPRecipes/PPREditRecipeViewController.swift
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
guard let identifier = segue.identifier else {
fatalError("Unidentified segue")
}
switch identifier {
case "editRecipeName":
prepareForEditRecipeNameSegue(segue.destinationViewController)
case "selectRecipeType":
prepareForSelectTypeSegue(segue.destinationViewController)
case "selectNumberOfServings":
prepareForSetServingsSegue(segue.destinationViewController)
case "selectLastUsed":
prepareForSetDateSegue(segue.destinationViewController)
case "selectAuthor":
prepareForSelectAuthorSegue(segue.destinationViewController)
case "selectIngredients":
prepareForSelectIngredientSegue(segue.destinationViewController)
case "editDescription":
prepareForDirectionsSegue(segue.destinationViewController)
default:
fatalError("Unrecognized segue: \(identifier)")
}
}
Here we see the value of using the -prepareForSegue: sender: method only for
branching. Had we put all of the flow logic into this one method, it would
easily be 100 lines of code or more and be a mess to maintain.
All of the UIViewController instances that are accessed from the edit UITableViewCon-
troller fall into one of two categories: edit something or select something. Let’s
look at an example of both kinds of instance. See the following screenshot.
PPRecipes/PPRecipes/PPREditRecipeViewController.swift
func prepareForEditRecipeNameSegue(ac: UIViewController) {
guard let controller = ac as? PPRTextEditViewController else {
fatalError("Unexpected controller type")
}
controller.text = recipeMO?.valueForKey("name") as? String
The most interesting part of this segue preparation is the callback. The PPR-
TextEditViewController is actually quite dumb. Its entire job is to consume the text
entered into a text field and listen for either the Done button to be clicked or
the Return key to be tapped. When either of those happen, it takes the text
from the UITextField (or the UITextView) and passes it to the callback block.
Note that the block accepts a string and expects the closure to throw an error
if it’s appropriate. The parent, which defines the block, then validates the text
and throws the error if there’s a problem. The PPRTextEditViewController receives
a pass/fail from the block. In the event of a failure, it displays the error. If
the block returns a pass, the text view controller pops back to its parent.
With this design, we can use the PPRTextEditViewController to edit any piece of text
we choose, and it doesn’t need any custom or special handling code. The only
thing we need to do for each instance is set up its view in the storyboard and
pass in the text that it needs to start with. By customizing the view, we also
gain access to which keyboard is appropriate for each text edit, thereby
making it easy to reuse this UIViewController for numeric text, email addresses,
or virtually any data we can think of.
The second function of the callback block is to update the data object and
the edit view. Since we’re using static cells, we must grab a reference to the
existing cell and refresh it based on the text being passed into the block.
Later, as we update and enhance our application, this workflow becomes even
longer and more complicated. Fortunately, the code stays quite sane with the
reuse of view controllers and the use of the storyboard.
Unfortunately, we need to build two specific view controllers for this workflow:
one to handle listing the ingredients (including adding and deleting) and one
for adding an ingredient. Luckily, we can get a lot of reuse from our text edit
view controller in this part of the application.
At the end of that chapter, you’ll have a firm understanding of the Core Data
stack and how to access it. From there we’ll begin to utilize some of the more
advanced concepts behind Core Data to improve on our application.
You can download the source code for this application (and the future changes
we’re going to introduce) at PragProg.com.1
1. http://www.pragprog.com
Part of the barrier to entering the world of Core Data is that it’s perceived as
having a steep learning curve. Looking at the code samples that Apple provides
for developers, you might at first glance agree with that evaluation. That
perception was born from the first few iterations of the framework. When Core
Data was first introduced, there was a large amount of confusion over what
needs to be done, what doesn’t need to be done, and what we’re allowed to
do with the framework. A lot has changed since those early days. As you’ll
see in the next couple of chapters, Core Data is very easy to use, and when
you need the complexity to handle an edge case, the options are available.
In this chapter, we go through the key pieces of Core Data and remove some
of the mysticism that surrounds them. By the end of this chapter, you’ll have
a much higher comfort level and will be able to understand what all of that
sample code does. We’ll also be discussing the terminology of Core Data so
that you can better understand what the individual components are and how
they work together.
At its most basic level, Core Data is an object graph designed to manage data
objects. It’s common when you’re first approaching Core Data to think of it
as an object-relational mapping framework—and in truth, it can be used as
such. However, that isn’t the best approach. My elevator pitch for Core Data
goes like this: “Core Data is an object graph that can persist to a database.”
The primary function of Core Data is to manage the object graph. Persisting
the data to disk is a secondary, although vital, function.
The Core Data API, or stack as it’s commonly called, consists of three primary
pieces: the NSManagedObjectModel, the NSPersistentStoreCoordinator, and the NSManage-
dObjectContext, as shown here.
All of these pieces work together to allow a program to retrieve and store
NSManagedObject instances. In most situations, the program will access the
NSManagedObjectContext only once the stack has been created. It’s possible to
access the other components of the stack, but it’s rarely necessary. Each of
the three pieces of the Core Data stack work together. As we’ll review in detail,
the NSManagedObjectModel feeds structure to the NSPersistentStoreCoordinator and the
NSPersistentStoreCoordinator feeds data and structure to the NSManagedObjectContext.
The NSManagedObjectContext in turn handles requests from the rest of the appli-
cation to create, update, delete, and insert NSManagedObject instances.
Throughout this chapter, and most of the rest of the book, we’ll be referencing
the application that we built in Chapter 1, Before We Begin, on page 1. We’ll
start that reference by exploring the creation of the Core Data stack.
While this view is great for conceptualizing the data and the objects, it’s not
great for editing. Therefore, the style can be changed using a control in the
lower-right corner called Editor Style. The second style is shown here.
Xcode understands how to compile these files in this bundle. When Xcode
encounters these files during the compile process of a project, it compiles
them into a binary form ending with the extension mom inside of a bundle
with the momd extension. We can also build these files from the command line
using the momc tool.
This presents us with a blank data model ready to be edited. From here, in
grid view, we added the three entities being used in the project: Recipe,
RecipeIngredient, and Type. We then added the attributes and relationships for
each of those entities. For a discussion of entities, attributes, and relation-
ships, take a look at Working with NSManagedObject Instances, on page 21.
Further, I like to construct the entire Core Data stack in a single method.
There’s rarely a situation where you wish to build only part of the stack. With
that structure, you can kick off the initialization of the Core Data stack as
soon as the application launches so that it’s available, in some form, immedi-
ately. Therefore, in our sample application, we have a method named -initial-
izeCoreDataStack that starts off with constructing the data model.
PPRecipes/PPRecipes/PPRDataController.swift
func initializeCoreDataStack() {
guard let modelURL = NSBundle.mainBundle().URLForResource("PPRecipes",
withExtension: "momd") else {
fatalError("Failed to locate DataModel.momd in app bundle")
}
guard let mom = NSManagedObjectModel(contentsOfURL: modelURL) else {
fatalError("Failed to initialize MOM")
}
In previous versions of Core Data and the sample projects, the initialization
of the NSPersistentStoreCoordinator and the addition of the NSPersistentStore were done
in a single method. This example tended to lead to a number of issues for
developers because they didn’t fully understand the impact of the example.
Therefore, we’re going to do this initialization in a more complex way, but it
will be a way that won’t paint us into a corner.
PPRecipes/PPRecipes/PPRDataController.swift
let psc = NSPersistentStoreCoordinator(managedObjectModel: mom)
PPRecipes/PPRecipes/PPRDataController.swift
let queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
dispatch_async(queue) {
let fileManager = NSFileManager.defaultManager()
guard let documentsURL = fileManager.URLsForDirectory(.DocumentDirectory,
inDomains: .UserDomainMask).first else {
fatalError("Failed to resolve documents directory")
}
let storeURL = documentsURL.URLByAppendingPathComponent("PPRecipes.sqlite")
do {
try psc.addPersistentStoreWithType(NSSQLiteStoreType,
configuration: nil, URL: storeURL, options: nil)
} catch {
fatalError("Failed to initialize PSC: \(error)")
}
In this portion of the code, we grab a reference to a global queue with a default
priority. Then we add a block to be executed on that queue that will handle
the addition of the NSPersistentStore to the NSPersistentStoreCoordinator.
Inside that block, we first determine where we want to store the file associated
with our NSPersistentStore. In this example, we’re going to put it into the Docu-
ments directory that’s part of the application sandbox. If we were working on
OS X, we could put it in the Application Support folder or anywhere else that
was appropriate. We resolve this path using the NSFileManager and call its
URLsForDirectory(: inDomains:) method, which will return an array of NSURL instances.
We call first on that array to retrieve the last NSURL. We then append the file-
name for our NSPersistentStore to the end of that NSURL.
With the location of the store now resolved, we can add the NSPersistentStore to
the NSPersistentStoreCoordinator. We do this with a call to addPersistentStoreWithType(:
configuration: URL: options:). This is a complex method call, so let’s break it down
by parameter. There are four in all.
• The first parameter is Type. This tells the NSPersistentStoreCoordinator what type
of store we want initialized. In this case, we’re passing NSSQLiteStoreType to
indicate we want a SQLite store. This is the parameter to change if we
want to use another store type.
Die Fischerei hat über die Menge der tierischen Feinde vielleicht
noch mehr zu klagen als die Jagd. Dabei wollen wir die kleineren
Räuber, die den Kerbtieren angehören, ganz unberücksichtigt lassen:
den Gelbrand und seine Larve, die nicht nur die junge Brut
überfallen, sondern sich auch nicht scheuen, mit ihren scharfen
Freßwerkzeugen selbst größere Fische anzubeißen, oder den
Rückenschwimmer, auch Wasserwanzen und Wasserskorpion,
ebenso die äußerst räuberischen Larven mancher anmutigen
Libellen, die als fertige Insekten zu den harmlosesten Tieren
gehören. Wir wollen nur an die vielen Fischfeinde oder, besser
gesagt, an die Fischliebhaber denken, die dem Fischereiberechtigten
aus der Reihe der Wirbeltiere mancherlei Schaden verursachen.
Ein wirkliches Raubtier, der Fischotter, der Familie der Marder
angehörend, ist wohl am meisten gefürchtet. Töricht und
ungerechtfertigt wäre es, vom Fischereiberechtigten zu verlangen,
diesen bösen Fischräuber unbehelligt zu lassen. Wo er sich in unsern
Teichgebieten zeigt, die vornehmlich der Karpfen- und Schleienzucht
dienen, da bleibt dem Besitzer oder Pächter gar nichts anderes
übrig, als den Otter im Eisen zu fangen oder auf dem Anstand zu
schießen oder auch durch scharfe Otterhunde und Teckel ihn in
seinem Bau aufzustöbern; denn der Schaden, den der gewandte
Schwimmer hier anrichtet, ist unberechenbar groß, zumal der
Fischotter ungleich mehr Fische vernichtet, als er zu verzehren
vermag. Auch den Möweneiern, der Kiebitzbrut, jungen Gänsen und
Enten, zahmen wie wilden, stellt der mordgierige Räuber nach. Aber
es gibt doch auch Gewässer in unserm Vaterland, Flüsse und Bäche,
wo von größerem Fischreichtum nie die Rede sein kann. Wenn sich
hier 'mal ein Fischotter zeigt und der Fischereiberechtigte fängt nun
an zu rechnen: 6 Pfund Fische täglich zum Fraß und noch doppelt so
viel aus reiner Mordlust, macht 18 Pfund auf den Tag oder
65 Zentner im Jahre; alles halbpfündige Forellen vielleicht – mir
schwindelt der Kopf, wenn ich dran denke, wieviel Tausende
Papiermark das ausmacht: so ist solches Rechenwerk einfach
lächerlich; denn so viel Fische beherbergt der ganze Fluß nicht,
selbst wenn man die winzigsten Schneider mitrechnet. Oder hofft
der Fischer etwa, wenn er den Übeltäter erst 'mal hat nun die
65 Zentner Fische selbst einheimsen zu können? Vergebliche
Hoffnung! Zu fischreichen Gründen, wie sie es vielleicht ehemals
waren, als die Fabriken durch ihre Abwässer den Flußlauf noch nicht
verunreinigt hatten, werden derartige Gewässer niemals wieder sich
umwandeln, ob man den Otter gewähren läßt oder ihn wegfängt.
Zum Glück ist der Herr der Seen und Flüsse ein kluges Geschöpf,
vorsichtig, mißtrauisch; die geringste Veränderung in der Nähe
seines Baues und Ausstieges bemerkt er sofort, und so müht sich
der Fänger in vielen Fällen vergeblich ab, den Fischräuber zu
überlisten. Wir dürfen hoffen, daß das interessante »Fischsäugetier«
unserer Heimat trotz aller Nachstellungen, wenn auch in
verschwindend geringer Anzahl, erhalten bleibt.
Auch die Verwandten, die Mitglieder der eigentlichen
Marderfamilie, stellen gelegentlich den Karpfen und Schleien und
selbst den flinken Forellen nach. Gute Schwimmer sind sie alle, und
was sie erreichen können zu Land und zu Wasser, wird
erbarmungslos gemordet. Aber gerade die Vielseitigkeit ihres
Speisezettels – Eichkatzen, Wildtauben, Häher, Krähen, allerlei
Kleinvögel und ihre Eier, Mäuse und Frösche, Ratten, Junghasen,
Kaninchen, Fasanen, Eidechsen, Fische, Maikäfer usw. – beweist,
daß sowohl die größeren Arten, Baum-, Hausmarder und Iltis, als
auch die kleineren, Hermelin und Mauswiesel, neben beträchtlichem
Schaden, den sie vor allem der Niederjagd zufügen, doch auch
manchen Nutzen stiften. Wo sie sich zu stark vermehren, da soll
man ihnen Einhalt gebieten; aber sie auszurotten, wäre eine sehr
bedenkliche Maßnahme. Mäusefraß und Rattenschaden, übermäßige
Vermehrung der Eichhörnchen oder auch der Krähen und Wildtauben
würden solchen Weltverbesserern beweisen, daß sie auf dem
Holzwege sind.
Auch die kleine Wasserspitzmaus wird des Fischraubes
beschuldigt, und gewiß mag ihr manche Elritze, mancher Stichling
zum Opfer fallen; aber wenn man bedenkt, daß die flinken, ewig
hungrigen Spitzmäuse jedes Tier auffressen, das sie überwältigen
können, Schnecken, Egel, Libellen- und Schwimmkäferlarven,
Flohkrebse, Uferwanzen, Heuschrecken, Regenwürmer, Raupen,
Larven von Köcherfliegen u. a., wird der Fischpächter versöhnlicher
gestimmt werden und den kleinen muntern Schwimmern auch 'mal
ein Fischchen gönnen.
Über die Wasserratte, die im Gegensatz zu den bisher genannten
Fleisch- und Insektenfressern zu den Nagetieren zählt, sind die
Ansichten geteilt. Die einen meinen, die Wasserratte rühre kein
Fischlein an; andere dagegen behaupten, kleine Fische fielen ihr
häufig zum Opfer, und wo Fischzucht getrieben wird, dürfe es daher
keine Wasserratten geben. Allzugroß wird der Schaden jedenfalls
nicht sein, zumal der Nager durch den Fang fischfeindlicher
Wasserinsekten manchen Verlust wieder auszugleichen mag.
Aber gefiederte Fischräuber gibt es viel mehr als bepelzte – leider,
leider! Man kann es den Fischereiberechtigten wirklich nicht
verargen, wenn sie sich gegen die Konkurrenz, die ihnen von dieser
Seite zweifellos in oft recht empfindlicher Weise gemacht wird, zur
Wehr setzen. Auf der andern Seite sind gerade unter diesen
gefiederten Fischliebhabern einige, die zu den schönsten Mitgliedern
der Vogelwelt gehören und unsern Teich- und Seenlandschaften zum
reizvollsten Schmuck gereichen, so daß deren Verfolgung den
Naturfreund außerordentlich schmerzlich berühren muß. Hier ist eine
Verständigung sehr schwierig. Es muß der Fischer dem Vogelfreund
ein wenig entgegenkommen, und dieser jenem. Schon wenn jeder
sich bemüht, den Standpunkt des andern zu verstehen und zu
würdigen, wird viel gewonnen sein.
Ich denke, man sollte zunächst einmal unterscheiden, ob es sich
um einzeln lebende Fischräuber handelt, z. B. den Fischadler, den
Schwarzstorch, den Eisvogel, die also mehr oder weniger als
Einsiedler hausen und ein weites Revier für sich beanspruchen, oder
um solche Vögel, die in größerer Menge auftreten, wie Reiher,
Möwen, Taucher u. a. Bei jenen darf man wohl erwarten, daß der
einsichtsvolle Fischer, dem doch auch die Erhaltung der heimatlichen
Natur am Herzen liegt, ein Auge zudrückt, falls die Verhältnisse nicht
besonders ungünstig sind; es kann ja hier höchstens von einem
örtlichen, nicht aber von einem allgemeinen Schaden die Rede sein.
Bei den in größerer Anzahl auftretenden Schädlingen aber sollte man
sich damit begnügen, sie auf ein gewisses Maß zu beschränken. Und
dieses Maß, das nicht überschritten werden darf, scheint mir
allerdings für manche Gegend bereits erreicht zu sein. Indessen
allgemeine Regeln, die in jedem Einzelfall zu beachten sind, lassen
sich nicht aufstellen.
Wer den Eisvogel aus dem Bereich der Fischzuchtanstalten
vertreibt, dem wird man es nicht verargen können; denn wo diese
gefiederten Fischer in größerer Anzahl regelmäßig bestimmte
Setzteiche besuchen, da wird der Schaden nicht unerheblich sein,
obgleich sie nur kleinfingerlange Fischchen erbeuten. Solche Fälle
aber sind Ausnahmen. Jedes Pärchen beansprucht ein großes Gebiet
und duldet kein zweites in unmittelbarer Nähe. Und gerade in
unserer Heimat sind die Eisvögel bereits so selten geworden, daß ich
nicht weiß, ob jeder meiner Leser schon einmal in freier Natur den
leuchtenden Funken, rotgoldig glänzend und seidig blau, an sich hat
vorüberschießen sehen, oder ob er ihn nur im ausgestopften
Zustande kennt. Jedenfalls ist es selbst für den, der mit der
gefiederten Welt der Heimat vertraut ist, immer ein Ereignis, wenn
er dem Eisvogel an unsern Bächen, Flüssen und Teichen begegnet.
Ihn überall, wo er sich zeigt, wegzuknallen oder in kleinen
Tellereisen zu fangen, ist eine Versündigung an der Natur. An unsern
Gebirgsbächen, an unsern Flüssen, an allen Teichen, die nicht
gerade der Fischzucht dienen, sollte man den einsamen Fischer
ruhig gewähren lassen. Oder ist wirklich jemand der Meinung, der
Eisvogel trage die Schuld, daß die heimatlichen Gewässer so arm an
Fischen sind?
In dem überaus heißen und regenarmen Sommer des Jahres
1911, wo bei uns alle Quellen versiegten, jedes Bächlein, jeder
Graben austrocknete, da sammelten sich einige Eisvögel an dem
einzigen größeren Bach meiner Heimat, der noch etwas Wasser
führte; der Hunger trieb sie hierher. Aber dem Tode entging vielleicht
keiner; man schoß ab, so viel man erreichte. Wozu? Hier, wo von
gewinnbringender Fischerei nicht die Rede sein kann, wo nur
gelegentlich ein paar Forellen gefangen werden, hätte man doch
wahrhaftig den schönen Vögeln den kleinen Tribut gönnen können,
den sie beanspruchten; nach kurzer Zeit würden sie sich wieder über
ein weites Gebiet, aus dem sie die Trockenheit vertrieben hatte,
verstreut haben. Ist der Fischereiberechtigte der sogenannten wilden
Fischereien wirklich in so bedrängten Verhältnissen, daß es ihm auf
ein paar winzige Fischchen ankommt? so fragt man sich. Nimmt er
lieber den Unwillen der vielen Naturfreunde, die solche
Handlungsweise mit Recht verurteilen, auf sich, als daß er auf eine
kleine Anzahl zum Teil fast wertloser Schuppenträger verzichtet?
Man möchte solch engherzigem Pfennigrechner den geringen Verlust
gern aus eigner Tasche ersetzen.
Und nun die weitere Frage: Hat der Fischereipächter ein
gesetzliches Recht, den Eisvogel zu töten? Nach dem deutschen
Vogelschutzgesetz ist der Eisvogel ebenso geschützt wie jeder
Singvogel. Bei uns in Sachsen wird er laut eines Beschlusses des
Finanzministeriums vom 3. Juni 1912 als jagdbar angesehen, »da er
wirtschaftlich wesentlich schädlich« sei3; doch soll er die allgemeine
Schonzeit vom 1. Februar bis mit 31. August genießen. Die
Dienststellen der Forstverwaltung sind angewiesen, ihn durchaus zu
schonen. In Preußen dürfen die Fischereiberechtigten den Eisvogel
ohne Anwendung von Schußwaffen fangen und töten, in Sachsen
nicht. In Bayern aber, in Württemberg, Baden, Mecklenburg und in
fast allen andern deutschen Einzelländern ist der Eisvogel unbedingt
geschützt. Man ist sich in vielen Kreisen über diese rechtliche
Stellung unseres Vogels noch gar nicht im klaren.
Viel allgemeiner und auch viel gerechtfertigter sind die Klagen der
Fischer über die Schädigungen durch den Fischreiher, gehört doch
dieser stattliche Vogel auch heute noch vielen deutschen Ländern als
Brutvogel an. Freilich auch seine Zahl ist, wie die aller größeren
Vögel, außerordentlich zurückgegangen, und die wirklich
reichbesetzten Reiherkolonien oder Reiherstände, welche Hunderte
von Horsten vereinigen, gehören bereits zu den Seltenheiten. Viele
Reiherstände sind völlig verschwunden. Nichts erinnert mehr daran,
daß einst in den hohen Buchen und Eichen zahlreiche Horste
standen; andere wieder, erst vor kurzem erloschen, zeigen noch in
den Wipfeln der Bäume die verlassenen Brutstätten, bis schließlich
ein Wintersturm die ineinander geflochtenen Reiser zerstreut.
Jedenfalls sind die Zeiten vorbei, wo man sicher sein konnte, im
Frühling und Sommer an jedem Fluß, an jedem See wenigstens
einige dieser schönen Vögel anzutreffen.
Im Mittelalter und auch später noch, bis ins 17. Jahrhundert,
erfreuten sich edle Herren und Damen an der Reiherbeize. In frohem
Zuge ritt man von der Burg herab, gefolgt von Jagdgästen,
Falkonieren und der bellenden Meute. Zeigte sich ein Reiher, so ließ
der Jagdherr und gleich darauf eine der Damen die schnell
entkappten Falken steigen, die nun versuchten, das immer höher
gehende Beutetier gemeinsam unter sich zu bringen. »Wie auf der
Fuchshatz sausen Reiter und Reiterinnen durch dick und dünn, den
sich in der Ferne fast verlierenden Kämpfern nach. Endlich hat ein
Falk die Fänge in die dicken Schwingen des Reihers gehakt, und
beide Partner wirbeln zur Erde. Der erste Reiter packt sie, bekappt
den Falken und stellt den Reiher der Dame vor.« Die unbeschädigten
Reiher, denen man nur ein paar Schmuckfedern nahm, ließ man
dann oft wieder fliegen; doch tötete man sie auch bisweilen, weil ihr
Wildbret auf vornehmen Tafeln sehr geschätzt war.
Der Reiher gehörte damals zur »hohen Jagd«, deren Ausübung
das Vorrecht hochstehender Personen, geistlicher und weltlicher
Würdenträger, war. Die Strafen, mit denen die unbefugte Tötung
eines Reihers bedroht ward, waren äußerst hart. Kein Reiherhorst
durfte zerstört, kein Ei genommen werden, und nur dem
Fischereiberechtigten war es allergnädigst gestattet – Scheuchen
aufzustellen. In Sachsen erreichte die Falknerei unter August dem
Starken ihren Höhepunkt; es wurden stattliche Summen für diesen
Jagdsport ausgegeben, und wenn die Falken auch auf das
verschiedenste Federwild, z. B. Trappen, Gänse, Schwäne,
Rebhühner, Wachteln, losgelassen wurden, die Beizjagd des Reihers
blieb doch immer die Hauptsache.
Wie haben sich die Zeiten gewandelt! Das deutsche
Vogelschutzgesetz hat die Reiher, sowohl den grauen Fischreiher, wie
den Nachtreiher und die Rohrdommel, auf die Liste der Geächteten
gesetzt; es gewährt ihnen in keiner Weise irgendwelchen Schutz,
und die preußische Jagdordnung vom 15. Juli 1907, die doch alle
Sumpf- und Wasservögel als jagdbare Tiere bezeichnet, schließt die
grauen Reiher – ebenso die Taucher, Säger, Kormorane und
Bläßhühner – von diesem Vorrecht aus. In Preußen entbehren also
die Fischreiher des Jagdschutzes, während die andern Reiherarten,
eingeschlossen die Rohrdommeln, jagdbar sind. Der Fischreiher
unterliegt somit in Preußen dem freien Tierfang, d. h. er darf auch
vom Nichtjagdberechtigten allezeit gefangen, getötet und seiner Brut
beraubt werden; er ist völlig schutzlos, der Willkür eines jeden
preisgegeben.
Bei uns in Sachsen liegen die Verhältnisse insofern etwas anders,
als die Reiher jagdbar sind. Es hat also nur der Jagdberechtigte ein
Anrecht auf sie. Irgendwelche Schon- und Hegezeit ist den Reihern
freilich versagt. Das Gesetz über die Ausübung der Fischerei vom
15. Oktober 1868 gestattet aber auch den Fischereiberechtigten, den
Fischreiher – ebenso den Fischotter – zu fangen und ohne
Benutzung des Schießgewehrs zu töten. Innerhalb 24 Stunden sind
die auf diese Weise erbeuteten Vögel an den Jagdberechtigten
auszuliefern. Auf die andern Reiherarten steht dem Fischer kein
Anrecht zu. Ähnlich lauten die Bestimmungen in den meisten
deutschen Einzelländern. In Bayern, Sachsen-Weimar, Hessen ist der
Fischreiher wie bei uns jagdbar, in Württemberg, Baden,
Mecklenburg, Oldenburg vogelfrei wie in Preußen.
Ich wüßte keinen einheimischen Vogel zu nennen, dessen
Geschlecht in den letzten 150 bis 200 Jahren so blutigen
Verfolgungen ausgesetzt gewesen wäre, wie der Fischreiher, und
wenn diese Verfolgungen heute auf ein geringeres Maß
zurückgegangen sind, so liegt der Grund hierfür nur in der Tatsache,
daß die Reiher an Zahl außerordentlich stark abgenommen haben.
Der Haß, mit dem man dem Fischräuber begegnet, ist der gleiche
geblieben. Wo sich der schöne, schon durch seine Größe auffallende
Vogel zeigt, und sei es auch nur auf der Wanderung, wenn er ein
wenig rastet, da sucht man seiner habhaft zu werden; an den
Horstplätzen aber wird zur Brutzeit unter den Alten sowohl, wie
namentlich unter den bald flugbaren Jungen, die auf dem Horstrand
hocken, oftmals das furchtbarste Blutbad angerichtet. Am Wasser
stellt der Fischer versteckte Fangeisen auf; tollkühne Burschen
klettern an den hohen Horstbäumen empor und wagen sich bis zu
den Nestern, die häufig auf den schwankenden Enden der Äste ihren
Platz haben; sie rauben die licht-grünlichblauen Eier, deren das volle
Gelege meist 4 bis 5 Stück zählt. Prämien, von Fischereivereinen
gewährt, locken immer mehr zu rücksichtsloser Vertilgung. In der
Tat, man muß sich wundern, daß es auch heute noch im Deutschen
Reiche eine Anzahl von Reiherhalden gibt – gegen früher allerdings
nur spärliche Reste. Ich fürchte sehr, daß auch diese in einem halben
Jahrhundert fast völlig verschwunden sein werden, und daß dann
der Reiher für Deutschland als Brutvogel ebenso selten sein wird,
wie heute schwarzer Storch, Kolkrabe, Uhu oder Wanderfalk.
In Süddeutschland, d. h. südlich des Mains, gibt es schon jetzt
kaum noch ein paar kleinere Kolonien; sie sind fast alle in den
letzten 30 oder 50 Jahren vernichtet oder versprengt worden, so daß
sich nur noch hie und da einzelne Reiherhorste finden. Als fast
einzige Ausnahme ist die Kolonie bei Schloß Morstein an der Jagst,
auf der Besitzung des Freiherrn von Crailsheim, hervorzuheben; aber
auch sie ist stark zurückgegangen, und von den 200 Horsten, die sie
vor einigen Jahren zählte, wird wohl kaum noch die Hälfte besetzt
sein, obgleich die Besitzer von jeher den schönen Tieren Schutz
gewährten und auf manche Vorteile verzichteten. Es ist leicht
möglich, daß diese Kolonie das ehrwürdige Alter von mehr als einem
halben Jahrtausend erreicht hat; denn eine Nachricht aus dem Jahre
1586 besagt, daß die Reiher hier schon »seit vielen hundert Jahren«
horsten. Die Maingegend zählt noch einige Reiherstände; in
Mittelfranken beherbergte z. B. der Windheimer Stadtwald
Schoßbach im Forstamte Ipsheim noch vor einiger Zeit eine Kolonie
von 20 bis 25 Horsten; wie es heute um sie steht, weiß ich nicht.
Auch im Hessischen gibt es noch einige kleine Reiherhalden,
während die Kolonien bei Nürnberg, Neuhaus in der Fränkischen
Schweiz u. v. a. der Vergangenheit angehören. In ganz Elsaß-
Lothringen scheint der Fischreiher nur als Strichvogel und auch nur
ausnahmsweise vorzukommen, und in der Rheinprovinz ist sein
Brutgebiet ganz beschränkt.
In den übrigen Ländern Mittel- und namentlich Norddeutschlands
ist der Reiher noch häufiger; er fehlt als Brutvogel wohl keiner
preußischen Provinz völlig und tritt ebenso in Oldenburg und in
Mecklenburg in mehreren Kolonien auf. Aber es gibt doch auch weite
Gebiete, wo man heute vergeblich selbst nach nur einzelnen
Reiherhorsten suchen würde. Unserm Sachsen fehlt der Reiher als
Brutvogel völlig, nachdem die letzte Kolonie auf den alten Eichen
einer Insel im »Horstsee« bei Schloß Hubertusburg durch Fällen der
Bäume i. J. 1888 vernichtet worden ist. Einige Reiher zogen sich
wohl nach dem Wermsdorfer Wald zurück, sind aber auch dort schon
längst völlig verschwunden.
Die letzte Kolonie ganz in der Nähe der sächsischen Grenze, nur
10 oder 11 km von ihr entfernt, nördlich von Königswartha, die ich
i. J. 1912 besuchte, stand in einem öden Kiefernwald bei Weißkollm.
Ich konnte im ganzen 16 Horste zählen, die bis auf einen sämtlich
besetzt waren: mächtige Bauwerke aus starken Reisern, 1½ bis
gegen 2 m im Durchmesser, mit weißem Kot übertüncht.
Generationen haben an diesen Horsten gebaut, die seit
Menschengedenken von den schönen Vögeln bewohnt wurden. In
jedem Jahr die gleiche Anzahl von Reiherfamilien, nicht mehr und
nicht weniger. Ein herrlicher Anblick, wenn die stolzen Segler der
Lüfte ruhigen Flugs über den uralten Föhren, die ihre Nester tragen,
in schwindelnder Höhe kreisen! Kopf und Hals sind auf den Rücken
gelegt, daß nur der lange Schnabel hervorschaut; die Ständer
werden weit nach hinten gestreckt, und in dem schönen Federbusch
am Kropf spielt lustig der Wind. Dann läßt sich ein oder der andere
Reiher auf dem Horstrand nieder und füttert die Jungen mit Fischen,
die er ihnen aus weiter Ferne im Kehlsack bringt; denn ein Gewässer
findet sich nicht in der Nähe. Wie ich mit großem Bedauern höre, ist
in den letzten Jahren die Kolonie stark zurückgegangen, vielleicht
ganz verschwunden.
Hannover, Schleswig-Holstein, Pommern, West- und Ostpreußen
beherbergen noch immer eine stattliche Anzahl von Reiherhorsten;
Posen, Schlesien, Brandenburg, die Provinz Sachsen sind schon
ärmer daran. Man sieht, der Reiher bevorzugt im allgemeinen die
Niederungen mit ihren ruhig fließenden oder stehenden Gewässern,
dazu die Meeresküste. Ob das Jagdgebiet mehr oder weniger im
freien Gelände liegt, ob dichtes Gebüsch die Ufer besetzt oder ob
finsterer Wald den See von allen Seiten umgibt, das ist den Reihern
gleich, sobald sich nur seichte Uferstellen finden, wo sie, im flachen
Wasser stehend, dem Fischfang ungestört obliegen können.
Die größte Reiherkolonie habe ich vor ein paar Jahren – es war in
der zweiten Hälfte des Mai – an der deutschen Ostseeküste besucht.
Den Ort verschweige ich; ebenso verrate ich nicht, wieviel besetzte
Horste hier auf den hohen Eichen stehen mögen. Sonst fangen die
pommerschen Boddenfischer, wenn sie's hören, sofort an zu
multiplizieren, erst die Anzahl der Reiherpaare mal zwei bis drei
Dutzend spannenlanger Fische, das Produkt mal 180 – so viele Tage
ungefähr weilt der Reiher an seinem Brutplatz – dann wird dividiert,
nun weiß man die Kilo, und wieder multipliziert – man hört ganz
deutlich die Goldstücke klimpern, die man ohne die Reiher
einheimsen könnte. Aber von dem Schaden, den die Fischer sich
selbst dadurch zufügen, daß auch sie so oft alles kleine
Fischgewürm, das sich in den Netzen gefangen hat, mit zu Gelde
machen, davon wollen die Leute nichts hören.
Wenigstens 20 bis 25 m schätzte ich die Höhe der Horste. Manche
Eiche trug deren fünf oder sechs. Die Alten fütterten eifrigst, viele
brüteten aber auch noch. Die großen Vögel kreisten schreiend über
den Horstbäumen. Ihre riesigen Schatten huschten ganz
eigentümlich zwischen den Eichen, deren Kronen noch ziemlich
unbelaubt waren, dahin. Es sah noch leidlich reinlich im Nistrevier
aus: ein paar Eierschalen, etwas weißer Kot und nur ausnahmsweise
ein verwesender Fisch. Wie anders, wenn man später kommt! Da
muß man in solchem Unrat förmlich waten, wie es mir erging, als ich
vor vielen Jahren einmal im Sommer eine große Reiherkolonie an der
Elbe, unterhalb Wittenberg, besuchte.
An einem der folgenden Tage sollten einige Reiher abgeschossen
werden. Auf höheren Befehl mußte sich der Oberforstmeister dazu
bequemen; denn die Fischer hatten sich schon ein paarmal bei der
Regierung beklagt, daß man hier die Reiher, die doch so
grenzenlosen Schaden anrichten, ruhig gewähren lasse, ja sie
geradezu hege und züchte. »Zwölf Stück, nicht mehr!« so lautete die
strenge Weisung, die der Oberforstmeister uns gab, »und nicht zwei
von demselben Horstbaum abschießen, damit der Überlebende des
Paares die Brut weiter aufzieht, auch peinlich darauf achten, daß
kein Reiher dabei in den Horst fällt, wodurch die Jungen elend
umkommen müssen, also nicht schießen, wenn der Reiher gerade
über seinem Nest schwebt!« Wir hatten das Dutzend schnell
zusammen; denn wenn auch nach jedem Schuß die Vögel
abstreichen, sie kommen doch recht bald wieder, falls man sich nur
ein wenig hinter den Stämmen versteckt. Die Mutterliebe läßt sie die
Gefahr nicht achten.
Die armen zwölf Stück! Für die andern hatten sie das Leben
gelassen – Opfer des Vogelschutzes, so seltsam es klingt. Ein
mäßiger Abschuß war eben unbedingt nötig, um den Klagen der
Fischer etwas gerecht zu werden. Nur auf diese Weise läßt sich die
Brutkolonie dauernd erhalten. Wir banden die prächtigen Tiere,
damit sie von allen Dorfbewohnern gesehen würden, an den
Jagdwagen und fuhren durch ein paar Dörfer mehr, als nötig
gewesen wäre, wieder heimwärts. Schaut, ihr Fischer, wie man
sorgt, daß ihr die Fischräuber los werdet, und haltet den Mund nun!
An unsern sächsischen Teichen, ja sogar an Gebirgsbächen halten
sich die Reiher, namentlich auf ihrer Wanderung, gern auf; es findet
sich überall ein Plätzchen, wo selbst das schnellfließende Wasser
seinen eiligen Lauf unterbricht. Den Hals niedergebogen, den
Schnabel gesenkt, den spähenden Blick auf den Wasserspiegel
gerichtet, so schleichen die schlanken Gestalten mit behutsamem
Tritt am Ufer entlang; sie gehen nur so weit ins Wasser, daß es ihnen
höchstens an die Fersen reicht. Bisweilen verharren sie auch
stundenlang unbeweglich fast auf demselben Fleck. Nur von Zeit zu
Zeit schnellt blitzartig der Hals vor, so daß der Schnabel, oft auch
zugleich der Kopf unter der Wasserfläche verschwindet. Selten nur
geht der Stoß fehl; das Bajonett trifft sein Ziel mit großer Sicherheit.
Der zappelnde Fisch wandert sofort in den unersättlichen Schlund.
Welcome to our website – the ideal destination for book lovers and
knowledge seekers. With a mission to inspire endlessly, we offer a
vast collection of books, ranging from classic literary works to
specialized publications, self-development books, and children's
literature. Each book is a new journey of discovery, expanding
knowledge and enriching the soul of the reade
Our website is not just a platform for buying books, but a bridge
connecting readers to the timeless values of culture and wisdom. With
an elegant, user-friendly interface and an intelligent search system,
we are committed to providing a quick and convenient shopping
experience. Additionally, our special promotions and home delivery
services ensure that you save time and fully enjoy the joy of reading.
ebooknice.com