Using UIActivityIndicator-for-SDWebImage with Swift - ios

I'm using SDWebImage and I would like to add a loading indicator. I found the UIActivityIndicator-for-SDWebImage library, and I have tried to add it to my Swift project by adding this:
#import "UIImageView+UIActivityIndicatorForSDWebImage.h"
to my bridging header. For some reason I still can't access the extra parameter usingActivityIndicatorStyle when setting image URLs.
Anyone have any idea what I'm doing wrong? I've tried removing the .m and .h files and re-adding them, but it didn't help.

Add "use_frameworks!" in the Podfile
use_frameworks!
target '<YOUR TARGET>' do
.........
pod 'UIActivityIndicator-for-SDWebImage'
.........
end
In "Pods -> UIActivityIndicator-for-SDWebImage -> UIImageView+UIActivityIndicatorForSDWebImage.h" replace:
#import "UIImageView+WebCache.h"
#import "SDImageCache.h"
With:
#import <SDWebImage/UIImageView+WebCache.h>
#import <SDWebImage/SDImageCache.h>
In "AppDelegate.swift" add
import UIActivityIndicator_for_SDWebImage
That's all.
P.S. You should correct Pods because author of UIActivityIndicator-for-SDWebImage wrote in description: "... I really don't want to keep this repo updated ...", and he really doesn't do it.

Swift 3 & SDWebImage 4.0.0
This will do the trick, try this code
let urlString = URL(string: "Your image URL")
yourImageView.sd_setIndicatorStyle(.gray)
yourImageView.sd_setShowActivityIndicatorView(true)
yourImageView.sd_setImage(with: urlString) { (loadedImage, error, cacheType, url) in
yourImageView.sd_removeActivityIndicator()
if error != nil {
print("Error code: \(error!.localizedDescription)")
} else {
yourImageView.image = loadedImage
}
}

The answer above works
Follow this issue https://github.com/JJSaccolo/UIActivityIndicator-for-SDWebImage/pull/28
You will find a fork which has made this update
https://github.com/masterfego/UIActivityIndicator-for-SDWebImage
I forked it too,
https://github.com/useeless37/UIActivityIndicator-for-SDWebImage
then in your pod file
pod 'UIActivityIndicator-for-SDWebImage', :git => 'https://github.com/useeless37/UIActivityIndicator-for-SDWebImage.git'

Related

Implement Google Analytics in ios swift

