Hoşgeldin. Soru sormak veya cevaplamak için hemen üye ol.
0 oy
2.9k kez görüntülendi
ios development kategorisinde tarafından
JSON Payload ile gönderdiğim dataları uygulamam içerisinde yakaladıktan sonra belirleyeceğim bir ViewController'in present edilmesini ve bu yakaladığım datayı da ilgili ViewController'de kullanmak istiyorum.

Bu konuda yardımınızı rica edebilir miyim ? Nereden başlamalıyım? Nasıl olmalı ?

1 cevap

+1 oy
tarafından
tarafından seçilmiş
 
En İyi Cevap

bildiginiz gibi apns notification'larını appDelegate içerisindeki didReceiveRemoteNotification metoduyla alıyoruz.

func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
    // payload'a eklediğiniz her key "aps" altında yer alıyor dolayısıyla bunun içine bakmamız lazım
    if let apsPayloadContent:AnyObject = userInfo["aps"] {

        //aps payload'ımızın içerisinde "pid" key'iyle girdiğimiz custom bir içeriğimiz olduğunu farz edelim.
        if let customData:String = apsPayloadContent["pid"] as? String {

            // aldığımız custom içeriğimizi daha sonra bir local notification'la post edelim.
            // ve elbette bir yerlere post edilen bu notification'ı karşılayabilecek bir observer ekleyeceksiniz'ki uygulama notification aldığında yapmak istediğiniz aksiyon tetiklenebilsin.
            NSNotificationCenter.defaultCenter().postNotificationName("remoteNotificationReceived", object: customData)
        }
    }
}

şimdi viewController'içerisinde neler yaptığımıza bir bakalım;

override func viewDidLoad() {
        super.viewDidLoad()    
// örnek vermek gerekirse mainViewController'ımız içerisinde bu local notification'ı karşılayabilecek ve yapmak istediğiniz aksiyonu tetikleyecek bir observer'ekleyelim.
        NSNotificationCenter.defaultCenter().addObserver(self, selector: "remoteNotificationReceiveAction:", name: "remoteNotificationReceived", object: nil)
}


func remoteNotificationReceiveAction(data:NSNotification) {
        // local notification'la post ettiğimiz içeriğimiz string olduğu için burada da string olarak karşılıyoruz.
        if let customData:String = data.object as? String {
            // böylece customData'mızı viewController'içinde yer alan bir metoda transfer ettik, artık bundan sonra yeni bir view veya viewController present etmek istiyorsanız buradan devam edebilirsiniz.
        }
    }
tarafından
Çok teşekkür ederim. AppDelegate içerisinde
NSNotificationCenter.defaultCenter().postNotificationName("remoteNotificationReceived", object: nil, userInfo: userInfo)
 
şeklinde kullanırsam,  viewDidLoad'daki remoteNotificationReceiveAction'da userInfo'yu nasıl okuyabilirim peki ?
tarafından
Sorunu çözdüm:
if let apsPayloadContent: AnyObject = data.userInfo as? AnyObject  {
// burada userInfo ile gelen verileri okuyabildim nihayet :)
}
tarafından
tarafından düzenlendi
Bildirim gelince Present kısmında sorun yaşıyorum:
eğer uygulama açık değilse ve bildirim gelmişse,  bildirime tıklayınca uygulama açılıyor fakat   present edemiyor. Uygulama açıksa present ediyor.

Uygulamamın Root View Controlleri bir splash  view controller:
https://gist.github.com/burhanaksendir/ab01fbe778e519532bff

Bu ekrandan  animasyon bitince Menu ViewControllere geçiyor.


JSON Payload şu şekilde:

{
    "aps": {
         "alert": "Hello World"
    },
    "imageURL": "https://pbs.twimg.com/media/CHyxqhSW8AAJV43.png”
}

AppDelegate ayarlarım şu şekilde:
https://gist.github.com/burhanaksendir/02820df6d0f1c335d6f9

Main View Controller ayarlarım da şu şekilde:
https://gist.github.com/burhanaksendir/2e84877396670533a5ba