I am following the Analytics for iOS (developers.google.com/analytics/devguides/collection/ios/v3/?ver=swift) guide and I've got errors in my Swift code Project that I can't fix.
I am working with XCode 6.4, Swift and the iOS Deployment Target 8.1.
Step 1
First I installed a Google SDK using CocoaPods.
This is the console result after running pod install command:
Updating local specs repositories
CocoaPods 1.0.0.beta.2 is available.
To update use: `gem install cocoapods --pre`
[!] This is a test version we'd love you to try.
For more information see http://blog.cocoapods.org
and the CHANGELOG for this version http://git.io/BaH8pQ.
Analyzing dependencies
Downloading dependencies
Using Google (1.0.7)
Using GoogleAnalytics (3.14.0)
Using GoogleNetworkingUtilities (1.0.0)
Using GoogleSymbolUtilities (1.0.3)
Using GoogleUtilities (1.1.0)
Generating Pods project
Integrating client project
Sending stats
Pod installation complete! There is 1 dependency from the
Podfile and 5 total pods installed.
Step 2
Then opened, as said in the guide, my app's Project .xcworkspace file.
My Podfile looks like this:
# Uncomment this line to define a global platform for your project
# platform :ios, '8.0'
# Uncomment this line if you're using Swift
# use_frameworks!
target 'XXXXXX' do
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.1'
pod 'Google/Analytics', '~> 1.0.0'
end
target 'XXXXXXTests' do
pod 'Google/Analytics', '~> 1.0.0'
end
Where XXXXXX is my Project's name.
Step 3
I got the configuration file GoogleService-Info.plist and included in my Project adding all the targets (2 targets in my project).
Step 4
I created a BridgingHeader by by choosing File > New > File > iOS > Source > Header File.
I named it BridgingHeader.h and is in the root of my Project.
The content is:
#ifndef XXXXX_BridgingHeader_h
#define XXXXX_BridgingHeader_h
#import "Google/Analytics.h"
#import <Google/Analytics.h>
#include "GAI.h"
#import <CoreData/CoreData.h>
#import <SystemConfiguration/SystemConfiguration.h>
#import "Libraries/GoogleAnalytics/GAI.h"
#import "Libraries/GoogleAnalytics/GAIFields.h"
#import "Libraries/GoogleAnalytics/GAILogger.h"
#import "Libraries/GoogleAnalytics/GAITracker.h"
#import "Libraries/GoogleAnalytics/GAIDictionaryBuilder.h"
#endif
Where "XXXXX" is my Project's name.
Step 5
Now the problems:
I tried to include/import the Google Analytics into my AppDelegate.swift but I can't. This is the error:
AppDelegate.swift import Google Analytics
I also tried import "Google/Analytics.h" but another error appears: Expected identifier in import declaration.
How can I fix this so XCode doesn't give me errors?
Is the BridgingHeader wrong? Do I have to point at this somehow to recognize its inner headers?
Do I have to configure something else for the Google Analytics that I am missing right now?
Thank you very much.
There are two options for implementation with Google Analytics using CocoaPods.
pod 'Google/Analytics'
pod 'GoogleAnalytics'
There are pros and cons between them.
pod 'Google/Analytics'
need google configuration file(GoogleService-Info.plist)
simple bridging header file. Just add #import <Google/Analytics.h> in bridging header file.
add import Googlein every file you want to implement google analytics.
pod 'GoogleAnalytics'
no google configuration file(GoogleService-Info.plist)
more complex bridging header file.
I prefer to use pod 'GoogleAnalytics' but I'll explain how to solve this issue using pod 'Google/Analytics'
because the google official site recommends pod 'Google/Analytics'.
bridging header
You just need one line of code for google analytics.
#import <Google/Analytics.h>
Don't forget to set target-build setting for Objective-C-Bridging-Header.
You have to provide correct path to enable Objective-C-Bridging-Header.
Set Target-Build Setting-Objective-C-Bridging-Header
$(SRCROOT)/$(PRODUCT_NAME)/projectName_Bridging_Header.h
AppDelegate.swift
import Google
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?)
-> Bool { self.setupGoogleAnalytics()
..
self.setupGoogleAnalytics()
..
}
func setupGoogleAnalytics() {
// Configure tracker from GoogleService-Info.plist.
let configureError:NSError?
GGLContext.sharedInstance().configureWithError(&configureError)
assert(configureError == nil, "Error configuring Google services: \(configureError)")
let gai = GAI.sharedInstance()
gai.trackUncaughtExceptions = true // report uncaught exceptions
gai.logger.logLevel = GAILogLevel.Verbose // remove before app release
}
SomeViewController.swift
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(true)
if let default_tracker = GAI.sharedInstance().defaultTracker {
#if DEBUG
print("default tracker")
#endif
}
// let tracker = GAI.sharedInstance().defaultTracker
let tracker = GAI.sharedInstance().trackerWithTrackingId("tracking_ID")
tracker.set(kGAIScreenName, value: screenName)
let builder = GAIDictionaryBuilder.createScreenView()
tracker.send(builder.build() as [NSObject : AnyObject])
}
Why do I use trackerWithTrackingId instead of defaultTracker property? You could got an error if you use defaultTracker :
fatal error: unexpectedly found nil while unwrapping an Optional value
defaultTracker property's initial value is nil, but it will be set after
trackerWithTrackingId method is called. But it doesn't work perfectly sometimes. To avoid this issue, I recommend that use trackerWithTrackingId method directly.
I make the sample project using pod 'GoogleAnalytics'. You can get an idea from it.
Good luck.
Test Env
GoogleAnalytics 3.14
Xcode 7.2.1
In Podfile
pod 'Google/Analytics'
In YourFantasticProjectName-Bridging-Header.h
#import "Google/Analytics.h"
You don't need this
GGLContext.sharedInstance().configureWithError(&configureError)
You need to have a proper tracker
let gai = GAI.sharedInstance()
let tracker = gai.tracker(withTrackingId: "UA-12345678-1")
In order for live view to work in GA dashboard, you must track screen using GAIDictionaryBuilder and correct key kGAIScreenName
tracker.set(kGAIScreenName, value: "this is my screen")
let event = GAIDictionaryBuilder.createScreenView()
tracker?.send(event!.build() as! [NSObject: Any])
In the same vein, to track events, you need to use GAIDictionaryBuilder as it will create dictionary with correct GA keys, and GA likes correct keys
let event = GAIDictionaryBuilder.createEvent(withCategory: "category", action: "action", label: "level", value: NSNumber(value: 120))
tracker?.send(event!.build() as! [NSObject: Any])
It seems to work in the simulator too
I faced the same problem. I could not import the "Google/Analytics.h" header as Xcode generate error. Because "Google/Analytics.h" header is not available in the 'GoogleAnalytics sdk' as mentioned in Google's Official page.
So, i just used following line
#import "GAI.h"
Hope it will work just fine.
Environment
Xcode: 8.2
iOS :10.2
For swift 3:
var configureError:NSError? = nil
GGLContext.sharedInstance().configureWithError(&configureError)
assert(configureError == nil, "Error configuring Google services: \(configureError)")
let gai = GAI.sharedInstance()
gai?.trackUncaughtExceptions = true
gai?.logger.logLevel = GAILogLevel.verbose
I think it's better to send error to crashlytics, but continue executing an app:
func configureGoogleAnalytics() {
var configureError: NSError? = nil
GGLContext.sharedInstance().configureWithError(&configureError)
if configureError != nil {
Crashlytics.sharedInstance().recordError(configureError!)
}
}
Also check this answer for newest way to add analytics.