Present kısmında yardımınızı rica edebilir miyim ?
tarafından
muhtemelen uygulama açılır açılmaz daha mainViewController initiate edilmeden yani viewDidLoad metodu çağrılmadan appDelegate içerisindeki didReceiveRemoteNotification metodu çağrılıyor olabilir. Bu durumda post edilen notification'ı alabilecek herhangi bir observer henüz set edilmediğiniden remoteNotificationReceiveAction metodu çağrılamıyor olabilir.
initiation sıralamasını log tutarak bir inceleyin.
sıralamanın viewDidLoad, didReceiveRemoteNotification ve remoteNotificationReceiveAction şeklinde olması lazım.
tarafından
Uygulama açıkken  println ile log tutuyorum. Dediğiniz şekilde sıralama oluyor. Ancak uygulama kapalıyken bildirim gönderdiğimde println  yani log nasıl olacak ? Cahilliğimi mazur görün, nasıl log tutacağım bu durumda ?
tarafından
uygulama tamamen kapalıyken yani background mode'da değilken notification'geldiğinde cihazınız usb kablosuyla mac'inize bağlı olsun. xcode içerisinde window menüsünün altında yer alan Devices'ı tıklayın açılan ekranda sol taraftan cihazınızı seçin.
en altta device log alanını göreceksiniz, uygulamanızı gelen notification'la açın ve uygulama log'larını inceleyin.
tarafından
Çok teşekkür ederim. Dediğiniz gibi yaptım. Hiçbir şekilde println ile belirlediğim mesajların hiçbiri gözükmedi. Yani viewDidLoad, didReceiveRemoteNotification ve remoteNotificationReceiveAction içine eklediğim println mesajlarını da göremedim.

Sadece notification'a tıklayınca log alanında bir hata mesajı yakaladım:
<Error>: assertion failed: 12F70: libxpc.dylib .....
tarafından
uygulama çöküyormu?
tarafından
Hayır hiçbir çökme olmuyor. Println ile belirlediğim mesajları görebilmem gerekiyor mu bu log alanında ?
tarafından
aa, evet.
gözden kaçırdığım küçük bir ayrıntı. print veya println değil objective-c'de yaptığımız gibi NSLog kullanın.
tarafından
NSLog ile deneyince  şu şekilde bir log alıyorum:
<Error>: assertion failed: 12F70: libxpc.dylib
iPhone Unknown[1391] <Error>:
<Warning>: viewDidLoad devreye girdi

Yani sadece viewDidload'taki log geliyor. didReceiveRemoteNotification ve remoteNotificationReceiveAction çalışmıyor.

Sizinle basit bir proje üzerinden örnek kodlarımı paylaşsam faydalı olur mu acaba sorunu tanımlayabilmek için ?
tarafından
daha iyi olur.
tarafından
Örnek proje dosyasını paylaşıyorum:
https://drive.google.com/file/d/0B94geQNpqygPbGpGS2pmZ3I2WU0/view

Yardımlarınız için şimdiden çok teşekkür ederim.
tarafından
ahhh tamam şimdi hatırladım, uygulamayı notification'a dokunarak açtığımızda didReceiveRemoteNotification metodu tetiklenmez, bu metod sadece uygulama notificationlar background mode'da çalışabilmesi için seçilmişse veya uygulama o an açıksa çalışır.

uygulamayı notification'laaçtığımızda tamamen farklı bir şey yapıyoruz.
appDelegate metodumuz içerisinde gelen launchOptions'u kullanarak notification payload'ına ulaşmalıyız.





func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        
        // parse initialization...
        
        Parse.setApplicationId("xxxx",
            clientKey: "xxxxx")
        
        // Register notifications settings
        let types = UIUserNotificationType.Badge | UIUserNotificationType.Alert | UIUserNotificationType.Sound
        let settings = UIUserNotificationSettings(forTypes: types, categories: nil)
        application.registerUserNotificationSettings(settings)
        
        if launchOptions != nil {
            if let apnsPayload:NSDictionary = launchOptions?[UIApplicationLaunchOptionsRemoteNotificationKey] as? NSDictionary {
                // apnsPayload'ı local notification'la post edeceğiz.
                // ama burada initiation hiyerarşisi içerisindeki gecikmeden kaynaklı belki bir problem olabilir yine log tutarak sıralamanın doğruluğunu kontrol etmeyi unutma.
            }
        }
        
        return true
    }
tarafından
Sağolun. Peki bu notunuzda yani // apnsPayload'ı local notification'la post edeceğiz.
kısmında ben daha önceki gibi mi post edeceğim:
  NSNotificationCenter.defaultCenter().postNotificationName("remoteNotificationReceived", object: nil, userInfo: apnsPayload as [NSObject : AnyObject])
tarafından
evet, güzel bir soru.

şöyle düzelteyim o zaman.
aynı notification observer'ini kullancaksın.
didReceiveRemoteNotification metodundan aldığın payload'ı [NSObject : AnyObject] olarak post ediyorsun.
ama benim bir önceki örneğimde NSDictionary olarak post ediyorsun
notification observer'inde bir problem yaratırmı tam emin olamıyorum test etmek lazım.
ama sen gel en iyisi biraz önce verdiğim örnekteki NSDictionary downcast'ini [NSObject : AnyObject] yapalım.

yani şöyle;



if launchOptions != nil {
            if let apnsPayload:[NSObject: AnyObject] = launchOptions?[UIApplicationLaunchOptionsRemoteNotificationKey] as? [NSObject: AnyObject] {
                // böyle bir dene bakalım böyle bir problem olmaması lazım.
            }
        }
tarafından
Dediğiniz şekilde yaptım. NSLog ile launchOptions'ta bildirimi gördüm. Ancak present kısmı hiç devreye girmedi. Yani size gönderdiğim projedeki  func remoteNotificationReceiveAction(data: NSNotification) kısmı...
tarafından
+1
dediğim gibi viewController daha initiate olmadan post ediyoruz o yüzden muhtemelen.
notification'ı post etmeyi biraz geciktir aşağıdaki gibi.



if launchOptions != nil {
            if let apnsPayload:[NSObject: AnyObject] = launchOptions?[UIApplicationLaunchOptionsRemoteNotificationKey] as? [NSObject: AnyObject] {
                let delayTime:Double = 2 // gecikme süresi
                dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(delayTime * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) {
                    // notification'ı burada post et
                }
            }
        }
tarafından
Gerçekten inanılmaz mutlu oldum :) Çok teşekkür ederim.  Peki bunun sebebi, benim bir splash screen kullanmamdan mı kaynaklanıyor? Yani bu  gecikme süresi olmadan present etmenin yolu var mıdır sizce ? uygulamamın hiyerarşisi mi bozuk ?
tarafından
yok işleyiş hiyerarşisi bu şekilde ios'un.
önce appDelegate initiate olur daha sonra bir window ve onunu içerisine bir viewController ve en son olarak'da view controller içerisine mainView
bu değiştirilemez bir sıralamadır.
biz daha yolun en başında yani didFinishLaunchingWithOptions içerisinde post etmeye çalışıyoruz. daha ortada bir viewController oluşturulmamışken.
aslında geciktirerek işin kolay yoluna kaçtık biraz.
bir global değişkenle veya appDelagate içerisinde tanımlayacağımız bir değişkene aldığımız payload'ı set edip, daha sonra viewController'da viewDidload metodu içerisinden bu değişkene ulaşarak daha sağlıklı bir yolda izleyebilirdik.
istersen böyle bir yolda izleyebilirsin.
tarafından
Çok teşekkür ederim bilgiler ve yardımlarınız için. İkinci yöntemi tercih ettiğimde, viewDidload içerisinde bu payloadu nasıl kontrol etmem gerekir ?

Yani viewController'de önce bir değişken tanımlarım:
 var remoteNotificationPayload = NSDictionary()

Sonra  appDelegate içerisinde bu viewController'e erişip,  remoteNotificationPayload değişkenime   launchOptions 'deki apnsPayload'ı atarım:?
if let mainVC = window?.rootViewController as? SplashViewController {
            if apnsPayload != nil {
                mainVC.remoteNotificationPayload = apnsPayload
            }
 }

Peki viewController içerisinde bu değişkeni nasıl kontrol edip peresent işlemini yaparım sizce?
tarafından
hayır öyle değil. değişkeni appDelegate içerisinde tanımla.
viewController'da daha tanımlamadığın değişkene appDelegate içerisinden nasıl ulaşacaksın?

öncelikle appDelegate içerisinde bir değişken tanımla

var myPayload:[NSObject: AnyObject]?

daha sonra didFinishLaunchingWithOptions metodunun içerisinde ilk yapılan işlem launcOptions'u almak ve bu değişkene set etmek olsun.


if launchOptions != nil {
            if let apnsPayload:[NSObject: AnyObject] = launchOptions?[UIApplicationLaunchOptionsRemoteNotificationKey] as? [NSObject: AnyObject] {
                self.myPayload = apnsPayload
            }
        }


viewController içerisinde viewDidload metodunda appDelegate bulunan bu değişkeni al.

if let appDelegate = UIApplication.sharedApplication().delegate as? AppDelegate {
            if let payLoad:[NSObject: AnyObject] = appDelegate.myPayload {
                // payload'artık burada
            }
        }


bu sayede viewController oluşturul oluşturulmaz appDelegate içerisindeki myPayload değişkeni eğer bir değer tutuyorsa aksiyonunu gerçekleştirebilirsin.
tarafından
tarafından düzenlendi
Gerçekten çok teşekkür ederim. Son olarak bu addObserver'ı remove etmemiz gerekecek mi ?
tarafından
Notification için eklediğimiz bu addObserver'ı remove etmemiz gerekecek mi ? Gerekiyorsa ne zaman ve nerde ? bilgilendirirseniz çok sevinirim.
tarafından
+1
eğer addObserver'i eklediğin viewController dismiss edilecekse viewwilldisappear metodunda remove edebilirsin.
tarafından
Teşekkür ederim.
...