Failed to recognize AWSDynamoDB with XCode 7.0 Beta, iOS 8.3, and aws-ios-sdk-2.2.0

I am matching guides for using AWSDynamoDB in a test project using Swift 2 in XCode 7.0 Beta. I am required to use that platform instead of the previous stable one and make it work.
I am using the next links:
https://docs.aws.amazon.com/mobile/sdkforios/developerguide/setup.html
http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LoadData_Java.html
Best way to make Amazon AWS DynamoDB queries using Swift?
I already made it work for reading and writing text files and images to an S3 Bucket, but now that I am trying to use DynamoDB service something might be missing.
Here is my Podfile contents:
# Uncomment this line to define a global platform for your project
platform :ios, '8.3'
target 'AWSSDKTest' do
source 'https://github.com/CocoaPods/Specs.git'
pod 'AWSCore'
pod 'AWSAutoScaling'
pod 'AWSCloudWatch'
pod 'AWSDynamoDB'
pod 'AWSEC2'
pod 'AWSElasticLoadBalancing'
pod 'AWSKinesis'
pod 'AWSLambda'
pod 'AWSMachineLearning'
pod 'AWSMobileAnalytics'
pod 'AWSS3'
pod 'AWSSES'
pod 'AWSSimpleDB'
pod 'AWSSNS'
pod 'AWSSQS'
pod 'AWSCognito'
end
target 'AWSSDKTestTests' do
end
I had to delete Podfile.lock and Pods folder, deleted Configuration Sets in Project->Info->Configurations, and installed pods again.
Here is my bridging.h file:
#ifndef AWSSDKTest_bridging_h
#define AWSSDKTest_bridging_h
#endif
#import <AWSCore/AWSCore.h>
#import <AWSS3/AWSS3.h>
#import <AWSDynamoDB/AWSDynamoDB.h>
#import <AWSSQS/AWSSQS.h>
#import <AWSSNS/AWSSNS.h>
#import <AWSCognito/AWSCognito.h>
I downloaded the aws-ios-sdk-2.2.0.zip file, unzipped and added to Frameworks all the AWS frameworks.
I am trying to use AWSDynamoDBModel, here is a swift file for implementing the Upload Sample Items Example for using DynamoDB Mapper:
import Foundation
class Forum : AWSDynamoDBModel, AWSDynamoDBModeling {
var name : String = ""
var category : String = ""
var threads : Int = 0
var messages : Int = 0
var views : Int = 0
// override init!() { super.init() }
required init!(coder: NSCoder!) {
fatalError("init(coder:) has not been implemented")
}
class func dynamoDBTableName() -> String! {
return "Demo"
}
class func hashKeyAttribute() -> String! {
return "email"
}
class func rangeKeyAttribute() -> String! {
return "date"
}
/*
override init(dictionary dictionaryValue: [NSObject : AnyObject]!, error: NSErrorPointer) {
super.init(dictionary: dictionaryValue, error: error)
}
override func isEqual(anObject: AnyObject?) -> Bool {
return super.isEqual(anObject)
}
*/
}
I had to comment the lines that caused error because those might be fixed. The errors mentioned that those functions couldnt be overridden and that super.init couldnt be called inside a root method.
After cleaning and building again, the error is at the class declaration line
class Forum : AWSDynamoDBModel, AWSDynamoDBModeling {
The error says: Use of undeclared type 'AWSDynamoDBModel'
If I try writing other AWSDynamoDB classes they don't appear in the list of suggestions and then cause the same error.
Additionally I want to mention that in the developer's guide setup (first link above) the 4th point of the Getting Started with Swift section says: "Import the AWSCore header in the application delegate":
#import <AWSCore/AWSCore.h>
Than can't be done, only in the bridging.h file which is mentioned in the 2nd point.
My first request of assistance is in fixing the error mentioned and making the project recognize the AWSDynamoDB framework.
Then I request your help for any observation about this merge of different tutorials, also any other online tutorial or guide that is more clear than those mentioned.
In case you are using CocoaPods (0.36) with "use_frameworks!", this answer might solve your problem:
"Normally when you’re importing Objective-C code into Swift, you do so by including the header of the file containing that code in the “Bridging Header” for your project. And that is indeed how you include code from a static library (which your pods used to be.)
But it is not how your import Objective-C code from a Framework. To do that you simply type…
import Framework
…inside your Swift file that’s using the Objective-C class (where “Framework” is the name of the actual Framework containing the class.)"
Source here: http://rogueleaderr.com/post/115372471213/unresolved-identifier-in-swift-when-importing
I think the problem is not related to Xcode7Beta, but the installation process of your project. (My sample DynamoDB project runs fine under Xcode7Beta.)
If you installed the AWS Mobile SDK via cocoapods, you neither have to worry about the bridging file nor need to download aws-ios-sdk-2.2.0.zip file since cocoapods already did everything for you.
My suggestion would be:
clean your project, remove all aws related frameworks, bridging files that you manually added,delete Podfile.lock and Pods folder and AWSSDKTest.xcworkspace file, and the re integrate pods by running "pod install"
Open your project using Xcode 6.4, confirm it can be built and run successfully under Xcode 6.
If everything looks good via Xcode 6, reopen it via Xcode7Beta, If it failed to compile, please post the error output so I can take a look.
Thanks

Ensembles in iOS swift

I would like to use Drew McCormack's Ensembles from github to relieve my current iOS/swift/coredata/iCloud induced headache. All of the Ensembles examples are in Objective-C. I have it as a Framework in my project, but being a weekend coder, I can't extrapolate how to use it from the ObjC example code.
Has anyone seen a How-To for Ensembles using swift?
Adding: I have it as a framework, but how do I set it up and have it start Leeching? The Obj-C way is to
//SetupEnsemble
cloudFileSystem=[[CDEICloudFileSystemalloc] initWithUbiquityContainerIdentifier:#"container"];
ensemble=[[CDEPersistentStoreEnsemblealloc]initWithEnsembleIdentifier:#"MainStore" persistentStoreURL:storeURL
managedObjectModelURL:modelURL
cloudFileSystem:cloudFileSystem]; ensemble.delegate=self;
and then Leech
if(!ensemble.isLeeched){
[ensemble leechPersistentStoreWithCompletion:^(NSError *error) {
if (error) NSLog(#"Could not leech to ensemble: %#", error); }];}
The following steps describe how you add ensembles with the iCloud + Dropbox filesystem to your project:
Add a 'Podfile' to your project with this contents:
target :YOUR_TARGET_NAME do
platform :ios, '7.0'
pod "Ensembles", :git => 'https://github.com/drewmccormack/ensembles.git'
pod "Ensembles/Dropbox", :git => 'https://github.com/drewmccormack/ensembles.git'
link_with 'YOUR_TARGET_NAME'
end
Run 'pod install' from your terminal
Create a ObjC bridging header
Add Ensembles (and other frameworks to the bridging header):
#import <Foundation/Foundation.h>
#import <Ensembles/Ensembles.h>
#import "DropboxSDK.h"
#import "CDEDropboxCloudFileSystem.h"
Happy coding:
var ensemble:CDEPersistentStoreEnsemble?
var ensembleFileSystem:CDECloudFileSystem?
ensembleFileSystem = CDEICloudFileSystem(
ubiquityContainerIdentifier: "SOME_CONTAINER",
relativePathToRootInContainer: "STORE_ROOT_PATH"
)
ensemble = CDEPersistentStoreEnsemble(
ensembleIdentifier: "IDENTIFIER",
persistentStoreURL: "STORE_URL",
persistentStoreOptions:nil,
managedObjectModelURL:"MOM_URL",
cloudFileSystem:ensembleFileSystem,
localDataRootDirectoryURL:"DATA_ROOT_URL"
)
e.leechPersistentStoreWithCompletion({ (error:NSError?) -> Void in
// check for error, etc...
})
If you're a weekend coder I would recommend using Apple's CloudKit. It's all in swift, of course. There are are some good tutorials at: https://videos.raywenderlich.com/courses/45-introduction-to-cloudkit/lessons/1

How to import and use SDWebImage in swift xcode 6.3.1

Im new to Swift and now making a project that includes showing many photos from the web and I understand that I need to use SDWebImage.
I saw related questions here and in other places but all are in Objective-C syntax and not working for me.
What I did till now:
I downloaded the zip from GitHub
Copied SDWebImage folder to my folder
Tried all possible combinations for import
#import <"SDWebImage/UIImageView+WebCache.h">
import SDWebImage/UIImageView+WebCache.h
etc..
Can someone please help me import it
Firstly, you need configure Bridging Header, it is described here at SO. Use the following:
#import <SDWebImage/UIImageView+WebCache.h>
This will import Objective-C code to Swift code
Secondly, just use it, like:
self.imageView.sd_setImageWithURL(self.imageURL)
As far as I understood you already have a Bridging header and only need to organize your imports. Since you copied the source files directly into your project without using cocoapods or Carthage you do the import like this:
#import "UIImageView+WebCache.h"
Swift 3.0 code
import SDWebImage
let url = URL.init(string: "https://vignette3.wikia.nocookie.net/zelda/images/b/b1/Link_%28SSB_3DS_%26_Wii_U%29.png")
imagelogo.sd_setImage(with: url , placeholderImage: nil)
In swift 5.1 simply import the SdWebimage and use extenion
extension UIImageView{
func downloadImage(url : String, placeHolder : UIImage?) throws{
if let url = URL(string: url){
self.sd_imageIndicator?.startAnimatingIndicator()
self.sd_setImage(with: url) { (image, err, type, url) in
if err != nil{
self.sd_imageIndicator?.stopAnimatingIndicator()
print("Failed to download image")
}
self.sd_imageIndicator?.stopAnimatingIndicator()
}
}
}
}
The only way it worked for me (using mac os 10.11.4 and ios 9.3) was this:
download and unpack framework from link: https://github.com/rs/SDWebImage/releases/download/3.6/SDWebImage-3.6.framework.zip:
drag that framework into x-code project and check option: Copy items if needed (In project navigator you should now see suitcase icon containing a folder with .h files)
create new bridging header file: cmd+n -> file -> new -> file... and select "header" template icon
open that file, write line (just above #endif:) #import < SDWebImage/UIImageView+WebCache.h > (this is path of one of header files from framework)
the most important step from #Azat answer above, is to connect the file you just made with project, in build settings:
select project name (blue icon in Project navigator)
select "Build Settings" on your right start to type "Bridging header..." and when you have row containing "Objective-C Bridging header"
press twice in empty field in that row (window pops-up), and drag bridging header file from Project navigator into that window.
hopefully now you can use library methods as: imageView.setImageWithUrl(url, placeholderImage:)

How to send emails in Swift using Mailgun

I have the need to send automatic emails in a Swift project I'm working on. So far my best lead seems to be using Mailgun. (I'm open to better options if anyone has liked something else)
Swift is not listed in the Mailgun API Reference in their documentation, and I didn't see objective-c either. The only article speaking at all about his I've found is this one.
Update
I've been trying to piece together everything and this is where I've gotten so far.
I was able to get Mailgun installed via cocoapods. Using it in Swift has been kinda tricky.
I setup cocoapods with the following pod file:
target 'TestApp' do
pod 'mailgun', '~> 1.0.3'
end
target 'TestAppTests' do
end
With this podfile I was able to run pod install and set up the dependencies. Then I setup an Objective-C-Bridging Header in build settings. I used the following objective-C bridging header.
#ifndef Promises_Promises_Bridging_Header_h
#define Promises_Promises_Bridging_Header_h
#import <mailgun/Mailgun.h>
#import "testMail.h"
#endif
I was getting a linking error for awhile, but I needed to have the project opened via the workspace and I had to go to Product -> Schemes -> Edit Schemes and add the Pods-mailgun to the top of the list and then it would let me build.
Now I want to take advantage of the MailGun API. The docs say to do the following.
Mailgun *mailgun = [Mailgun clientWithDomain:#"samples.mailgun.org" apiKey:#"key-3ax6xnjp29jd6fds4gc373sgvjxteol0"];
[mailgun sendMessageTo:#"Jay Baird <jay.baird#rackspace.com>"
from:#"Excited User <someone#sample.org>"
subject:#"Mailgun is awesome!"
body:#"A unicode snowman for you! ☃"];
I think i am facing exactly the same problem with you. But I am a little confused on how many .h and .m files you have used and what each one contains. I am clueless on obj C so I try to follow you blindly.
Correct me if I am wrong.
• You have one .h bridging header file that contains:
//
// Use this file to import your target's public headers that you would like to expose to Swift.
//
#import "AFNetworking.h"
#import <mailgun/Mailgun.h>
• You have one .m file that contains:
#import <Foundation/Foundation.h>
#import <mailgun/Mailgun.h>
#interface mailTest: NSObject
- (void) sendMail: (NSString*)email;
#end
• And in your Viewcontroller.swift you have (lets say in a button) this:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
#IBAction func myButton(sender: UIButton) {
var test: mailTest = mailTest()
test.sendMail("testemail#testemail.com")
}
}
Is that correct?
There's another option that you could try if you wanted as much as possible to be on the Swift side:
If you don't have a bridging header yet, create a dummy objective-c file (add new file to project). Xcode will ask if you will like to add a header file (this will sort out the header for you automatically)
Add this to your bridging header (providing you already imported mail gun using cocoa pods):
#import "mailgun/Mailgun.h"
Import maligun in your swift class:
import mailgun
Simply use mailgun's API in swift as you would in Objective-C:
#IBAction func sendEmail(_ sender: Any) {
let mailgun = Mailgun.client(withDomain: "samples.mailgun.org", apiKey: "key-3ax6xnjp29jd6fds4gc373sgvjxteol0")
mailgun?.sendMessage(to: "Jay Baird <jay.baird#rackspace.com>", from: "Excited User <someone#sample.org>", subject: "Mailgun is awesome!", body: "A unicode snowman for you! ☃")
}
At this point I've answered my own question. The process isn't too terrible. Install mailgun using cocoapods.
Link the objective-c code that is needed using an objective-c bridging header.
Create an objective c file to house your method that will call the mailgun operation, and use it.
#import <Foundation/Foundation.h>
#import <mailgun/Mailgun.h>
#interface mailTest: NSObject
- (void) sendMail: (NSString*)email;
#end
Then in my swift code I just call:
var test: mailTest = mailTest()
test.sendMail("testemail#testemail.com")
Here is the mailTest header file. I created a .m file that implements the sendMail method and calls the code from the API and it works great. The only other thing that could be challenging is setting up the mailgun account and configuring your domain so that emails can be sent, but that isn't code related.

Resources